Compare commits

..

8 Commits

Author SHA1 Message Date
Mayukha Vadari
7fac09ccc3 fix issues 2026-01-30 12:14:24 -05:00
copilot-swe-agent[bot]
d18a9e2e54 Extract helper function to avoid code duplication and update API-CHANGELOG
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
2026-01-30 15:55:51 +00:00
copilot-swe-agent[bot]
a7abee3c7b Fix includes in Submit_test.cpp
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
2026-01-30 15:29:38 +00:00
copilot-swe-agent[bot]
0affb48188 Fix test to properly construct transaction JSON for sign-and-submit
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
2026-01-30 15:26:10 +00:00
copilot-swe-agent[bot]
c0f1a1f094 Add augmented fields to sign-and-submit mode and create test
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
2026-01-30 15:24:51 +00:00
copilot-swe-agent[bot]
72bf625bfe Initial plan 2026-01-30 15:20:54 +00:00
Ayaz Salikhov
fe9c8d568f chore: Format all cmake files without comments (#6294) 2026-01-29 18:19:32 +00:00
Ayaz Salikhov
a0e09187b9 chore: Add cmake-format pre-commit hook (#6279)
This change adds `cmake-format` as. a pre-commit hook. The style file closely matches that in Clio, and they will be made to be equivalent over time. For now, some files have been excluded, as those need some manual adjustments, which will be done in future changes.
2026-01-29 13:33:24 +00:00
161 changed files with 1558 additions and 21293 deletions

247
.cmake-format.yaml Normal file
View File

@@ -0,0 +1,247 @@
_help_parse: Options affecting listfile parsing
parse:
_help_additional_commands:
- Specify structure for custom cmake functions
additional_commands:
target_protobuf_sources:
pargs:
- target
- prefix
kwargs:
PROTOS: "*"
LANGUAGE: cpp
IMPORT_DIRS: "*"
GENERATE_EXTENSIONS: "*"
PLUGIN: "*"
_help_override_spec:
- Override configurations per-command where available
override_spec: {}
_help_vartags:
- Specify variable tags.
vartags: []
_help_proptags:
- Specify property tags.
proptags: []
_help_format: Options affecting formatting.
format:
_help_disable:
- Disable formatting entirely, making cmake-format a no-op
disable: false
_help_line_width:
- How wide to allow formatted cmake files
line_width: 120
_help_tab_size:
- How many spaces to tab for indent
tab_size: 4
_help_use_tabchars:
- If true, lines are indented using tab characters (utf-8
- 0x09) instead of <tab_size> space characters (utf-8 0x20).
- In cases where the layout would require a fractional tab
- character, the behavior of the fractional indentation is
- governed by <fractional_tab_policy>
use_tabchars: false
_help_fractional_tab_policy:
- If <use_tabchars> is True, then the value of this variable
- indicates how fractional indentions are handled during
- whitespace replacement. If set to 'use-space', fractional
- indentation is left as spaces (utf-8 0x20). If set to
- "`round-up` fractional indentation is replaced with a single"
- tab character (utf-8 0x09) effectively shifting the column
- to the next tabstop
fractional_tab_policy: use-space
_help_max_subgroups_hwrap:
- If an argument group contains more than this many sub-groups
- (parg or kwarg groups) then force it to a vertical layout.
max_subgroups_hwrap: 4
_help_max_pargs_hwrap:
- If a positional argument group contains more than this many
- arguments, then force it to a vertical layout.
max_pargs_hwrap: 5
_help_max_rows_cmdline:
- If a cmdline positional group consumes more than this many
- lines without nesting, then invalidate the layout (and nest)
max_rows_cmdline: 2
_help_separate_ctrl_name_with_space:
- If true, separate flow control names from their parentheses
- with a space
separate_ctrl_name_with_space: true
_help_separate_fn_name_with_space:
- If true, separate function names from parentheses with a
- space
separate_fn_name_with_space: false
_help_dangle_parens:
- If a statement is wrapped to more than one line, than dangle
- the closing parenthesis on its own line.
dangle_parens: false
_help_dangle_align:
- If the trailing parenthesis must be 'dangled' on its on
- "line, then align it to this reference: `prefix`: the start"
- "of the statement, `prefix-indent`: the start of the"
- "statement, plus one indentation level, `child`: align to"
- the column of the arguments
dangle_align: prefix
_help_min_prefix_chars:
- If the statement spelling length (including space and
- parenthesis) is smaller than this amount, then force reject
- nested layouts.
min_prefix_chars: 18
_help_max_prefix_chars:
- If the statement spelling length (including space and
- parenthesis) is larger than the tab width by more than this
- amount, then force reject un-nested layouts.
max_prefix_chars: 10
_help_max_lines_hwrap:
- If a candidate layout is wrapped horizontally but it exceeds
- this many lines, then reject the layout.
max_lines_hwrap: 2
_help_line_ending:
- What style line endings to use in the output.
line_ending: unix
_help_command_case:
- Format command names consistently as 'lower' or 'upper' case
command_case: canonical
_help_keyword_case:
- Format keywords consistently as 'lower' or 'upper' case
keyword_case: unchanged
_help_always_wrap:
- A list of command names which should always be wrapped
always_wrap: []
_help_enable_sort:
- If true, the argument lists which are known to be sortable
- will be sorted lexicographicall
enable_sort: true
_help_autosort:
- If true, the parsers may infer whether or not an argument
- list is sortable (without annotation).
autosort: true
_help_require_valid_layout:
- By default, if cmake-format cannot successfully fit
- everything into the desired linewidth it will apply the
- last, most aggressive attempt that it made. If this flag is
- True, however, cmake-format will print error, exit with non-
- zero status code, and write-out nothing
require_valid_layout: false
_help_layout_passes:
- A dictionary mapping layout nodes to a list of wrap
- decisions. See the documentation for more information.
layout_passes: {}
_help_markup: Options affecting comment reflow and formatting.
markup:
_help_bullet_char:
- What character to use for bulleted lists
bullet_char: "-"
_help_enum_char:
- What character to use as punctuation after numerals in an
- enumerated list
enum_char: .
_help_first_comment_is_literal:
- If comment markup is enabled, don't reflow the first comment
- block in each listfile. Use this to preserve formatting of
- your copyright/license statements.
first_comment_is_literal: false
_help_literal_comment_pattern:
- If comment markup is enabled, don't reflow any comment block
- which matches this (regex) pattern. Default is `None`
- (disabled).
literal_comment_pattern: null
_help_fence_pattern:
- Regular expression to match preformat fences in comments
- default= ``r'^\s*([`~]{3}[`~]*)(.*)$'``
fence_pattern: ^\s*([`~]{3}[`~]*)(.*)$
_help_ruler_pattern:
- Regular expression to match rulers in comments default=
- '``r''^\s*[^\w\s]{3}.*[^\w\s]{3}$''``'
ruler_pattern: ^\s*[^\w\s]{3}.*[^\w\s]{3}$
_help_explicit_trailing_pattern:
- If a comment line matches starts with this pattern then it
- is explicitly a trailing comment for the preceding
- argument. Default is '#<'
explicit_trailing_pattern: "#<"
_help_hashruler_min_length:
- If a comment line starts with at least this many consecutive
- hash characters, then don't lstrip() them off. This allows
- for lazy hash rulers where the first hash char is not
- separated by space
hashruler_min_length: 10
_help_canonicalize_hashrulers:
- If true, then insert a space between the first hash char and
- remaining hash chars in a hash ruler, and normalize its
- length to fill the column
canonicalize_hashrulers: true
_help_enable_markup:
- enable comment markup parsing and reflow
enable_markup: false
_help_lint: Options affecting the linter
lint:
_help_disabled_codes:
- a list of lint codes to disable
disabled_codes: []
_help_function_pattern:
- regular expression pattern describing valid function names
function_pattern: "[0-9a-z_]+"
_help_macro_pattern:
- regular expression pattern describing valid macro names
macro_pattern: "[0-9A-Z_]+"
_help_global_var_pattern:
- regular expression pattern describing valid names for
- variables with global (cache) scope
global_var_pattern: "[A-Z][0-9A-Z_]+"
_help_internal_var_pattern:
- regular expression pattern describing valid names for
- variables with global scope (but internal semantic)
internal_var_pattern: _[A-Z][0-9A-Z_]+
_help_local_var_pattern:
- regular expression pattern describing valid names for
- variables with local scope
local_var_pattern: "[a-z][a-z0-9_]+"
_help_private_var_pattern:
- regular expression pattern describing valid names for
- privatedirectory variables
private_var_pattern: _[0-9a-z_]+
_help_public_var_pattern:
- regular expression pattern describing valid names for public
- directory variables
public_var_pattern: "[A-Z][0-9A-Z_]+"
_help_argument_var_pattern:
- regular expression pattern describing valid names for
- function/macro arguments and loop variables.
argument_var_pattern: "[a-z][a-z0-9_]+"
_help_keyword_pattern:
- regular expression pattern describing valid names for
- keywords used in functions or macros
keyword_pattern: "[A-Z][0-9A-Z_]+"
_help_max_conditionals_custom_parser:
- In the heuristic for C0201, how many conditionals to match
- within a loop in before considering the loop a parser.
max_conditionals_custom_parser: 2
_help_min_statement_spacing:
- Require at least this many newlines between statements
min_statement_spacing: 1
_help_max_statement_spacing:
- Require no more than this many newlines between statements
max_statement_spacing: 2
max_returns: 6
max_branches: 12
max_arguments: 5
max_localvars: 15
max_statements: 50
_help_encode: Options affecting file encoding
encode:
_help_emit_byteorder_mark:
- If true, emit the unicode byte-order mark (BOM) at the start
- of the file
emit_byteorder_mark: false
_help_input_encoding:
- Specify the encoding of the input file. Defaults to utf-8
input_encoding: utf-8
_help_output_encoding:
- Specify the encoding of the output file. Defaults to utf-8.
- Note that cmake only claims to support utf-8 so be careful
- when using anything else
output_encoding: utf-8
_help_misc: Miscellaneous configurations options.
misc:
_help_per_command:
- A dictionary containing any per-command configuration
- overrides. Currently only `command_case` is supported.
per_command: {}

View File

@@ -101,6 +101,7 @@ words:
- gpgcheck
- gpgkey
- hotwallet
- hwrap
- ifndef
- inequation
- insuf
@@ -114,6 +115,8 @@ words:
- keylet
- keylets
- keyvadb
- kwarg
- kwargs
- ledgerentry
- ledgerhash
- ledgerindex
@@ -163,6 +166,7 @@ words:
- nunl
- Nyffenegger
- ostr
- pargs
- partitioner
- paychan
- paychans
@@ -268,7 +272,6 @@ words:
- venv
- vfalco
- vinnie
- wasmi
- wextra
- wptr
- writeme

6
.github/CODEOWNERS vendored
View File

@@ -1,2 +1,8 @@
# Allow anyone to review any change by default.
*
# Require the rpc-reviewers team to review changes to the rpc code.
include/xrpl/protocol/ @xrplf/rpc-reviewers
src/libxrpl/protocol/ @xrplf/rpc-reviewers
src/xrpld/rpc/ @xrplf/rpc-reviewers
src/xrpld/app/misc/ @xrplf/rpc-reviewers

View File

@@ -26,6 +26,12 @@ repos:
args: [--style=file]
"types_or": [c++, c, proto]
- repo: https://github.com/cheshirekow/cmake-format-precommit
rev: e2c2116d86a80e72e7146a06e68b7c228afc6319 # frozen: v0.6.13
hooks:
- id: cmake-format
additional_dependencies: [PyYAML]
- repo: https://github.com/rbubley/mirrors-prettier
rev: 5ba47274f9b181bce26a5150a725577f3c336011 # frozen: v3.6.2
hooks:

View File

@@ -83,6 +83,12 @@ The [commandline](https://xrpl.org/docs/references/http-websocket-apis/api-conve
The `network_id` field was added in the `server_info` response in version 1.5.0 (2019), but it is not returned in [reporting mode](https://xrpl.org/rippled-server-modes.html#reporting-mode). However, use of reporting mode is now discouraged, in favor of using [Clio](https://github.com/XRPLF/clio) instead.
## Unreleased Changes
### Additions and bugfixes
- `submit`: Augmented response fields (`accepted`, `applied`, `broadcast`, `queued`, `kept`, `account_sequence_next`, `account_sequence_available`, `open_ledger_cost`, `validated_ledger_index`) are now included in sign-and-submit mode. Previously, these fields were only returned when submitting a binary transaction blob. ([#6304](https://github.com/XRPLF/rippled/pull/6304))
## XRP Ledger server version 2.5.0
As of 2025-04-04, version 2.5.0 is in development. You can use a pre-release version by building from source or [using the `nightly` package](https://xrpl.org/docs/infrastructure/installation/install-rippled-on-ubuntu).

View File

@@ -1,16 +1,16 @@
cmake_minimum_required(VERSION 3.16)
if(POLICY CMP0074)
cmake_policy(SET CMP0074 NEW)
endif()
if(POLICY CMP0077)
cmake_policy(SET CMP0077 NEW)
endif()
if (POLICY CMP0074)
cmake_policy(SET CMP0074 NEW)
endif ()
if (POLICY CMP0077)
cmake_policy(SET CMP0077 NEW)
endif ()
# Fix "unrecognized escape" issues when passing CMAKE_MODULE_PATH on Windows.
if(DEFINED CMAKE_MODULE_PATH)
file(TO_CMAKE_PATH "${CMAKE_MODULE_PATH}" CMAKE_MODULE_PATH)
endif()
if (DEFINED CMAKE_MODULE_PATH)
file(TO_CMAKE_PATH "${CMAKE_MODULE_PATH}" CMAKE_MODULE_PATH)
endif ()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
project(xrpl)
@@ -20,65 +20,65 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(CompilationEnv)
if(is_gcc)
if (is_gcc)
# GCC-specific fixes
add_compile_options(-Wno-unknown-pragmas -Wno-subobject-linkage)
# -Wno-subobject-linkage can be removed when we upgrade GCC version to at least 13.3
elseif(is_clang)
elseif (is_clang)
# Clang-specific fixes
add_compile_options(-Wno-unknown-warning-option) # Ignore unknown warning options
elseif(is_msvc)
elseif (is_msvc)
# MSVC-specific fixes
add_compile_options(/wd4068) # Ignore unknown pragmas
endif()
endif ()
# Enable ccache to speed up builds.
include(Ccache)
# make GIT_COMMIT_HASH define available to all sources
find_package(Git)
if(Git_FOUND)
if (Git_FOUND)
execute_process(COMMAND ${GIT_EXECUTABLE} --git-dir=${CMAKE_CURRENT_SOURCE_DIR}/.git rev-parse HEAD
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE gch)
if(gch)
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE gch)
if (gch)
set(GIT_COMMIT_HASH "${gch}")
message(STATUS gch: ${GIT_COMMIT_HASH})
add_definitions(-DGIT_COMMIT_HASH="${GIT_COMMIT_HASH}")
endif()
endif ()
execute_process(COMMAND ${GIT_EXECUTABLE} --git-dir=${CMAKE_CURRENT_SOURCE_DIR}/.git rev-parse --abbrev-ref HEAD
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE gb)
if(gb)
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE gb)
if (gb)
set(GIT_BRANCH "${gb}")
message(STATUS gb: ${GIT_BRANCH})
add_definitions(-DGIT_BRANCH="${GIT_BRANCH}")
endif()
endif() #git
endif ()
endif () # git
if(thread_safety_analysis)
add_compile_options(-Wthread-safety -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS -DXRPL_ENABLE_THREAD_SAFETY_ANNOTATIONS)
add_compile_options("-stdlib=libc++")
add_link_options("-stdlib=libc++")
endif()
if (thread_safety_analysis)
add_compile_options(-Wthread-safety -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
-DXRPL_ENABLE_THREAD_SAFETY_ANNOTATIONS)
add_compile_options("-stdlib=libc++")
add_link_options("-stdlib=libc++")
endif ()
include (CheckCXXCompilerFlag)
include (FetchContent)
include (ExternalProject)
include (CMakeFuncs) # must come *after* ExternalProject b/c it overrides one function in EP
include(CheckCXXCompilerFlag)
include(FetchContent)
include(ExternalProject)
include(CMakeFuncs) # must come *after* ExternalProject b/c it overrides one function in EP
if (target)
message (FATAL_ERROR "The target option has been removed - use native cmake options to control build")
message(FATAL_ERROR "The target option has been removed - use native cmake options to control build")
endif ()
include(XrplSanity)
include(XrplVersion)
include(XrplSettings)
# this check has to remain in the top-level cmake
# because of the early return statement
# this check has to remain in the top-level cmake because of the early return statement
if (packages_only)
if (NOT TARGET rpm)
message (FATAL_ERROR "packages_only requested, but targets were not created - is docker installed?")
endif()
return ()
if (NOT TARGET rpm)
message(FATAL_ERROR "packages_only requested, but targets were not created - is docker installed?")
endif ()
return()
endif ()
include(XrplCompiler)
include(XrplSanitizers)
@@ -86,11 +86,9 @@ include(XrplInterface)
option(only_docs "Include only the docs target?" FALSE)
include(XrplDocs)
if(only_docs)
return()
endif()
###
if (only_docs)
return()
endif ()
include(deps/Boost)
@@ -105,48 +103,45 @@ find_package(OpenSSL REQUIRED)
find_package(secp256k1 REQUIRED)
find_package(SOCI REQUIRED)
find_package(SQLite3 REQUIRED)
find_package(wasmi REQUIRED)
find_package(xxHash REQUIRED)
target_link_libraries(xrpl_libs INTERFACE
ed25519::ed25519
lz4::lz4
OpenSSL::Crypto
OpenSSL::SSL
secp256k1::secp256k1
soci::soci
SQLite::SQLite3
)
target_link_libraries(
xrpl_libs
INTERFACE ed25519::ed25519
lz4::lz4
OpenSSL::Crypto
OpenSSL::SSL
secp256k1::secp256k1
soci::soci
SQLite::SQLite3)
option(rocksdb "Enable RocksDB" ON)
if(rocksdb)
if (rocksdb)
find_package(RocksDB REQUIRED)
set_target_properties(RocksDB::rocksdb PROPERTIES
INTERFACE_COMPILE_DEFINITIONS XRPL_ROCKSDB_AVAILABLE=1
)
set_target_properties(RocksDB::rocksdb PROPERTIES INTERFACE_COMPILE_DEFINITIONS XRPL_ROCKSDB_AVAILABLE=1)
target_link_libraries(xrpl_libs INTERFACE RocksDB::rocksdb)
endif()
endif ()
# Work around changes to Conan recipe for now.
if(TARGET nudb::core)
set(nudb nudb::core)
elseif(TARGET NuDB::nudb)
set(nudb NuDB::nudb)
else()
message(FATAL_ERROR "unknown nudb target")
endif()
if (TARGET nudb::core)
set(nudb nudb::core)
elseif (TARGET NuDB::nudb)
set(nudb NuDB::nudb)
else ()
message(FATAL_ERROR "unknown nudb target")
endif ()
target_link_libraries(xrpl_libs INTERFACE ${nudb})
if(coverage)
include(XrplCov)
endif()
if (coverage)
include(XrplCov)
endif ()
set(PROJECT_EXPORT_SET XrplExports)
include(XrplCore)
include(XrplInstall)
include(XrplValidatorKeys)
if(tests)
include(CTest)
add_subdirectory(src/tests/libxrpl)
endif()
if (tests)
include(CTest)
add_subdirectory(src/tests/libxrpl)
endif ()

View File

@@ -1290,39 +1290,6 @@
# Example:
# owner_reserve = 2000000 # 2 XRP
#
# extension_compute_limit = <gas>
#
# The extension compute limit is the maximum amount of gas that can be
# consumed by a single transaction. The gas limit is used to prevent
# transactions from consuming too many resources.
#
# If this parameter is unspecified, xrpld will use an internal
# default. Don't change this without understanding the consequences.
#
# Example:
# extension_compute_limit = 1000000 # 1 million gas
#
# extension_size_limit = <bytes>
#
# The extension size limit is the maximum size of a WASM extension in
# bytes. The size limit is used to prevent extensions from consuming
# too many resources.
#
# If this parameter is unspecified, xrpld will use an internal
# default. Don't change this without understanding the consequences.
#
# Example:
# extension_size_limit = 100000 # 100 kb
#
# gas_price = <bytes>
#
# The gas price is the conversion between WASM gas and its price in drops.
#
# If this parameter is unspecified, xrpld will use an internal
# default. Don't change this without understanding the consequences.
#
# Example:
# gas_price = 1000000 # 1 drop per gas
#-------------------------------------------------------------------------------
#
# 9. Misc Settings

View File

@@ -1,30 +1,29 @@
macro (exclude_from_default target_)
set_target_properties (${target_} PROPERTIES EXCLUDE_FROM_ALL ON)
set_target_properties (${target_} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD ON)
set_target_properties(${target_} PROPERTIES EXCLUDE_FROM_ALL ON)
set_target_properties(${target_} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD ON)
endmacro ()
macro (exclude_if_included target_)
get_directory_property(has_parent PARENT_DIRECTORY)
if (has_parent)
exclude_from_default (${target_})
endif ()
get_directory_property(has_parent PARENT_DIRECTORY)
if (has_parent)
exclude_from_default(${target_})
endif ()
endmacro ()
find_package(Git)
function (git_branch branch_val)
if (NOT GIT_FOUND)
return ()
endif ()
set (_branch "")
execute_process (COMMAND ${GIT_EXECUTABLE} "rev-parse" "--abbrev-ref" "HEAD"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE _git_exit_code
OUTPUT_VARIABLE _temp_branch
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET)
if (_git_exit_code EQUAL 0)
set (_branch ${_temp_branch})
endif ()
set (${branch_val} "${_branch}" PARENT_SCOPE)
if (NOT GIT_FOUND)
return()
endif ()
set(_branch "")
execute_process(COMMAND ${GIT_EXECUTABLE} "rev-parse" "--abbrev-ref" "HEAD"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE _git_exit_code
OUTPUT_VARIABLE _temp_branch
OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET)
if (_git_exit_code EQUAL 0)
set(_branch ${_temp_branch})
endif ()
set(${branch_val} "${_branch}" PARENT_SCOPE)
endfunction ()

View File

@@ -15,18 +15,17 @@ endif ()
# https://github.com/ccache/ccache/wiki/MS-Visual-Studio#usage-with-cmake.
if ("${CCACHE_PATH}" MATCHES "chocolatey")
message(DEBUG "Ccache path: ${CCACHE_PATH}")
# Chocolatey uses a shim executable that we cannot use directly, in which
# case we have to find the executable it points to. If we cannot find the
# target executable then we cannot use ccache.
# Chocolatey uses a shim executable that we cannot use directly, in which case we have to find the executable it
# points to. If we cannot find the target executable then we cannot use ccache.
find_program(BASH_PATH "bash")
if (NOT BASH_PATH)
message(WARNING "Could not find bash.")
return()
endif ()
execute_process(
COMMAND bash -c "export LC_ALL='en_US.UTF-8'; ${CCACHE_PATH} --shimgen-noop | grep -oP 'path to executable: \\K.+' | head -c -1"
OUTPUT_VARIABLE CCACHE_PATH)
execute_process(COMMAND bash -c
"export LC_ALL='en_US.UTF-8'; ${CCACHE_PATH} --shimgen-noop | grep -oP 'path to executable: \\K.+' | head -c -1"
OUTPUT_VARIABLE CCACHE_PATH)
if (NOT CCACHE_PATH)
message(WARNING "Could not find ccache target.")
@@ -37,21 +36,14 @@ endif ()
message(STATUS "Found ccache: ${CCACHE_PATH}")
# Tell cmake to use ccache for compiling with Visual Studio.
file(COPY_FILE
${CCACHE_PATH} ${CMAKE_BINARY_DIR}/cl.exe
ONLY_IF_DIFFERENT)
set(CMAKE_VS_GLOBALS
"CLToolExe=cl.exe"
"CLToolPath=${CMAKE_BINARY_DIR}"
"TrackFileAccess=false"
"UseMultiToolTask=true")
file(COPY_FILE ${CCACHE_PATH} ${CMAKE_BINARY_DIR}/cl.exe ONLY_IF_DIFFERENT)
set(CMAKE_VS_GLOBALS "CLToolExe=cl.exe" "CLToolPath=${CMAKE_BINARY_DIR}" "TrackFileAccess=false"
"UseMultiToolTask=true")
# By default Visual Studio generators will use /Zi to capture debug information,
# which is not compatible with ccache, so tell it to use /Z7 instead.
# By default Visual Studio generators will use /Zi to capture debug information, which is not compatible with ccache, so
# tell it to use /Z7 instead.
if (MSVC)
foreach (var_
CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE)
string (REPLACE "/Zi" "/Z7" ${var_} "${${var_}}")
foreach (var_ CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE)
string(REPLACE "/Zi" "/Z7" ${var_} "${${var_}}")
endforeach ()
endif ()

View File

@@ -172,51 +172,47 @@ include(CMakeParseArguments)
option(CODE_COVERAGE_VERBOSE "Verbose information" FALSE)
# Check prereqs
find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
find_program(GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
if(DEFINED CODE_COVERAGE_GCOV_TOOL)
set(GCOV_TOOL "${CODE_COVERAGE_GCOV_TOOL}")
elseif(DEFINED ENV{CODE_COVERAGE_GCOV_TOOL})
set(GCOV_TOOL "$ENV{CODE_COVERAGE_GCOV_TOOL}")
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
if(APPLE)
execute_process( COMMAND xcrun -f llvm-cov
OUTPUT_VARIABLE LLVMCOV_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
else()
find_program( LLVMCOV_PATH llvm-cov )
endif()
if(LLVMCOV_PATH)
set(GCOV_TOOL "${LLVMCOV_PATH} gcov")
endif()
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
find_program( GCOV_PATH gcov )
set(GCOV_TOOL "${GCOV_PATH}")
endif()
if (DEFINED CODE_COVERAGE_GCOV_TOOL)
set(GCOV_TOOL "${CODE_COVERAGE_GCOV_TOOL}")
elseif (DEFINED ENV{CODE_COVERAGE_GCOV_TOOL})
set(GCOV_TOOL "$ENV{CODE_COVERAGE_GCOV_TOOL}")
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
if (APPLE)
execute_process(COMMAND xcrun -f llvm-cov OUTPUT_VARIABLE LLVMCOV_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
else ()
find_program(LLVMCOV_PATH llvm-cov)
endif ()
if (LLVMCOV_PATH)
set(GCOV_TOOL "${LLVMCOV_PATH} gcov")
endif ()
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
find_program(GCOV_PATH gcov)
set(GCOV_TOOL "${GCOV_PATH}")
endif ()
# Check supported compiler (Clang, GNU and Flang)
get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach(LANG ${LANGUAGES})
if("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
if("${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS 3)
message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
endif()
elseif(NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU"
AND NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(LLVM)?[Ff]lang")
message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...")
endif()
endforeach()
foreach (LANG ${LANGUAGES})
if ("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
if ("${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS 3)
message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
endif ()
elseif (NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU" AND NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES
"(LLVM)?[Ff]lang")
message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...")
endif ()
endforeach ()
set(COVERAGE_COMPILER_FLAGS "-g --coverage"
CACHE INTERNAL "")
set(COVERAGE_COMPILER_FLAGS "-g --coverage" CACHE INTERNAL "")
set(COVERAGE_CXX_COMPILER_FLAGS "")
set(COVERAGE_C_COMPILER_FLAGS "")
set(COVERAGE_CXX_LINKER_FLAGS "")
set(COVERAGE_C_LINKER_FLAGS "")
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
if (CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
include(CheckCXXCompilerFlag)
include(CheckCCompilerFlag)
include(CheckLinkerFlag)
@@ -227,51 +223,51 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
set(COVERAGE_C_LINKER_FLAGS ${COVERAGE_COMPILER_FLAGS})
check_cxx_compiler_flag(-fprofile-abs-path HAVE_cxx_fprofile_abs_path)
if(HAVE_cxx_fprofile_abs_path)
if (HAVE_cxx_fprofile_abs_path)
set(COVERAGE_CXX_COMPILER_FLAGS "${COVERAGE_CXX_COMPILER_FLAGS} -fprofile-abs-path")
endif()
endif ()
check_c_compiler_flag(-fprofile-abs-path HAVE_c_fprofile_abs_path)
if(HAVE_c_fprofile_abs_path)
if (HAVE_c_fprofile_abs_path)
set(COVERAGE_C_COMPILER_FLAGS "${COVERAGE_C_COMPILER_FLAGS} -fprofile-abs-path")
endif()
endif ()
check_linker_flag(CXX -fprofile-abs-path HAVE_cxx_linker_fprofile_abs_path)
if(HAVE_cxx_linker_fprofile_abs_path)
if (HAVE_cxx_linker_fprofile_abs_path)
set(COVERAGE_CXX_LINKER_FLAGS "${COVERAGE_CXX_LINKER_FLAGS} -fprofile-abs-path")
endif()
endif ()
check_linker_flag(C -fprofile-abs-path HAVE_c_linker_fprofile_abs_path)
if(HAVE_c_linker_fprofile_abs_path)
if (HAVE_c_linker_fprofile_abs_path)
set(COVERAGE_C_LINKER_FLAGS "${COVERAGE_C_LINKER_FLAGS} -fprofile-abs-path")
endif()
endif ()
check_cxx_compiler_flag(-fprofile-update=atomic HAVE_cxx_fprofile_update)
if(HAVE_cxx_fprofile_update)
if (HAVE_cxx_fprofile_update)
set(COVERAGE_CXX_COMPILER_FLAGS "${COVERAGE_CXX_COMPILER_FLAGS} -fprofile-update=atomic")
endif()
endif ()
check_c_compiler_flag(-fprofile-update=atomic HAVE_c_fprofile_update)
if(HAVE_c_fprofile_update)
if (HAVE_c_fprofile_update)
set(COVERAGE_C_COMPILER_FLAGS "${COVERAGE_C_COMPILER_FLAGS} -fprofile-update=atomic")
endif()
endif ()
check_linker_flag(CXX -fprofile-update=atomic HAVE_cxx_linker_fprofile_update)
if(HAVE_cxx_linker_fprofile_update)
if (HAVE_cxx_linker_fprofile_update)
set(COVERAGE_CXX_LINKER_FLAGS "${COVERAGE_CXX_LINKER_FLAGS} -fprofile-update=atomic")
endif()
endif ()
check_linker_flag(C -fprofile-update=atomic HAVE_c_linker_fprofile_update)
if(HAVE_c_linker_fprofile_update)
if (HAVE_c_linker_fprofile_update)
set(COVERAGE_C_LINKER_FLAGS "${COVERAGE_C_LINKER_FLAGS} -fprofile-update=atomic")
endif()
endif ()
endif()
endif ()
get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG))
if (NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG))
message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
endif() # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)
endif () # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)
# Defines a target for running and collection code coverage information
# Builds dependencies, runs the given executable and outputs reports.
@@ -295,193 +291,186 @@ endif() # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)
# )
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
# GCVOR command.
function(setup_target_for_coverage_gcovr)
function (setup_target_for_coverage_gcovr)
set(options NONE)
set(oneValueArgs BASE_DIRECTORY NAME FORMAT)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT GCOV_TOOL)
if (NOT GCOV_TOOL)
message(FATAL_ERROR "Could not find gcov or llvm-cov tool! Aborting...")
endif()
endif ()
if(NOT GCOVR_PATH)
if (NOT GCOVR_PATH)
message(FATAL_ERROR "Could not find gcovr tool! Aborting...")
endif()
endif ()
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(DEFINED Coverage_BASE_DIRECTORY)
if (DEFINED Coverage_BASE_DIRECTORY)
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
else ()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif()
endif ()
if(NOT DEFINED Coverage_FORMAT)
if (NOT DEFINED Coverage_FORMAT)
set(Coverage_FORMAT xml)
endif()
endif ()
if(NOT DEFINED Coverage_EXECUTABLE AND DEFINED Coverage_EXECUTABLE_ARGS)
if (NOT DEFINED Coverage_EXECUTABLE AND DEFINED Coverage_EXECUTABLE_ARGS)
message(FATAL_ERROR "EXECUTABLE_ARGS must not be set if EXECUTABLE is not set")
endif()
endif ()
if("--output" IN_LIST GCOVR_ADDITIONAL_ARGS)
if ("--output" IN_LIST GCOVR_ADDITIONAL_ARGS)
message(FATAL_ERROR "Unsupported --output option detected in GCOVR_ADDITIONAL_ARGS! Aborting...")
else()
if((Coverage_FORMAT STREQUAL "html-details")
OR (Coverage_FORMAT STREQUAL "html-nested"))
else ()
if ((Coverage_FORMAT STREQUAL "html-details") OR (Coverage_FORMAT STREQUAL "html-nested"))
set(GCOVR_OUTPUT_FILE ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html)
set(GCOVR_CREATE_FOLDER ${PROJECT_BINARY_DIR}/${Coverage_NAME})
elseif(Coverage_FORMAT STREQUAL "html-single")
elseif (Coverage_FORMAT STREQUAL "html-single")
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.html)
elseif((Coverage_FORMAT STREQUAL "json-summary")
OR (Coverage_FORMAT STREQUAL "json-details")
OR (Coverage_FORMAT STREQUAL "coveralls"))
elseif ((Coverage_FORMAT STREQUAL "json-summary") OR (Coverage_FORMAT STREQUAL "json-details")
OR (Coverage_FORMAT STREQUAL "coveralls"))
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.json)
elseif(Coverage_FORMAT STREQUAL "txt")
elseif (Coverage_FORMAT STREQUAL "txt")
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.txt)
elseif(Coverage_FORMAT STREQUAL "csv")
elseif (Coverage_FORMAT STREQUAL "csv")
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.csv)
elseif(Coverage_FORMAT STREQUAL "lcov")
elseif (Coverage_FORMAT STREQUAL "lcov")
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.lcov)
else()
else ()
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.xml)
endif()
endif()
endif ()
endif ()
if((Coverage_FORMAT STREQUAL "cobertura")
OR (Coverage_FORMAT STREQUAL "xml"))
list(APPEND GCOVR_ADDITIONAL_ARGS --cobertura "${GCOVR_OUTPUT_FILE}" )
list(APPEND GCOVR_ADDITIONAL_ARGS --cobertura-pretty )
if ((Coverage_FORMAT STREQUAL "cobertura") OR (Coverage_FORMAT STREQUAL "xml"))
list(APPEND GCOVR_ADDITIONAL_ARGS --cobertura "${GCOVR_OUTPUT_FILE}")
list(APPEND GCOVR_ADDITIONAL_ARGS --cobertura-pretty)
set(Coverage_FORMAT cobertura) # overwrite xml
elseif(Coverage_FORMAT STREQUAL "sonarqube")
list(APPEND GCOVR_ADDITIONAL_ARGS --sonarqube "${GCOVR_OUTPUT_FILE}" )
elseif(Coverage_FORMAT STREQUAL "jacoco")
list(APPEND GCOVR_ADDITIONAL_ARGS --jacoco "${GCOVR_OUTPUT_FILE}" )
list(APPEND GCOVR_ADDITIONAL_ARGS --jacoco-pretty )
elseif(Coverage_FORMAT STREQUAL "clover")
list(APPEND GCOVR_ADDITIONAL_ARGS --clover "${GCOVR_OUTPUT_FILE}" )
list(APPEND GCOVR_ADDITIONAL_ARGS --clover-pretty )
elseif(Coverage_FORMAT STREQUAL "lcov")
list(APPEND GCOVR_ADDITIONAL_ARGS --lcov "${GCOVR_OUTPUT_FILE}" )
elseif(Coverage_FORMAT STREQUAL "json-summary")
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary "${GCOVR_OUTPUT_FILE}" )
elseif (Coverage_FORMAT STREQUAL "sonarqube")
list(APPEND GCOVR_ADDITIONAL_ARGS --sonarqube "${GCOVR_OUTPUT_FILE}")
elseif (Coverage_FORMAT STREQUAL "jacoco")
list(APPEND GCOVR_ADDITIONAL_ARGS --jacoco "${GCOVR_OUTPUT_FILE}")
list(APPEND GCOVR_ADDITIONAL_ARGS --jacoco-pretty)
elseif (Coverage_FORMAT STREQUAL "clover")
list(APPEND GCOVR_ADDITIONAL_ARGS --clover "${GCOVR_OUTPUT_FILE}")
list(APPEND GCOVR_ADDITIONAL_ARGS --clover-pretty)
elseif (Coverage_FORMAT STREQUAL "lcov")
list(APPEND GCOVR_ADDITIONAL_ARGS --lcov "${GCOVR_OUTPUT_FILE}")
elseif (Coverage_FORMAT STREQUAL "json-summary")
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary "${GCOVR_OUTPUT_FILE}")
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary-pretty)
elseif(Coverage_FORMAT STREQUAL "json-details")
list(APPEND GCOVR_ADDITIONAL_ARGS --json "${GCOVR_OUTPUT_FILE}" )
elseif (Coverage_FORMAT STREQUAL "json-details")
list(APPEND GCOVR_ADDITIONAL_ARGS --json "${GCOVR_OUTPUT_FILE}")
list(APPEND GCOVR_ADDITIONAL_ARGS --json-pretty)
elseif(Coverage_FORMAT STREQUAL "coveralls")
list(APPEND GCOVR_ADDITIONAL_ARGS --coveralls "${GCOVR_OUTPUT_FILE}" )
elseif (Coverage_FORMAT STREQUAL "coveralls")
list(APPEND GCOVR_ADDITIONAL_ARGS --coveralls "${GCOVR_OUTPUT_FILE}")
list(APPEND GCOVR_ADDITIONAL_ARGS --coveralls-pretty)
elseif(Coverage_FORMAT STREQUAL "csv")
list(APPEND GCOVR_ADDITIONAL_ARGS --csv "${GCOVR_OUTPUT_FILE}" )
elseif(Coverage_FORMAT STREQUAL "txt")
list(APPEND GCOVR_ADDITIONAL_ARGS --txt "${GCOVR_OUTPUT_FILE}" )
elseif(Coverage_FORMAT STREQUAL "html-single")
list(APPEND GCOVR_ADDITIONAL_ARGS --html "${GCOVR_OUTPUT_FILE}" )
elseif (Coverage_FORMAT STREQUAL "csv")
list(APPEND GCOVR_ADDITIONAL_ARGS --csv "${GCOVR_OUTPUT_FILE}")
elseif (Coverage_FORMAT STREQUAL "txt")
list(APPEND GCOVR_ADDITIONAL_ARGS --txt "${GCOVR_OUTPUT_FILE}")
elseif (Coverage_FORMAT STREQUAL "html-single")
list(APPEND GCOVR_ADDITIONAL_ARGS --html "${GCOVR_OUTPUT_FILE}")
list(APPEND GCOVR_ADDITIONAL_ARGS --html-self-contained)
elseif(Coverage_FORMAT STREQUAL "html-nested")
list(APPEND GCOVR_ADDITIONAL_ARGS --html-nested "${GCOVR_OUTPUT_FILE}" )
elseif(Coverage_FORMAT STREQUAL "html-details")
list(APPEND GCOVR_ADDITIONAL_ARGS --html-details "${GCOVR_OUTPUT_FILE}" )
else()
elseif (Coverage_FORMAT STREQUAL "html-nested")
list(APPEND GCOVR_ADDITIONAL_ARGS --html-nested "${GCOVR_OUTPUT_FILE}")
elseif (Coverage_FORMAT STREQUAL "html-details")
list(APPEND GCOVR_ADDITIONAL_ARGS --html-details "${GCOVR_OUTPUT_FILE}")
else ()
message(FATAL_ERROR "Unsupported output style ${Coverage_FORMAT}! Aborting...")
endif()
endif ()
# Collect excludes (CMake 3.4+: Also compute absolute paths)
set(GCOVR_EXCLUDES "")
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
if(CMAKE_VERSION VERSION_GREATER 3.4)
foreach (EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
if (CMAKE_VERSION VERSION_GREATER 3.4)
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
endif()
endif ()
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
endforeach()
endforeach ()
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
# Combine excludes to several -e arguments
set(GCOVR_EXCLUDE_ARGS "")
foreach(EXCLUDE ${GCOVR_EXCLUDES})
foreach (EXCLUDE ${GCOVR_EXCLUDES})
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
endforeach()
endforeach ()
# Set up commands which will be run to generate coverage data
# If EXECUTABLE is not set, the user is expected to run the tests manually
# before running the coverage target NAME
if(DEFINED Coverage_EXECUTABLE)
set(GCOVR_EXEC_TESTS_CMD
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
)
endif()
if (DEFINED Coverage_EXECUTABLE)
set(GCOVR_EXEC_TESTS_CMD ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS})
endif ()
# Create folder
if(DEFINED GCOVR_CREATE_FOLDER)
set(GCOVR_FOLDER_CMD
${CMAKE_COMMAND} -E make_directory ${GCOVR_CREATE_FOLDER})
endif()
if (DEFINED GCOVR_CREATE_FOLDER)
set(GCOVR_FOLDER_CMD ${CMAKE_COMMAND} -E make_directory ${GCOVR_CREATE_FOLDER})
endif ()
# Running gcovr
set(GCOVR_CMD
${GCOVR_PATH}
--gcov-executable ${GCOV_TOOL}
--gcov-executable
${GCOV_TOOL}
--gcov-ignore-parse-errors=negative_hits.warn_once_per_file
-r ${BASEDIR}
-r
${BASEDIR}
${GCOVR_ADDITIONAL_ARGS}
${GCOVR_EXCLUDE_ARGS}
--object-directory=${PROJECT_BINARY_DIR}
)
--object-directory=${PROJECT_BINARY_DIR})
if(CODE_COVERAGE_VERBOSE)
if (CODE_COVERAGE_VERBOSE)
message(STATUS "Executed command report")
if(NOT "${GCOVR_EXEC_TESTS_CMD}" STREQUAL "")
if (NOT "${GCOVR_EXEC_TESTS_CMD}" STREQUAL "")
message(STATUS "Command to run tests: ")
string(REPLACE ";" " " GCOVR_EXEC_TESTS_CMD_SPACED "${GCOVR_EXEC_TESTS_CMD}")
message(STATUS "${GCOVR_EXEC_TESTS_CMD_SPACED}")
endif()
endif ()
if(NOT "${GCOVR_FOLDER_CMD}" STREQUAL "")
if (NOT "${GCOVR_FOLDER_CMD}" STREQUAL "")
message(STATUS "Command to create a folder: ")
string(REPLACE ";" " " GCOVR_FOLDER_CMD_SPACED "${GCOVR_FOLDER_CMD}")
message(STATUS "${GCOVR_FOLDER_CMD_SPACED}")
endif()
endif ()
message(STATUS "Command to generate gcovr coverage data: ")
string(REPLACE ";" " " GCOVR_CMD_SPACED "${GCOVR_CMD}")
message(STATUS "${GCOVR_CMD_SPACED}")
endif()
endif ()
add_custom_target(${Coverage_NAME}
COMMAND ${GCOVR_EXEC_TESTS_CMD}
COMMAND ${GCOVR_FOLDER_CMD}
COMMAND ${GCOVR_CMD}
BYPRODUCTS ${GCOVR_OUTPUT_FILE}
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Running gcovr to produce code coverage report."
)
COMMAND ${GCOVR_EXEC_TESTS_CMD}
COMMAND ${GCOVR_FOLDER_CMD}
COMMAND ${GCOVR_CMD}
BYPRODUCTS ${GCOVR_OUTPUT_FILE}
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Running gcovr to produce code coverage report.")
# Show info where to find the report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND echo
COMMENT "Code coverage report saved in ${GCOVR_OUTPUT_FILE} formatted as ${Coverage_FORMAT}"
)
endfunction() # setup_target_for_coverage_gcovr
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD COMMAND echo
COMMENT "Code coverage report saved in ${GCOVR_OUTPUT_FILE} formatted as ${Coverage_FORMAT}")
endfunction () # setup_target_for_coverage_gcovr
function(add_code_coverage_to_target name scope)
function (add_code_coverage_to_target name scope)
separate_arguments(COVERAGE_CXX_COMPILER_FLAGS NATIVE_COMMAND "${COVERAGE_CXX_COMPILER_FLAGS}")
separate_arguments(COVERAGE_C_COMPILER_FLAGS NATIVE_COMMAND "${COVERAGE_C_COMPILER_FLAGS}")
separate_arguments(COVERAGE_CXX_LINKER_FLAGS NATIVE_COMMAND "${COVERAGE_CXX_LINKER_FLAGS}")
separate_arguments(COVERAGE_C_LINKER_FLAGS NATIVE_COMMAND "${COVERAGE_C_LINKER_FLAGS}")
# Add compiler options to the target
target_compile_options(${name} ${scope}
$<$<COMPILE_LANGUAGE:CXX>:${COVERAGE_CXX_COMPILER_FLAGS}>
$<$<COMPILE_LANGUAGE:C>:${COVERAGE_C_COMPILER_FLAGS}>)
target_compile_options(${name} ${scope} $<$<COMPILE_LANGUAGE:CXX>:${COVERAGE_CXX_COMPILER_FLAGS}>
$<$<COMPILE_LANGUAGE:C>:${COVERAGE_C_COMPILER_FLAGS}>)
target_link_libraries (${name} ${scope}
$<$<LINK_LANGUAGE:CXX>:${COVERAGE_CXX_LINKER_FLAGS} gcov>
$<$<LINK_LANGUAGE:C>:${COVERAGE_C_LINKER_FLAGS} gcov>
)
endfunction() # add_code_coverage_to_target
target_link_libraries(
${name}
${scope}
$<$<LINK_LANGUAGE:CXX>:${COVERAGE_CXX_LINKER_FLAGS}
gcov>
$<$<LINK_LANGUAGE:C>:${COVERAGE_C_LINKER_FLAGS}
gcov>)
endfunction () # add_code_coverage_to_target

View File

@@ -1,8 +1,7 @@
# Shared detection of compiler, operating system, and architecture.
#
# This module centralizes environment detection so that other
# CMake modules can use the same variables instead of repeating
# checks on CMAKE_* and built-in platform variables.
# Shared detection of compiler, operating system, and architecture.
#
# This module centralizes environment detection so that other CMake modules can use the same variables instead of
# repeating checks on CMAKE_* and built-in platform variables.
# Only run once per configure step.
include_guard(GLOBAL)
@@ -15,21 +14,20 @@ set(is_gcc FALSE)
set(is_msvc FALSE)
set(is_xcode FALSE)
if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") # Clang or AppleClang
set(is_clang TRUE)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(is_gcc TRUE)
elseif(MSVC)
set(is_msvc TRUE)
else()
message(FATAL_ERROR "Unsupported C++ compiler: ${CMAKE_CXX_COMPILER_ID}")
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") # Clang or AppleClang
set(is_clang TRUE)
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(is_gcc TRUE)
elseif (MSVC)
set(is_msvc TRUE)
else ()
message(FATAL_ERROR "Unsupported C++ compiler: ${CMAKE_CXX_COMPILER_ID}")
endif ()
# Xcode generator detection
if(CMAKE_GENERATOR STREQUAL "Xcode")
set(is_xcode TRUE)
endif()
if (CMAKE_GENERATOR STREQUAL "Xcode")
set(is_xcode TRUE)
endif ()
# --------------------------------------------------------------------
# Operating system detection
@@ -38,23 +36,23 @@ set(is_linux FALSE)
set(is_windows FALSE)
set(is_macos FALSE)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(is_linux TRUE)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
set(is_windows TRUE)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set(is_macos TRUE)
endif()
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(is_linux TRUE)
elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows")
set(is_windows TRUE)
elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set(is_macos TRUE)
endif ()
# --------------------------------------------------------------------
# Architecture
# --------------------------------------------------------------------
set(is_amd64 FALSE)
set(is_arm64 FALSE)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64")
set(is_amd64 TRUE)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64")
set(is_arm64 TRUE)
else()
message(FATAL_ERROR "Unknown architecture: ${CMAKE_SYSTEM_PROCESSOR}")
endif()
if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64")
set(is_amd64 TRUE)
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64")
set(is_arm64 TRUE)
else ()
message(FATAL_ERROR "Unknown architecture: ${CMAKE_SYSTEM_PROCESSOR}")
endif ()

View File

@@ -1,25 +1,16 @@
include(isolate_headers)
function(xrpl_add_test name)
set(target ${PROJECT_NAME}.test.${name})
function (xrpl_add_test name)
set(target ${PROJECT_NAME}.test.${name})
file(GLOB_RECURSE sources CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/${name}/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp"
)
add_executable(${target} ${ARGN} ${sources})
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${name}/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp")
add_executable(${target} ${ARGN} ${sources})
isolate_headers(
${target}
"${CMAKE_SOURCE_DIR}"
"${CMAKE_SOURCE_DIR}/tests/${name}"
PRIVATE
)
isolate_headers(${target} "${CMAKE_SOURCE_DIR}" "${CMAKE_SOURCE_DIR}/tests/${name}" PRIVATE)
# Make sure the test isn't optimized away in unity builds
set_target_properties(${target} PROPERTIES
UNITY_BUILD_MODE GROUP
UNITY_BUILD_BATCH_SIZE 0) # Adjust as needed
# Make sure the test isn't optimized away in unity builds
set_target_properties(${target} PROPERTIES UNITY_BUILD_MODE GROUP UNITY_BUILD_BATCH_SIZE 0) # Adjust as needed
add_test(NAME ${target} COMMAND ${target})
endfunction()
add_test(NAME ${target} COMMAND ${target})
endfunction ()

View File

@@ -8,153 +8,155 @@ include(CompilationEnv)
TODO some/most of these common settings belong in a
toolchain file, especially the ABI-impacting ones
#]=========================================================]
add_library (common INTERFACE)
add_library (Xrpl::common ALIAS common)
add_library(common INTERFACE)
add_library(Xrpl::common ALIAS common)
include(XrplSanitizers)
# add a single global dependency on this interface lib
link_libraries (Xrpl::common)
link_libraries(Xrpl::common)
# Respect CMAKE_POSITION_INDEPENDENT_CODE setting (may be set by Conan toolchain)
if(NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
set_target_properties (common
PROPERTIES INTERFACE_POSITION_INDEPENDENT_CODE ${CMAKE_POSITION_INDEPENDENT_CODE})
if (NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif ()
set_target_properties(common PROPERTIES INTERFACE_POSITION_INDEPENDENT_CODE ${CMAKE_POSITION_INDEPENDENT_CODE})
set(CMAKE_CXX_EXTENSIONS OFF)
target_compile_definitions (common
INTERFACE
$<$<CONFIG:Debug>:DEBUG _DEBUG>
#[===[
target_compile_definitions(
common
INTERFACE $<$<CONFIG:Debug>:DEBUG
_DEBUG>
#[===[
NOTE: CMAKE release builds already have NDEBUG defined, so no need to add it
explicitly except for the special case of (profile ON) and (assert OFF).
Presumably this is because we don't want profile builds asserting unless
asserts were specifically requested.
]===]
$<$<AND:$<BOOL:${profile}>,$<NOT:$<BOOL:${assert}>>>:NDEBUG>
# TODO: Remove once we have migrated functions from OpenSSL 1.x to 3.x.
OPENSSL_SUPPRESS_DEPRECATED
)
$<$<AND:$<BOOL:${profile}>,$<NOT:$<BOOL:${assert}>>>:NDEBUG>
# TODO: Remove once we have migrated functions from OpenSSL 1.x to 3.x.
OPENSSL_SUPPRESS_DEPRECATED)
if (MSVC)
# remove existing exception flag since we set it to -EHa
string (REGEX REPLACE "[-/]EH[a-z]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
# remove existing exception flag since we set it to -EHa
string(REGEX REPLACE "[-/]EH[a-z]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
foreach (var_
CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE)
foreach (var_ CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE)
# also remove dynamic runtime
string (REGEX REPLACE "[-/]MD[d]*" " " ${var_} "${${var_}}")
# also remove dynamic runtime
string(REGEX REPLACE "[-/]MD[d]*" " " ${var_} "${${var_}}")
# /ZI (Edit & Continue debugging information) is incompatible with Gy-
string (REPLACE "/ZI" "/Zi" ${var_} "${${var_}}")
# /ZI (Edit & Continue debugging information) is incompatible with Gy-
string(REPLACE "/ZI" "/Zi" ${var_} "${${var_}}")
# omit debug info completely under CI (not needed)
if (is_ci)
string (REPLACE "/Zi" " " ${var_} "${${var_}}")
string (REPLACE "/Z7" " " ${var_} "${${var_}}")
endif ()
endforeach ()
# omit debug info completely under CI (not needed)
if (is_ci)
string(REPLACE "/Zi" " " ${var_} "${${var_}}")
string(REPLACE "/Z7" " " ${var_} "${${var_}}")
endif ()
endforeach ()
target_compile_options (common
INTERFACE
-bigobj # Increase object file max size
-fp:precise # Floating point behavior
-Gd # __cdecl calling convention
-Gm- # Minimal rebuild: disabled
-Gy- # Function level linking: disabled
-MP # Multiprocessor compilation
-openmp- # pragma omp: disabled
-errorReport:none # No error reporting to Internet
-nologo # Suppress login banner
-wd4018 # Disable signed/unsigned comparison warnings
-wd4244 # Disable float to int possible loss of data warnings
-wd4267 # Disable size_t to T possible loss of data warnings
-wd4800 # Disable C4800(int to bool performance)
-wd4503 # Decorated name length exceeded, name was truncated
$<$<COMPILE_LANGUAGE:CXX>:
-EHa
-GR
>
$<$<CONFIG:Release>:-Ox>
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:Debug>>:
-GS
-Zc:forScope
>
# static runtime
$<$<CONFIG:Debug>:-MTd>
$<$<NOT:$<CONFIG:Debug>>:-MT>
$<$<BOOL:${werr}>:-WX>
)
target_compile_definitions (common
INTERFACE
_WIN32_WINNT=0x6000
_SCL_SECURE_NO_WARNINGS
_CRT_SECURE_NO_WARNINGS
WIN32_CONSOLE
WIN32_LEAN_AND_MEAN
NOMINMAX
# TODO: Resolve these warnings, don't just silence them
_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:Debug>>:_CRTDBG_MAP_ALLOC>)
target_link_libraries (common
INTERFACE
-errorreport:none
-machine:X64)
target_compile_options(
common
INTERFACE # Increase object file max size
-bigobj
# Floating point behavior
-fp:precise
# __cdecl calling convention
-Gd
# Minimal rebuild: disabled
-Gm-
# Function level linking: disabled
-Gy-
# Multiprocessor compilation
-MP
# pragma omp: disabled
-openmp-
# No error reporting to Internet
-errorReport:none
# Suppress login banner
-nologo
# Disable signed/unsigned comparison warnings
-wd4018
# Disable float to int possible loss of data warnings
-wd4244
# Disable size_t to T possible loss of data warnings
-wd4267
# Disable C4800(int to bool performance)
-wd4800
# Decorated name length exceeded, name was truncated
-wd4503
$<$<COMPILE_LANGUAGE:CXX>:
-EHa
-GR
>
$<$<CONFIG:Release>:-Ox>
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:Debug>>:
-GS
-Zc:forScope
>
# static runtime
$<$<CONFIG:Debug>:-MTd>
$<$<NOT:$<CONFIG:Debug>>:-MT>
$<$<BOOL:${werr}>:-WX>)
target_compile_definitions(
common
INTERFACE _WIN32_WINNT=0x6000
_SCL_SECURE_NO_WARNINGS
_CRT_SECURE_NO_WARNINGS
WIN32_CONSOLE
WIN32_LEAN_AND_MEAN
NOMINMAX
# TODO: Resolve these warnings, don't just silence them
_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:Debug>>:_CRTDBG_MAP_ALLOC>)
target_link_libraries(common INTERFACE -errorreport:none -machine:X64)
else ()
target_compile_options (common
INTERFACE
-Wall
-Wdeprecated
$<$<BOOL:${is_clang}>:-Wno-deprecated-declarations>
$<$<BOOL:${wextra}>:-Wextra -Wno-unused-parameter>
$<$<BOOL:${werr}>:-Werror>
-fstack-protector
-Wno-sign-compare
-Wno-unused-but-set-variable
$<$<NOT:$<CONFIG:Debug>>:-fno-strict-aliasing>
# tweak gcc optimization for debug
$<$<AND:$<BOOL:${is_gcc}>,$<CONFIG:Debug>>:-O0>
# Add debug symbols to release config
$<$<CONFIG:Release>:-g>)
target_link_libraries (common
INTERFACE
-rdynamic
$<$<BOOL:${is_linux}>:-Wl,-z,relro,-z,now,--build-id>
# link to static libc/c++ iff:
# * static option set and
# * NOT APPLE (AppleClang does not support static libc/c++) and
# * NOT SANITIZERS (sanitizers typically don't work with static libc/c++)
$<$<AND:$<BOOL:${static}>,$<NOT:$<BOOL:${APPLE}>>,$<NOT:$<BOOL:${SANITIZERS_ENABLED}>>>:
-static-libstdc++
-static-libgcc
>)
target_compile_options(
common
INTERFACE -Wall
-Wdeprecated
$<$<BOOL:${is_clang}>:-Wno-deprecated-declarations>
$<$<BOOL:${wextra}>:-Wextra
-Wno-unused-parameter>
$<$<BOOL:${werr}>:-Werror>
-fstack-protector
-Wno-sign-compare
-Wno-unused-but-set-variable
$<$<NOT:$<CONFIG:Debug>>:-fno-strict-aliasing>
# tweak gcc optimization for debug
$<$<AND:$<BOOL:${is_gcc}>,$<CONFIG:Debug>>:-O0>
# Add debug symbols to release config
$<$<CONFIG:Release>:-g>)
target_link_libraries(
common
INTERFACE -rdynamic
$<$<BOOL:${is_linux}>:-Wl,-z,relro,-z,now,--build-id>
# link to static libc/c++ iff: * static option set and * NOT APPLE (AppleClang does not support static
# libc/c++) and * NOT SANITIZERS (sanitizers typically don't work with static libc/c++)
$<$<AND:$<BOOL:${static}>,$<NOT:$<BOOL:${APPLE}>>,$<NOT:$<BOOL:${SANITIZERS_ENABLED}>>>:
-static-libstdc++
-static-libgcc
>)
endif ()
# Antithesis instrumentation will only be built and deployed using machines running Linux.
if (voidstar)
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
message(FATAL_ERROR "Antithesis instrumentation requires Debug build type, aborting...")
elseif (NOT is_linux)
message(FATAL_ERROR "Antithesis instrumentation requires Linux, aborting...")
elseif (NOT (is_clang AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0))
message(FATAL_ERROR "Antithesis instrumentation requires Clang version 16 or later, aborting...")
endif ()
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
message(FATAL_ERROR "Antithesis instrumentation requires Debug build type, aborting...")
elseif (NOT is_linux)
message(FATAL_ERROR "Antithesis instrumentation requires Linux, aborting...")
elseif (NOT (is_clang AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0))
message(FATAL_ERROR "Antithesis instrumentation requires Clang version 16 or later, aborting...")
endif ()
endif ()
if (use_mold)
# use mold linker if available
execute_process (
COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=mold -Wl,--version
ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
if ("${LD_VERSION}" MATCHES "mold")
target_link_libraries (common INTERFACE -fuse-ld=mold)
endif ()
unset (LD_VERSION)
# use mold linker if available
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=mold -Wl,--version ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
if ("${LD_VERSION}" MATCHES "mold")
target_link_libraries(common INTERFACE -fuse-ld=mold)
endif ()
unset(LD_VERSION)
elseif (use_gold AND is_gcc)
# use gold linker if available
execute_process (
COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=gold -Wl,--version
ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
# use gold linker if available
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=gold -Wl,--version ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
#[=========================================================[
NOTE: THE gold linker inserts -rpath as DT_RUNPATH by
default instead of DT_RPATH, so you might have slightly
@@ -168,34 +170,31 @@ elseif (use_gold AND is_gcc)
disabling would be to figure out all the settings
required to make gold play nicely with jemalloc.
#]=========================================================]
if (("${LD_VERSION}" MATCHES "GNU gold") AND (NOT jemalloc))
target_link_libraries (common
INTERFACE
-fuse-ld=gold
-Wl,--no-as-needed
#[=========================================================[
if (("${LD_VERSION}" MATCHES "GNU gold") AND (NOT jemalloc))
target_link_libraries(
common
INTERFACE -fuse-ld=gold
-Wl,--no-as-needed
#[=========================================================[
see https://bugs.launchpad.net/ubuntu/+source/eglibc/+bug/1253638/comments/5
DT_RUNPATH does not work great for transitive
dependencies (of which boost has a few) - so just
switch to DT_RPATH if doing dynamic linking with gold
#]=========================================================]
$<$<NOT:$<BOOL:${static}>>:-Wl,--disable-new-dtags>)
endif ()
unset (LD_VERSION)
$<$<NOT:$<BOOL:${static}>>:-Wl,--disable-new-dtags>)
endif ()
unset(LD_VERSION)
elseif (use_lld)
# use lld linker if available
execute_process (
COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=lld -Wl,--version
ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
if ("${LD_VERSION}" MATCHES "LLD")
target_link_libraries (common INTERFACE -fuse-ld=lld)
endif ()
unset (LD_VERSION)
endif()
# use lld linker if available
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=lld -Wl,--version ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
if ("${LD_VERSION}" MATCHES "LLD")
target_link_libraries(common INTERFACE -fuse-ld=lld)
endif ()
unset(LD_VERSION)
endif ()
if (assert)
foreach (var_ CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE)
STRING (REGEX REPLACE "[-/]DNDEBUG" "" ${var_} "${${var_}}")
endforeach ()
foreach (var_ CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE)
string(REGEX REPLACE "[-/]DNDEBUG" "" ${var_} "${${var_}}")
endforeach ()
endif ()

View File

@@ -1,54 +1,52 @@
include (CMakeFindDependencyMacro)
include(CMakeFindDependencyMacro)
# need to represent system dependencies of the lib here
#[=========================================================[
Boost
#]=========================================================]
if (static OR APPLE OR MSVC)
set (Boost_USE_STATIC_LIBS ON)
set(Boost_USE_STATIC_LIBS ON)
endif ()
set (Boost_USE_MULTITHREADED ON)
set(Boost_USE_MULTITHREADED ON)
if (static OR MSVC)
set (Boost_USE_STATIC_RUNTIME ON)
set(Boost_USE_STATIC_RUNTIME ON)
else ()
set (Boost_USE_STATIC_RUNTIME OFF)
set(Boost_USE_STATIC_RUNTIME OFF)
endif ()
find_dependency (Boost
COMPONENTS
chrono
container
context
coroutine
date_time
filesystem
program_options
regex
system
thread)
find_dependency(Boost
COMPONENTS
chrono
container
context
coroutine
date_time
filesystem
program_options
regex
system
thread)
#[=========================================================[
OpenSSL
#]=========================================================]
if (NOT DEFINED OPENSSL_ROOT_DIR)
if (DEFINED ENV{OPENSSL_ROOT})
set (OPENSSL_ROOT_DIR $ENV{OPENSSL_ROOT})
elseif (APPLE)
find_program (homebrew brew)
if (homebrew)
execute_process (COMMAND ${homebrew} --prefix openssl
OUTPUT_VARIABLE OPENSSL_ROOT_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
if (DEFINED ENV{OPENSSL_ROOT})
set(OPENSSL_ROOT_DIR $ENV{OPENSSL_ROOT})
elseif (APPLE)
find_program(homebrew brew)
if (homebrew)
execute_process(COMMAND ${homebrew} --prefix openssl OUTPUT_VARIABLE OPENSSL_ROOT_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif ()
endif ()
endif ()
file (TO_CMAKE_PATH "${OPENSSL_ROOT_DIR}" OPENSSL_ROOT_DIR)
file(TO_CMAKE_PATH "${OPENSSL_ROOT_DIR}" OPENSSL_ROOT_DIR)
endif ()
if (static OR APPLE OR MSVC)
set (OPENSSL_USE_STATIC_LIBS ON)
set(OPENSSL_USE_STATIC_LIBS ON)
endif ()
set (OPENSSL_MSVC_STATIC_RT ON)
find_dependency (OpenSSL REQUIRED)
find_dependency (ZLIB)
find_dependency (date)
set(OPENSSL_MSVC_STATIC_RT ON)
find_dependency(OpenSSL REQUIRED)
find_dependency(ZLIB)
find_dependency(date)
if (TARGET ZLIB::ZLIB)
set_target_properties(OpenSSL::Crypto PROPERTIES
INTERFACE_LINK_LIBRARIES ZLIB::ZLIB)
set_target_properties(OpenSSL::Crypto PROPERTIES INTERFACE_LINK_LIBRARIES ZLIB::ZLIB)
endif ()

View File

@@ -10,64 +10,44 @@ include(target_protobuf_sources)
# so we just build them as a separate library.
add_library(xrpl.libpb)
set_target_properties(xrpl.libpb PROPERTIES UNITY_BUILD OFF)
target_protobuf_sources(xrpl.libpb xrpl/proto
LANGUAGE cpp
IMPORT_DIRS include/xrpl/proto
PROTOS include/xrpl/proto/xrpl.proto
)
target_protobuf_sources(xrpl.libpb xrpl/proto LANGUAGE cpp IMPORT_DIRS include/xrpl/proto
PROTOS include/xrpl/proto/xrpl.proto)
file(GLOB_RECURSE protos "include/xrpl/proto/org/*.proto")
target_protobuf_sources(xrpl.libpb xrpl/proto
LANGUAGE cpp
IMPORT_DIRS include/xrpl/proto
PROTOS "${protos}"
)
target_protobuf_sources(xrpl.libpb xrpl/proto
LANGUAGE grpc
IMPORT_DIRS include/xrpl/proto
PROTOS "${protos}"
PLUGIN protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>
GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc
)
target_protobuf_sources(xrpl.libpb xrpl/proto LANGUAGE cpp IMPORT_DIRS include/xrpl/proto PROTOS "${protos}")
target_protobuf_sources(
xrpl.libpb xrpl/proto
LANGUAGE grpc
IMPORT_DIRS include/xrpl/proto
PROTOS "${protos}"
PLUGIN protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>
GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc)
target_compile_options(xrpl.libpb
PUBLIC
$<$<BOOL:${is_msvc}>:-wd4996>
$<$<BOOL:${is_xcode}>:
--system-header-prefix="google/protobuf"
-Wno-deprecated-dynamic-exception-spec
>
PRIVATE
$<$<BOOL:${is_msvc}>:-wd4065>
$<$<NOT:$<BOOL:${is_msvc}>>:-Wno-deprecated-declarations>
)
target_compile_options(
xrpl.libpb PUBLIC $<$<BOOL:${is_msvc}>:-wd4996> $<$<BOOL:${is_xcode}>: --system-header-prefix="google/protobuf"
-Wno-deprecated-dynamic-exception-spec >
PRIVATE $<$<BOOL:${is_msvc}>:-wd4065> $<$<NOT:$<BOOL:${is_msvc}>>:-Wno-deprecated-declarations>)
target_link_libraries(xrpl.libpb
PUBLIC
protobuf::libprotobuf
gRPC::grpc++
)
target_link_libraries(xrpl.libpb PUBLIC protobuf::libprotobuf gRPC::grpc++)
# TODO: Clean up the number of library targets later.
add_library(xrpl.imports.main INTERFACE)
target_link_libraries(xrpl.imports.main
INTERFACE
absl::random_random
date::date
ed25519::ed25519
LibArchive::LibArchive
OpenSSL::Crypto
Xrpl::boost
Xrpl::libs
Xrpl::opts
Xrpl::syslibs
secp256k1::secp256k1
wasmi::wasmi
xrpl.libpb
xxHash::xxhash
$<$<BOOL:${voidstar}>:antithesis-sdk-cpp>
)
target_link_libraries(
xrpl.imports.main
INTERFACE absl::random_random
date::date
ed25519::ed25519
LibArchive::LibArchive
OpenSSL::Crypto
Xrpl::boost
Xrpl::libs
Xrpl::opts
Xrpl::syslibs
secp256k1::secp256k1
xrpl.libpb
xxHash::xxhash
$<$<BOOL:${voidstar}>:antithesis-sdk-cpp>)
include(add_module)
include(target_link_modules)
@@ -89,18 +69,11 @@ target_link_libraries(xrpl.libxrpl.crypto PUBLIC xrpl.libxrpl.basics)
# Level 04
add_module(xrpl protocol)
target_link_libraries(xrpl.libxrpl.protocol PUBLIC
xrpl.libxrpl.crypto
xrpl.libxrpl.json
)
target_link_libraries(xrpl.libxrpl.protocol PUBLIC xrpl.libxrpl.crypto xrpl.libxrpl.json)
# Level 05
add_module(xrpl core)
target_link_libraries(xrpl.libxrpl.core PUBLIC
xrpl.libxrpl.basics
xrpl.libxrpl.json
xrpl.libxrpl.protocol
)
target_link_libraries(xrpl.libxrpl.core PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json xrpl.libxrpl.protocol)
# Level 06
add_module(xrpl resource)
@@ -108,62 +81,45 @@ target_link_libraries(xrpl.libxrpl.resource PUBLIC xrpl.libxrpl.protocol)
# Level 07
add_module(xrpl net)
target_link_libraries(xrpl.libxrpl.net PUBLIC
xrpl.libxrpl.basics
xrpl.libxrpl.json
xrpl.libxrpl.protocol
xrpl.libxrpl.resource
)
target_link_libraries(xrpl.libxrpl.net PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json xrpl.libxrpl.protocol
xrpl.libxrpl.resource)
add_module(xrpl server)
target_link_libraries(xrpl.libxrpl.server PUBLIC xrpl.libxrpl.protocol)
add_module(xrpl nodestore)
target_link_libraries(xrpl.libxrpl.nodestore PUBLIC
xrpl.libxrpl.basics
xrpl.libxrpl.json
xrpl.libxrpl.protocol
)
target_link_libraries(xrpl.libxrpl.nodestore PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json xrpl.libxrpl.protocol)
add_module(xrpl shamap)
target_link_libraries(xrpl.libxrpl.shamap PUBLIC
xrpl.libxrpl.basics
xrpl.libxrpl.crypto
xrpl.libxrpl.protocol
xrpl.libxrpl.nodestore
)
target_link_libraries(xrpl.libxrpl.shamap PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.crypto xrpl.libxrpl.protocol
xrpl.libxrpl.nodestore)
add_module(xrpl ledger)
target_link_libraries(xrpl.libxrpl.ledger PUBLIC
xrpl.libxrpl.basics
xrpl.libxrpl.json
xrpl.libxrpl.protocol
)
target_link_libraries(xrpl.libxrpl.ledger PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json xrpl.libxrpl.protocol)
add_library(xrpl.libxrpl)
set_target_properties(xrpl.libxrpl PROPERTIES OUTPUT_NAME xrpl)
add_library(xrpl::libxrpl ALIAS xrpl.libxrpl)
file(GLOB_RECURSE sources CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/src/libxrpl/*.cpp"
)
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/libxrpl/*.cpp")
target_sources(xrpl.libxrpl PRIVATE ${sources})
target_link_modules(xrpl PUBLIC
basics
beast
core
crypto
json
protocol
resource
server
nodestore
shamap
net
ledger
)
target_link_modules(
xrpl
PUBLIC
basics
beast
core
crypto
json
protocol
resource
server
nodestore
shamap
net
ledger)
# All headers in libxrpl are in modules.
# Uncomment this stanza if you have not yet moved new headers into a module.
@@ -174,63 +130,42 @@ target_link_modules(xrpl PUBLIC
# $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
# $<INSTALL_INTERFACE:include>)
if(xrpld)
add_executable(xrpld)
if(tests)
target_compile_definitions(xrpld PUBLIC ENABLE_TESTS)
target_compile_definitions(xrpld PRIVATE
UNIT_TEST_REFERENCE_FEE=${UNIT_TEST_REFERENCE_FEE}
)
endif()
target_include_directories(xrpld
PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
)
if (xrpld)
add_executable(xrpld)
if (tests)
target_compile_definitions(xrpld PUBLIC ENABLE_TESTS)
target_compile_definitions(xrpld PRIVATE UNIT_TEST_REFERENCE_FEE=${UNIT_TEST_REFERENCE_FEE})
endif ()
target_include_directories(xrpld PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>)
file(GLOB_RECURSE sources CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/src/xrpld/*.cpp"
)
target_sources(xrpld PRIVATE ${sources})
if(tests)
file(GLOB_RECURSE sources CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/src/test/*.cpp"
)
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/xrpld/*.cpp")
target_sources(xrpld PRIVATE ${sources})
endif()
target_link_libraries(xrpld
Xrpl::boost
Xrpl::opts
Xrpl::libs
xrpl.libxrpl
)
exclude_if_included(xrpld)
# define a macro for tests that might need to
# be excluded or run differently in CI environment
if(is_ci)
target_compile_definitions(xrpld PRIVATE XRPL_RUNNING_IN_CI)
endif ()
if (tests)
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/test/*.cpp")
target_sources(xrpld PRIVATE ${sources})
endif ()
if(voidstar)
target_compile_options(xrpld
PRIVATE
-fsanitize-coverage=trace-pc-guard
)
# xrpld requires access to antithesis-sdk-cpp implementation file
# antithesis_instrumentation.h, which is not exported as INTERFACE
target_include_directories(xrpld
PRIVATE
${CMAKE_SOURCE_DIR}/external/antithesis-sdk
)
endif()
target_link_libraries(xrpld Xrpl::boost Xrpl::opts Xrpl::libs xrpl.libxrpl)
exclude_if_included(xrpld)
# define a macro for tests that might need to
# be excluded or run differently in CI environment
if (is_ci)
target_compile_definitions(xrpld PRIVATE XRPL_RUNNING_IN_CI)
endif ()
# any files that don't play well with unity should be added here
if(tests)
set_source_files_properties(
# these two seem to produce conflicts in beast teardown template methods
src/test/rpc/ValidatorRPC_test.cpp
src/test/ledger/Invariants_test.cpp
PROPERTIES SKIP_UNITY_BUILD_INCLUSION TRUE)
endif()
endif()
if (voidstar)
target_compile_options(xrpld PRIVATE -fsanitize-coverage=trace-pc-guard)
# xrpld requires access to antithesis-sdk-cpp implementation file
# antithesis_instrumentation.h, which is not exported as INTERFACE
target_include_directories(xrpld PRIVATE ${CMAKE_SOURCE_DIR}/external/antithesis-sdk)
endif ()
# any files that don't play well with unity should be added here
if (tests)
set_source_files_properties(
# these two seem to produce conflicts in beast teardown template methods
src/test/rpc/ValidatorRPC_test.cpp src/test/ledger/Invariants_test.cpp PROPERTIES SKIP_UNITY_BUILD_INCLUSION
TRUE)
endif ()
endif ()

View File

@@ -2,40 +2,51 @@
coverage report target
#]===================================================================]
if(NOT coverage)
message(FATAL_ERROR "Code coverage not enabled! Aborting ...")
endif()
if (NOT coverage)
message(FATAL_ERROR "Code coverage not enabled! Aborting ...")
endif ()
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
message(WARNING "Code coverage on Windows is not supported, ignoring 'coverage' flag")
return()
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
message(WARNING "Code coverage on Windows is not supported, ignoring 'coverage' flag")
return()
endif ()
include(ProcessorCount)
ProcessorCount(PROCESSOR_COUNT)
include(CodeCoverage)
# The instructions for these commands come from the `CodeCoverage` module,
# which was copied from https://github.com/bilke/cmake-modules, commit fb7d2a3,
# then locally changed (see CHANGES: section in `CodeCoverage.cmake`)
# The instructions for these commands come from the `CodeCoverage` module, which was copied from
# https://github.com/bilke/cmake-modules, commit fb7d2a3, then locally changed (see CHANGES: section in
# `CodeCoverage.cmake`)
set(GCOVR_ADDITIONAL_ARGS ${coverage_extra_args})
if(NOT GCOVR_ADDITIONAL_ARGS STREQUAL "")
separate_arguments(GCOVR_ADDITIONAL_ARGS)
endif()
if (NOT GCOVR_ADDITIONAL_ARGS STREQUAL "")
separate_arguments(GCOVR_ADDITIONAL_ARGS)
endif ()
list(APPEND GCOVR_ADDITIONAL_ARGS
--exclude-throw-branches
--exclude-noncode-lines
--exclude-unreachable-branches -s
-j ${PROCESSOR_COUNT})
list(APPEND
GCOVR_ADDITIONAL_ARGS
--exclude-throw-branches
--exclude-noncode-lines
--exclude-unreachable-branches
-s
-j
${PROCESSOR_COUNT})
setup_target_for_coverage_gcovr(
NAME coverage
FORMAT ${coverage_format}
EXCLUDE "src/test" "src/tests" "include/xrpl/beast/test" "include/xrpl/beast/unit_test" "${CMAKE_BINARY_DIR}/pb-xrpl.libpb"
DEPENDENCIES xrpld xrpl.tests
)
NAME
coverage
FORMAT
${coverage_format}
EXCLUDE
"src/test"
"src/tests"
"include/xrpl/beast/test"
"include/xrpl/beast/unit_test"
"${CMAKE_BINARY_DIR}/pb-xrpl.libpb"
DEPENDENCIES
xrpld
xrpl.tests)
add_code_coverage_to_target(opts INTERFACE)

View File

@@ -2,45 +2,44 @@
docs target (optional)
#]===================================================================]
if(NOT only_docs)
return()
endif()
if (NOT only_docs)
return()
endif ()
find_package(Doxygen)
if(NOT TARGET Doxygen::doxygen)
message(STATUS "doxygen executable not found -- skipping docs target")
return()
endif()
if (NOT TARGET Doxygen::doxygen)
message(STATUS "doxygen executable not found -- skipping docs target")
return()
endif ()
set(doxygen_output_directory "${CMAKE_BINARY_DIR}/docs")
set(doxygen_include_path "${CMAKE_CURRENT_SOURCE_DIR}/src")
set(doxygen_index_file "${doxygen_output_directory}/html/index.html")
set(doxyfile "${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile")
file(GLOB_RECURSE doxygen_input
docs/*.md
include/*.h
include/*.cpp
include/*.md
src/*.h
src/*.cpp
src/*.md
Builds/*.md
*.md)
list(APPEND doxygen_input
external/README.md
)
file(GLOB_RECURSE
doxygen_input
docs/*.md
include/*.h
include/*.cpp
include/*.md
src/*.h
src/*.cpp
src/*.md
Builds/*.md
*.md)
list(APPEND doxygen_input external/README.md)
set(dependencies "${doxygen_input}" "${doxyfile}")
function(verbose_find_path variable name)
# find_path sets a CACHE variable, so don't try using a "local" variable.
find_path(${variable} "${name}" ${ARGN})
if(NOT ${variable})
message(NOTICE "could not find ${name}")
else()
message(STATUS "found ${name}: ${${variable}}/${name}")
endif()
endfunction()
function (verbose_find_path variable name)
# find_path sets a CACHE variable, so don't try using a "local" variable.
find_path(${variable} "${name}" ${ARGN})
if (NOT ${variable})
message(NOTICE "could not find ${name}")
else ()
message(STATUS "found ${name}: ${${variable}}/${name}")
endif ()
endfunction ()
verbose_find_path(doxygen_plantuml_jar_path plantuml.jar PATH_SUFFIXES share/plantuml)
verbose_find_path(doxygen_dot_path dot)
@@ -48,36 +47,26 @@ verbose_find_path(doxygen_dot_path dot)
# https://en.cppreference.com/w/Cppreference:Archives
# https://stackoverflow.com/questions/60822559/how-to-move-a-file-download-from-configure-step-to-build-step
set(download_script "${CMAKE_BINARY_DIR}/docs/download-cppreference.cmake")
file(WRITE
"${download_script}"
"file(DOWNLOAD \
file(WRITE "${download_script}"
"file(DOWNLOAD \
https://github.com/PeterFeicht/cppreference-doc/releases/download/v20250209/html-book-20250209.zip \
${CMAKE_BINARY_DIR}/docs/cppreference.zip \
EXPECTED_HASH MD5=bda585f72fbca4b817b29a3d5746567b \
)\n \
execute_process( \
COMMAND \"${CMAKE_COMMAND}\" -E tar -xf cppreference.zip \
)\n"
)
)\n")
set(tagfile "${CMAKE_BINARY_DIR}/docs/cppreference-doxygen-web.tag.xml")
add_custom_command(
OUTPUT "${tagfile}"
COMMAND "${CMAKE_COMMAND}" -P "${download_script}"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/docs"
)
add_custom_command(OUTPUT "${tagfile}" COMMAND "${CMAKE_COMMAND}" -P "${download_script}"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/docs")
set(doxygen_tagfiles "${tagfile}=http://en.cppreference.com/w/")
add_custom_command(
OUTPUT "${doxygen_index_file}"
COMMAND "${CMAKE_COMMAND}" -E env
"DOXYGEN_OUTPUT_DIRECTORY=${doxygen_output_directory}"
"DOXYGEN_INCLUDE_PATH=${doxygen_include_path}"
"DOXYGEN_TAGFILES=${doxygen_tagfiles}"
"DOXYGEN_PLANTUML_JAR_PATH=${doxygen_plantuml_jar_path}"
"DOXYGEN_DOT_PATH=${doxygen_dot_path}"
"${DOXYGEN_EXECUTABLE}" "${doxyfile}"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
DEPENDS "${dependencies}" "${tagfile}")
add_custom_target(docs
DEPENDS "${doxygen_index_file}"
SOURCES "${dependencies}")
OUTPUT "${doxygen_index_file}"
COMMAND "${CMAKE_COMMAND}" -E env "DOXYGEN_OUTPUT_DIRECTORY=${doxygen_output_directory}"
"DOXYGEN_INCLUDE_PATH=${doxygen_include_path}" "DOXYGEN_TAGFILES=${doxygen_tagfiles}"
"DOXYGEN_PLANTUML_JAR_PATH=${doxygen_plantuml_jar_path}" "DOXYGEN_DOT_PATH=${doxygen_dot_path}"
"${DOXYGEN_EXECUTABLE}" "${doxyfile}"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
DEPENDS "${dependencies}" "${tagfile}")
add_custom_target(docs DEPENDS "${doxygen_index_file}" SOURCES "${dependencies}")

View File

@@ -6,61 +6,51 @@ include(create_symbolic_link)
# If no suffix is defined for executables (e.g. Windows uses .exe but Linux
# and macOS use none), then explicitly set it to the empty string.
if(NOT DEFINED suffix)
set(suffix "")
endif()
if (NOT DEFINED suffix)
set(suffix "")
endif ()
install (
TARGETS
common
opts
xrpl_boost
xrpl_libs
xrpl_syslibs
xrpl.imports.main
xrpl.libpb
xrpl.libxrpl
xrpl.libxrpl.basics
xrpl.libxrpl.beast
xrpl.libxrpl.core
xrpl.libxrpl.crypto
xrpl.libxrpl.json
xrpl.libxrpl.ledger
xrpl.libxrpl.net
xrpl.libxrpl.nodestore
xrpl.libxrpl.protocol
xrpl.libxrpl.resource
xrpl.libxrpl.server
xrpl.libxrpl.shamap
antithesis-sdk-cpp
EXPORT XrplExports
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include)
install(TARGETS common
opts
xrpl_boost
xrpl_libs
xrpl_syslibs
xrpl.imports.main
xrpl.libpb
xrpl.libxrpl
xrpl.libxrpl.basics
xrpl.libxrpl.beast
xrpl.libxrpl.core
xrpl.libxrpl.crypto
xrpl.libxrpl.json
xrpl.libxrpl.ledger
xrpl.libxrpl.net
xrpl.libxrpl.nodestore
xrpl.libxrpl.protocol
xrpl.libxrpl.resource
xrpl.libxrpl.server
xrpl.libxrpl.shamap
antithesis-sdk-cpp
EXPORT XrplExports
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES
DESTINATION include)
install(
DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/xrpl"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/xrpl" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
install (EXPORT XrplExports
FILE XrplTargets.cmake
NAMESPACE Xrpl::
DESTINATION lib/cmake/xrpl)
include (CMakePackageConfigHelpers)
write_basic_package_version_file (
XrplConfigVersion.cmake
VERSION ${xrpld_version}
COMPATIBILITY SameMajorVersion)
install(EXPORT XrplExports FILE XrplTargets.cmake NAMESPACE Xrpl:: DESTINATION lib/cmake/xrpl)
include(CMakePackageConfigHelpers)
write_basic_package_version_file(XrplConfigVersion.cmake VERSION ${xrpld_version} COMPATIBILITY SameMajorVersion)
if (is_root_project AND TARGET xrpld)
install (TARGETS xrpld RUNTIME DESTINATION bin)
set_target_properties(xrpld PROPERTIES INSTALL_RPATH_USE_LINK_PATH ON)
# sample configs should not overwrite existing files
# install if-not-exists workaround as suggested by
# https://cmake.org/Bug/view.php?id=12646
install(CODE "
install(TARGETS xrpld RUNTIME DESTINATION bin)
set_target_properties(xrpld PROPERTIES INSTALL_RPATH_USE_LINK_PATH ON)
# sample configs should not overwrite existing files
# install if-not-exists workaround as suggested by
# https://cmake.org/Bug/view.php?id=12646
install(CODE "
macro (copy_if_not_exists SRC DEST NEWNAME)
if (NOT EXISTS \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${DEST}/\${NEWNAME}\")
file (INSTALL FILE_PERMISSIONS OWNER_READ OWNER_WRITE DESTINATION \"\${CMAKE_INSTALL_PREFIX}/\${DEST}\" FILES \"\${SRC}\" RENAME \"\${NEWNAME}\")
@@ -71,7 +61,7 @@ if (is_root_project AND TARGET xrpld)
copy_if_not_exists(\"${CMAKE_CURRENT_SOURCE_DIR}/cfg/xrpld-example.cfg\" etc xrpld.cfg)
copy_if_not_exists(\"${CMAKE_CURRENT_SOURCE_DIR}/cfg/validators-example.txt\" etc validators.txt)
")
install(CODE "
install(CODE "
set(CMAKE_MODULE_PATH \"${CMAKE_MODULE_PATH}\")
include(create_symbolic_link)
create_symbolic_link(xrpld${suffix} \
@@ -79,8 +69,5 @@ if (is_root_project AND TARGET xrpld)
")
endif ()
install (
FILES
${CMAKE_CURRENT_SOURCE_DIR}/cmake/XrplConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/XrplConfigVersion.cmake
DESTINATION lib/cmake/xrpl)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cmake/XrplConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/XrplConfigVersion.cmake
DESTINATION lib/cmake/xrpl)

View File

@@ -5,84 +5,79 @@
include(CompilationEnv)
# Set defaults for optional variables to avoid uninitialized variable warnings
if(NOT DEFINED voidstar)
set(voidstar OFF)
endif()
if (NOT DEFINED voidstar)
set(voidstar OFF)
endif ()
add_library (opts INTERFACE)
add_library (Xrpl::opts ALIAS opts)
target_compile_definitions (opts
INTERFACE
BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS
BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT
BOOST_CONTAINER_FWD_BAD_DEQUE
HAS_UNCAUGHT_EXCEPTIONS=1
$<$<BOOL:${boost_show_deprecated}>:
BOOST_ASIO_NO_DEPRECATED
BOOST_FILESYSTEM_NO_DEPRECATED
>
$<$<NOT:$<BOOL:${boost_show_deprecated}>>:
BOOST_COROUTINES_NO_DEPRECATION_WARNING
BOOST_BEAST_ALLOW_DEPRECATED
BOOST_FILESYSTEM_DEPRECATED
>
$<$<BOOL:${beast_no_unit_test_inline}>:BEAST_NO_UNIT_TEST_INLINE=1>
$<$<BOOL:${beast_disable_autolink}>:BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES=1>
$<$<BOOL:${single_io_service_thread}>:XRPL_SINGLE_IO_SERVICE_THREAD=1>
$<$<BOOL:${voidstar}>:ENABLE_VOIDSTAR>)
target_compile_options (opts
INTERFACE
$<$<AND:$<BOOL:${is_gcc}>,$<COMPILE_LANGUAGE:CXX>>:-Wsuggest-override>
$<$<BOOL:${is_gcc}>:-Wno-maybe-uninitialized>
$<$<BOOL:${perf}>:-fno-omit-frame-pointer>
$<$<BOOL:${profile}>:-pg>
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>)
add_library(opts INTERFACE)
add_library(Xrpl::opts ALIAS opts)
target_compile_definitions(
opts
INTERFACE BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS
BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT
BOOST_CONTAINER_FWD_BAD_DEQUE
HAS_UNCAUGHT_EXCEPTIONS=1
$<$<BOOL:${boost_show_deprecated}>:
BOOST_ASIO_NO_DEPRECATED
BOOST_FILESYSTEM_NO_DEPRECATED
>
$<$<NOT:$<BOOL:${boost_show_deprecated}>>:
BOOST_COROUTINES_NO_DEPRECATION_WARNING
BOOST_BEAST_ALLOW_DEPRECATED
BOOST_FILESYSTEM_DEPRECATED
>
$<$<BOOL:${beast_no_unit_test_inline}>:BEAST_NO_UNIT_TEST_INLINE=1>
$<$<BOOL:${beast_disable_autolink}>:BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES=1>
$<$<BOOL:${single_io_service_thread}>:XRPL_SINGLE_IO_SERVICE_THREAD=1>
$<$<BOOL:${voidstar}>:ENABLE_VOIDSTAR>)
target_compile_options(
opts
INTERFACE $<$<AND:$<BOOL:${is_gcc}>,$<COMPILE_LANGUAGE:CXX>>:-Wsuggest-override>
$<$<BOOL:${is_gcc}>:-Wno-maybe-uninitialized> $<$<BOOL:${perf}>:-fno-omit-frame-pointer>
$<$<BOOL:${profile}>:-pg> $<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>)
target_link_libraries (opts
INTERFACE
$<$<BOOL:${profile}>:-pg>
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>)
target_link_libraries(opts INTERFACE $<$<BOOL:${profile}>:-pg> $<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>)
if(jemalloc)
find_package(jemalloc REQUIRED)
target_compile_definitions(opts INTERFACE PROFILE_JEMALLOC)
target_link_libraries(opts INTERFACE jemalloc::jemalloc)
if (jemalloc)
find_package(jemalloc REQUIRED)
target_compile_definitions(opts INTERFACE PROFILE_JEMALLOC)
target_link_libraries(opts INTERFACE jemalloc::jemalloc)
endif ()
#[===================================================================[
xrpld transitive library deps via an interface library
#]===================================================================]
add_library (xrpl_syslibs INTERFACE)
add_library (Xrpl::syslibs ALIAS xrpl_syslibs)
target_link_libraries (xrpl_syslibs
INTERFACE
$<$<BOOL:${is_msvc}>:
legacy_stdio_definitions.lib
Shlwapi
kernel32
user32
gdi32
winspool
comdlg32
advapi32
shell32
ole32
oleaut32
uuid
odbc32
odbccp32
crypt32
>
$<$<NOT:$<BOOL:${is_msvc}>>:dl>
$<$<NOT:$<OR:$<BOOL:${is_msvc}>,$<BOOL:${is_macos}>>>:rt>)
add_library(xrpl_syslibs INTERFACE)
add_library(Xrpl::syslibs ALIAS xrpl_syslibs)
target_link_libraries(
xrpl_syslibs
INTERFACE $<$<BOOL:${is_msvc}>:
legacy_stdio_definitions.lib
Shlwapi
kernel32
user32
gdi32
winspool
comdlg32
advapi32
shell32
ole32
oleaut32
uuid
odbc32
odbccp32
crypt32
>
$<$<NOT:$<BOOL:${is_msvc}>>:dl>
$<$<NOT:$<OR:$<BOOL:${is_msvc}>,$<BOOL:${is_macos}>>>:rt>)
if (NOT is_msvc)
set (THREADS_PREFER_PTHREAD_FLAG ON)
find_package (Threads)
target_link_libraries (xrpl_syslibs INTERFACE Threads::Threads)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads)
target_link_libraries(xrpl_syslibs INTERFACE Threads::Threads)
endif ()
add_library (xrpl_libs INTERFACE)
add_library (Xrpl::libs ALIAS xrpl_libs)
target_link_libraries (xrpl_libs INTERFACE Xrpl::syslibs)
add_library(xrpl_libs INTERFACE)
add_library(Xrpl::libs ALIAS xrpl_libs)
target_link_libraries(xrpl_libs INTERFACE Xrpl::syslibs)

View File

@@ -44,23 +44,23 @@ include(CompilationEnv)
# Read environment variable
set(SANITIZERS "")
if(DEFINED ENV{SANITIZERS})
set(SANITIZERS "$ENV{SANITIZERS}")
endif()
if (DEFINED ENV{SANITIZERS})
set(SANITIZERS "$ENV{SANITIZERS}")
endif ()
# Set SANITIZERS_ENABLED flag for use in other modules
if(SANITIZERS MATCHES "address|thread|undefinedbehavior")
if (SANITIZERS MATCHES "address|thread|undefinedbehavior")
set(SANITIZERS_ENABLED TRUE)
else()
else ()
set(SANITIZERS_ENABLED FALSE)
return()
endif()
endif ()
# Sanitizers are not supported on Windows/MSVC
if(is_msvc)
if (is_msvc)
message(FATAL_ERROR "Sanitizers are not supported on Windows/MSVC. "
"Please unset the SANITIZERS environment variable.")
endif()
"Please unset the SANITIZERS environment variable.")
endif ()
message(STATUS "Configuring sanitizers: ${SANITIZERS}")
@@ -74,24 +74,24 @@ set(san_list "${SANITIZERS}")
string(REPLACE "," ";" san_list "${san_list}")
separate_arguments(san_list)
foreach(san IN LISTS san_list)
if(san STREQUAL "address")
foreach (san IN LISTS san_list)
if (san STREQUAL "address")
set(enable_asan TRUE)
elseif(san STREQUAL "thread")
elseif (san STREQUAL "thread")
set(enable_tsan TRUE)
elseif(san STREQUAL "undefinedbehavior")
elseif (san STREQUAL "undefinedbehavior")
set(enable_ubsan TRUE)
else()
else ()
message(FATAL_ERROR "Unsupported sanitizer type: ${san}"
"Supported: address, thread, undefinedbehavior and their combinations.")
endif()
endforeach()
"Supported: address, thread, undefinedbehavior and their combinations.")
endif ()
endforeach ()
# Validate sanitizer compatibility
if(enable_asan AND enable_tsan)
if (enable_asan AND enable_tsan)
message(FATAL_ERROR "AddressSanitizer and ThreadSanitizer are incompatible and cannot be enabled simultaneously. "
"Use 'address' or 'thread', optionally with 'undefinedbehavior'.")
endif()
"Use 'address' or 'thread', optionally with 'undefinedbehavior'.")
endif ()
# Frame pointer is required for meaningful stack traces. Sanitizers recommend minimum of -O1 for reasonable performance
set(SANITIZERS_COMPILE_FLAGS "-fno-omit-frame-pointer" "-O1")
@@ -99,31 +99,31 @@ set(SANITIZERS_COMPILE_FLAGS "-fno-omit-frame-pointer" "-O1")
# Build the sanitizer flags list
set(SANITIZER_TYPES)
if(enable_asan)
if (enable_asan)
list(APPEND SANITIZER_TYPES "address")
elseif(enable_tsan)
elseif (enable_tsan)
list(APPEND SANITIZER_TYPES "thread")
endif()
endif ()
if(enable_ubsan)
if (enable_ubsan)
# UB sanitizer flags
list(APPEND SANITIZER_TYPES "undefined" "float-divide-by-zero")
if(is_clang)
# Clang supports additional UB checks. More info here https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
if (is_clang)
# Clang supports additional UB checks. More info here
# https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
list(APPEND SANITIZER_TYPES "unsigned-integer-overflow")
endif()
endif()
endif ()
endif ()
# Configure code model for GCC on amd64
# Use large code model for ASAN to avoid relocation errors
# Use medium code model for TSAN (large is not compatible with TSAN)
# Configure code model for GCC on amd64 Use large code model for ASAN to avoid relocation errors Use medium code model
# for TSAN (large is not compatible with TSAN)
set(SANITIZERS_RELOCATION_FLAGS)
# Compiler-specific configuration
if(is_gcc)
# Disable mold, gold and lld linkers for GCC with sanitizers
# Use default linker (bfd/ld) which is more lenient with mixed code models
# This is needed since the size of instrumented binary exceeds the limits set by mold, lld and gold linkers
if (is_gcc)
# Disable mold, gold and lld linkers for GCC with sanitizers Use default linker (bfd/ld) which is more lenient with
# mixed code models This is needed since the size of instrumented binary exceeds the limits set by mold, lld and
# gold linkers
set(use_mold OFF CACHE BOOL "Use mold linker" FORCE)
set(use_gold OFF CACHE BOOL "Use gold linker" FORCE)
set(use_lld OFF CACHE BOOL "Use lld linker" FORCE)
@@ -132,17 +132,17 @@ if(is_gcc)
# Suppress false positive warnings in GCC with stringop-overflow
list(APPEND SANITIZERS_COMPILE_FLAGS "-Wno-stringop-overflow")
if(is_amd64 AND enable_asan)
if (is_amd64 AND enable_asan)
message(STATUS " Using large code model (-mcmodel=large)")
list(APPEND SANITIZERS_COMPILE_FLAGS "-mcmodel=large")
list(APPEND SANITIZERS_RELOCATION_FLAGS "-mcmodel=large")
elseif(enable_tsan)
elseif (enable_tsan)
# GCC doesn't support atomic_thread_fence with tsan. Suppress warnings.
list(APPEND SANITIZERS_COMPILE_FLAGS "-Wno-tsan")
message(STATUS " Using medium code model (-mcmodel=medium)")
list(APPEND SANITIZERS_COMPILE_FLAGS "-mcmodel=medium")
list(APPEND SANITIZERS_RELOCATION_FLAGS "-mcmodel=medium")
endif()
endif ()
# Join sanitizer flags with commas for -fsanitize option
list(JOIN SANITIZER_TYPES "," SANITIZER_TYPES_STR)
@@ -151,13 +151,12 @@ if(is_gcc)
list(APPEND SANITIZERS_COMPILE_FLAGS "-fsanitize=${SANITIZER_TYPES_STR}")
set(SANITIZERS_LINK_FLAGS "${SANITIZERS_RELOCATION_FLAGS}" "-fsanitize=${SANITIZER_TYPES_STR}")
elseif(is_clang)
# Add ignorelist for Clang (GCC doesn't support this)
# Use CMAKE_SOURCE_DIR to get the path to the ignorelist
elseif (is_clang)
# Add ignorelist for Clang (GCC doesn't support this) Use CMAKE_SOURCE_DIR to get the path to the ignorelist
set(IGNORELIST_PATH "${CMAKE_SOURCE_DIR}/sanitizers/suppressions/sanitizer-ignorelist.txt")
if(NOT EXISTS "${IGNORELIST_PATH}")
if (NOT EXISTS "${IGNORELIST_PATH}")
message(FATAL_ERROR "Sanitizer ignorelist not found: ${IGNORELIST_PATH}")
endif()
endif ()
list(APPEND SANITIZERS_COMPILE_FLAGS "-fsanitize-ignorelist=${IGNORELIST_PATH}")
message(STATUS " Using sanitizer ignorelist: ${IGNORELIST_PATH}")
@@ -168,34 +167,31 @@ elseif(is_clang)
# Add sanitizer to compile and link flags
list(APPEND SANITIZERS_COMPILE_FLAGS "-fsanitize=${SANITIZER_TYPES_STR}")
set(SANITIZERS_LINK_FLAGS "-fsanitize=${SANITIZER_TYPES_STR}")
endif()
endif ()
message(STATUS " Compile flags: ${SANITIZERS_COMPILE_FLAGS}")
message(STATUS " Link flags: ${SANITIZERS_LINK_FLAGS}")
# Apply the sanitizer flags to the 'common' interface library
# This is the same library used by XrplCompiler.cmake
target_compile_options(common INTERFACE
$<$<COMPILE_LANGUAGE:CXX>:${SANITIZERS_COMPILE_FLAGS}>
$<$<COMPILE_LANGUAGE:C>:${SANITIZERS_COMPILE_FLAGS}>
)
# Apply the sanitizer flags to the 'common' interface library This is the same library used by XrplCompiler.cmake
target_compile_options(common INTERFACE $<$<COMPILE_LANGUAGE:CXX>:${SANITIZERS_COMPILE_FLAGS}>
$<$<COMPILE_LANGUAGE:C>:${SANITIZERS_COMPILE_FLAGS}>)
# Apply linker flags
target_link_options(common INTERFACE ${SANITIZERS_LINK_FLAGS})
# Define SANITIZERS macro for BuildInfo.cpp
set(sanitizers_list)
if(enable_asan)
if (enable_asan)
list(APPEND sanitizers_list "ASAN")
endif()
if(enable_tsan)
endif ()
if (enable_tsan)
list(APPEND sanitizers_list "TSAN")
endif()
if(enable_ubsan)
endif ()
if (enable_ubsan)
list(APPEND sanitizers_list "UBSAN")
endif()
endif ()
if(sanitizers_list)
if (sanitizers_list)
list(JOIN sanitizers_list "." sanitizers_str)
target_compile_definitions(common INTERFACE SANITIZERS=${sanitizers_str})
endif()
endif ()

View File

@@ -6,40 +6,39 @@ include(CompilationEnv)
get_property(is_multiconfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
set (CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE)
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE)
if (NOT is_multiconfig)
if (NOT CMAKE_BUILD_TYPE)
message (STATUS "Build type not specified - defaulting to Release")
set (CMAKE_BUILD_TYPE Release CACHE STRING "build type" FORCE)
elseif (NOT (CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_BUILD_TYPE STREQUAL Release))
# for simplicity, these are the only two config types we care about. Limiting
# the build types simplifies dealing with external project builds especially
message (FATAL_ERROR " *** Only Debug or Release build types are currently supported ***")
endif ()
if (NOT CMAKE_BUILD_TYPE)
message(STATUS "Build type not specified - defaulting to Release")
set(CMAKE_BUILD_TYPE Release CACHE STRING "build type" FORCE)
elseif (NOT (CMAKE_BUILD_TYPE STREQUAL Debug OR CMAKE_BUILD_TYPE STREQUAL Release))
# for simplicity, these are the only two config types we care about. Limiting the build types simplifies dealing
# with external project builds especially
message(FATAL_ERROR " *** Only Debug or Release build types are currently supported ***")
endif ()
endif ()
if (is_clang) # both Clang and AppleClang
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND
CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0)
message (FATAL_ERROR "This project requires clang 16 or later")
endif ()
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0)
message(FATAL_ERROR "This project requires clang 16 or later")
endif ()
elseif (is_gcc)
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0)
message (FATAL_ERROR "This project requires GCC 12 or later")
endif ()
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0)
message(FATAL_ERROR "This project requires GCC 12 or later")
endif ()
endif ()
# check for in-source build and fail
if ("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
message (FATAL_ERROR "Builds (in-source) are not allowed in "
"${CMAKE_CURRENT_SOURCE_DIR}. Please remove CMakeCache.txt and the CMakeFiles "
"directory from ${CMAKE_CURRENT_SOURCE_DIR} and try building in a separate directory.")
message(FATAL_ERROR "Builds (in-source) are not allowed in "
"${CMAKE_CURRENT_SOURCE_DIR}. Please remove CMakeCache.txt and the CMakeFiles "
"directory from ${CMAKE_CURRENT_SOURCE_DIR} and try building in a separate directory.")
endif ()
if (MSVC AND CMAKE_GENERATOR_PLATFORM STREQUAL "Win32")
message (FATAL_ERROR "Visual Studio 32-bit build is not supported.")
message(FATAL_ERROR "Visual Studio 32-bit build is not supported.")
endif ()
if (APPLE AND NOT HOMEBREW)
find_program (HOMEBREW brew)
find_program(HOMEBREW brew)
endif ()

View File

@@ -5,125 +5,110 @@
include(CompilationEnv)
set(is_ci FALSE)
if(DEFINED ENV{CI})
if("$ENV{CI}" STREQUAL "true")
set(is_ci TRUE)
endif()
endif()
if (DEFINED ENV{CI})
if ("$ENV{CI}" STREQUAL "true")
set(is_ci TRUE)
endif ()
endif ()
get_directory_property(has_parent PARENT_DIRECTORY)
if(has_parent)
set(is_root_project OFF)
else()
set(is_root_project ON)
endif()
if (has_parent)
set(is_root_project OFF)
else ()
set(is_root_project ON)
endif ()
option(assert "Enables asserts, even in release builds" OFF)
option(xrpld "Build xrpld" ON)
option(tests "Build tests" ON)
if(tests)
# This setting allows making a separate workflow to test fees other than default 10
if(NOT UNIT_TEST_REFERENCE_FEE)
set(UNIT_TEST_REFERENCE_FEE "10" CACHE STRING "")
endif()
endif()
if (tests)
# This setting allows making a separate workflow to test fees other than default 10
if (NOT UNIT_TEST_REFERENCE_FEE)
set(UNIT_TEST_REFERENCE_FEE "10" CACHE STRING "")
endif ()
endif ()
option(unity "Creates a build using UNITY support in cmake." OFF)
if(unity)
if(NOT is_ci)
set(CMAKE_UNITY_BUILD_BATCH_SIZE 15 CACHE STRING "")
endif()
set(CMAKE_UNITY_BUILD ON CACHE BOOL "Do a unity build")
endif()
if (unity)
if (NOT is_ci)
set(CMAKE_UNITY_BUILD_BATCH_SIZE 15 CACHE STRING "")
endif ()
set(CMAKE_UNITY_BUILD ON CACHE BOOL "Do a unity build")
endif ()
if(is_clang AND is_linux)
option(voidstar "Enable Antithesis instrumentation." OFF)
endif()
if (is_clang AND is_linux)
option(voidstar "Enable Antithesis instrumentation." OFF)
endif ()
if(is_gcc OR is_clang)
include(ProcessorCount)
ProcessorCount(PROCESSOR_COUNT)
if (is_gcc OR is_clang)
include(ProcessorCount)
ProcessorCount(PROCESSOR_COUNT)
option(coverage "Generates coverage info." OFF)
option(profile "Add profiling flags" OFF)
set(coverage_format "html-details" CACHE STRING
"Output format of the coverage report.")
set(coverage_extra_args "" CACHE STRING
"Additional arguments to pass to gcovr.")
option(wextra "compile with extra gcc/clang warnings enabled" ON)
else()
set(profile OFF CACHE BOOL "gcc/clang only" FORCE)
set(coverage OFF CACHE BOOL "gcc/clang only" FORCE)
set(wextra OFF CACHE BOOL "gcc/clang only" FORCE)
endif()
option(coverage "Generates coverage info." OFF)
option(profile "Add profiling flags" OFF)
set(coverage_format "html-details" CACHE STRING "Output format of the coverage report.")
set(coverage_extra_args "" CACHE STRING "Additional arguments to pass to gcovr.")
option(wextra "compile with extra gcc/clang warnings enabled" ON)
else ()
set(profile OFF CACHE BOOL "gcc/clang only" FORCE)
set(coverage OFF CACHE BOOL "gcc/clang only" FORCE)
set(wextra OFF CACHE BOOL "gcc/clang only" FORCE)
endif ()
if(is_linux AND NOT SANITIZER)
option(BUILD_SHARED_LIBS "build shared xrpl libraries" OFF)
option(static "link protobuf, openssl, libc++, and boost statically" ON)
option(perf "Enables flags that assist with perf recording" OFF)
option(use_gold "enables detection of gold (binutils) linker" ON)
option(use_mold "enables detection of mold (binutils) linker" ON)
# Set a default value for the log flag based on the build type.
# This provides a sensible default (on for debug, off for release)
# while still allowing the user to override it for any build.
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(TRUNCATED_LOGS_DEFAULT ON)
else()
set(TRUNCATED_LOGS_DEFAULT OFF)
endif()
option(TRUNCATED_THREAD_NAME_LOGS
"Show warnings about truncated thread names on Linux."
${TRUNCATED_LOGS_DEFAULT}
)
if(TRUNCATED_THREAD_NAME_LOGS)
add_compile_definitions(TRUNCATED_THREAD_NAME_LOGS)
endif()
else()
# we are not ready to allow shared-libs on windows because it would require
# export declarations. On macos it's more feasible, but static openssl
# produces odd linker errors, thus we disable shared lib builds for now.
set(BUILD_SHARED_LIBS OFF CACHE BOOL "build shared xrpl libraries - OFF for win/macos" FORCE)
set(static ON CACHE BOOL "static link, linux only. ON for WIN/macos" FORCE)
set(perf OFF CACHE BOOL "perf flags, linux only" FORCE)
set(use_gold OFF CACHE BOOL "gold linker, linux only" FORCE)
set(use_mold OFF CACHE BOOL "mold linker, linux only" FORCE)
endif()
if (is_linux AND NOT SANITIZER)
option(BUILD_SHARED_LIBS "build shared xrpl libraries" OFF)
option(static "link protobuf, openssl, libc++, and boost statically" ON)
option(perf "Enables flags that assist with perf recording" OFF)
option(use_gold "enables detection of gold (binutils) linker" ON)
option(use_mold "enables detection of mold (binutils) linker" ON)
# Set a default value for the log flag based on the build type. This provides a sensible default (on for debug, off
# for release) while still allowing the user to override it for any build.
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(TRUNCATED_LOGS_DEFAULT ON)
else ()
set(TRUNCATED_LOGS_DEFAULT OFF)
endif ()
option(TRUNCATED_THREAD_NAME_LOGS "Show warnings about truncated thread names on Linux." ${TRUNCATED_LOGS_DEFAULT})
if (TRUNCATED_THREAD_NAME_LOGS)
add_compile_definitions(TRUNCATED_THREAD_NAME_LOGS)
endif ()
else ()
# we are not ready to allow shared-libs on windows because it would require export declarations. On macos it's more
# feasible, but static openssl produces odd linker errors, thus we disable shared lib builds for now.
set(BUILD_SHARED_LIBS OFF CACHE BOOL "build shared xrpl libraries - OFF for win/macos" FORCE)
set(static ON CACHE BOOL "static link, linux only. ON for WIN/macos" FORCE)
set(perf OFF CACHE BOOL "perf flags, linux only" FORCE)
set(use_gold OFF CACHE BOOL "gold linker, linux only" FORCE)
set(use_mold OFF CACHE BOOL "mold linker, linux only" FORCE)
endif ()
if(is_clang)
option(use_lld "enables detection of lld linker" ON)
else()
set(use_lld OFF CACHE BOOL "try lld linker, clang only" FORCE)
endif()
if (is_clang)
option(use_lld "enables detection of lld linker" ON)
else ()
set(use_lld OFF CACHE BOOL "try lld linker, clang only" FORCE)
endif ()
option(jemalloc "Enables jemalloc for heap profiling" OFF)
option(werr "treat warnings as errors" OFF)
option(local_protobuf
"Force a local build of protobuf instead of looking for an installed version." OFF)
option(local_grpc
"Force a local build of gRPC instead of looking for an installed version." OFF)
option(local_protobuf "Force a local build of protobuf instead of looking for an installed version." OFF)
option(local_grpc "Force a local build of gRPC instead of looking for an installed version." OFF)
# the remaining options are obscure and rarely used
option(beast_no_unit_test_inline
"Prevents unit test definitions from being inserted into global table"
OFF)
option(single_io_service_thread
"Restricts the number of threads calling io_context::run to one. \
This can be useful when debugging."
OFF)
option(boost_show_deprecated
"Allow boost to fail on deprecated usage. Only useful if you're trying\
to find deprecated calls."
OFF)
option(beast_no_unit_test_inline "Prevents unit test definitions from being inserted into global table" OFF)
option(single_io_service_thread "Restricts the number of threads calling io_context::run to one. \
This can be useful when debugging." OFF)
option(boost_show_deprecated "Allow boost to fail on deprecated usage. Only useful if you're trying\
to find deprecated calls." OFF)
if(WIN32)
option(beast_disable_autolink "Disables autolinking of system libraries on WIN32" OFF)
else()
set(beast_disable_autolink OFF CACHE BOOL "WIN32 only" FORCE)
endif()
if (WIN32)
option(beast_disable_autolink "Disables autolinking of system libraries on WIN32" OFF)
else ()
set(beast_disable_autolink OFF CACHE BOOL "WIN32 only" FORCE)
endif ()
if(coverage)
message(STATUS "coverage build requested - forcing Debug build")
set(CMAKE_BUILD_TYPE Debug CACHE STRING "build type" FORCE)
endif()
if (coverage)
message(STATUS "coverage build requested - forcing Debug build")
set(CMAKE_BUILD_TYPE Debug CACHE STRING "build type" FORCE)
endif ()

View File

@@ -1,20 +1,17 @@
option (validator_keys "Enables building of validator-keys tool as a separate target (imported via FetchContent)" OFF)
option(validator_keys "Enables building of validator-keys tool as a separate target (imported via FetchContent)" OFF)
if (validator_keys)
git_branch (current_branch)
# default to tracking VK master branch unless we are on release
if (NOT (current_branch STREQUAL "release"))
set (current_branch "master")
endif ()
message (STATUS "Tracking ValidatorKeys branch: ${current_branch}")
git_branch(current_branch)
# default to tracking VK master branch unless we are on release
if (NOT (current_branch STREQUAL "release"))
set(current_branch "master")
endif ()
message(STATUS "Tracking ValidatorKeys branch: ${current_branch}")
FetchContent_Declare (
validator_keys
GIT_REPOSITORY https://github.com/ripple/validator-keys-tool.git
GIT_TAG "${current_branch}"
)
FetchContent_MakeAvailable(validator_keys)
set_target_properties(validator-keys PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
install(TARGETS validator-keys RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
FetchContent_Declare(validator_keys GIT_REPOSITORY https://github.com/ripple/validator-keys-tool.git
GIT_TAG "${current_branch}")
FetchContent_MakeAvailable(validator_keys)
set_target_properties(validator-keys PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
install(TARGETS validator-keys RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif ()

View File

@@ -3,13 +3,13 @@
#]===================================================================]
file(STRINGS src/libxrpl/protocol/BuildInfo.cpp BUILD_INFO)
foreach(line_ ${BUILD_INFO})
if(line_ MATCHES "versionString[ ]*=[ ]*\"(.+)\"")
set(xrpld_version ${CMAKE_MATCH_1})
endif()
endforeach()
if(xrpld_version)
message(STATUS "xrpld version: ${xrpld_version}")
else()
message(FATAL_ERROR "unable to determine xrpld version")
endif()
foreach (line_ ${BUILD_INFO})
if (line_ MATCHES "versionString[ ]*=[ ]*\"(.+)\"")
set(xrpld_version ${CMAKE_MATCH_1})
endif ()
endforeach ()
if (xrpld_version)
message(STATUS "xrpld version: ${xrpld_version}")
else ()
message(FATAL_ERROR "unable to determine xrpld version")
endif ()

View File

@@ -12,26 +12,14 @@ include(isolate_headers)
# add_module(parent a)
# add_module(parent b)
# target_link_libraries(project.libparent.b PUBLIC project.libparent.a)
function(add_module parent name)
set(target ${PROJECT_NAME}.lib${parent}.${name})
add_library(${target} OBJECT)
file(GLOB_RECURSE sources CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/src/lib${parent}/${name}/*.cpp"
)
target_sources(${target} PRIVATE ${sources})
target_include_directories(${target} PUBLIC
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)
isolate_headers(
${target}
"${CMAKE_CURRENT_SOURCE_DIR}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/include/${parent}/${name}"
PUBLIC
)
isolate_headers(
${target}
"${CMAKE_CURRENT_SOURCE_DIR}/src"
"${CMAKE_CURRENT_SOURCE_DIR}/src/lib${parent}/${name}"
PRIVATE
)
endfunction()
function (add_module parent name)
set(target ${PROJECT_NAME}.lib${parent}.${name})
add_library(${target} OBJECT)
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/lib${parent}/${name}/*.cpp")
target_sources(${target} PRIVATE ${sources})
target_include_directories(${target} PUBLIC "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
isolate_headers(${target} "${CMAKE_CURRENT_SOURCE_DIR}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/include/${parent}/${name}" PUBLIC)
isolate_headers(${target} "${CMAKE_CURRENT_SOURCE_DIR}/src" "${CMAKE_CURRENT_SOURCE_DIR}/src/lib${parent}/${name}"
PRIVATE)
endfunction ()

View File

@@ -1,20 +1,19 @@
# file(CREATE_SYMLINK) only works on Windows with administrator privileges.
# https://stackoverflow.com/a/61244115/618906
function(create_symbolic_link target link)
if(WIN32)
if(NOT IS_SYMLINK "${link}")
if(NOT IS_ABSOLUTE "${target}")
# Relative links work do not work on Windows.
set(target "${link}/../${target}")
endif()
file(TO_NATIVE_PATH "${target}" target)
file(TO_NATIVE_PATH "${link}" link)
execute_process(COMMAND cmd.exe /c mklink /J "${link}" "${target}")
endif()
else()
file(CREATE_LINK "${target}" "${link}" SYMBOLIC)
endif()
if(NOT IS_SYMLINK "${link}")
message(ERROR "failed to create symlink: <${link}>")
endif()
endfunction()
# file(CREATE_SYMLINK) only works on Windows with administrator privileges. https://stackoverflow.com/a/61244115/618906
function (create_symbolic_link target link)
if (WIN32)
if (NOT IS_SYMLINK "${link}")
if (NOT IS_ABSOLUTE "${target}")
# Relative links work do not work on Windows.
set(target "${link}/../${target}")
endif ()
file(TO_NATIVE_PATH "${target}" target)
file(TO_NATIVE_PATH "${link}" link)
execute_process(COMMAND cmd.exe /c mklink /J "${link}" "${target}")
endif ()
else ()
file(CREATE_LINK "${target}" "${link}" SYMBOLIC)
endif ()
if (NOT IS_SYMLINK "${link}")
message(ERROR "failed to create symlink: <${link}>")
endif ()
endfunction ()

View File

@@ -2,48 +2,43 @@ include(CompilationEnv)
include(XrplSanitizers)
find_package(Boost REQUIRED
COMPONENTS
chrono
container
coroutine
date_time
filesystem
json
program_options
regex
system
thread
)
COMPONENTS chrono
container
coroutine
date_time
filesystem
json
program_options
regex
system
thread)
add_library(xrpl_boost INTERFACE)
add_library(Xrpl::boost ALIAS xrpl_boost)
target_link_libraries(xrpl_boost
INTERFACE
Boost::headers
Boost::chrono
Boost::container
Boost::coroutine
Boost::date_time
Boost::filesystem
Boost::json
Boost::process
Boost::program_options
Boost::regex
Boost::thread)
if(Boost_COMPILER)
target_link_libraries(xrpl_boost INTERFACE Boost::disable_autolinking)
endif()
if(SANITIZERS_ENABLED AND is_clang)
# TODO: gcc does not support -fsanitize-blacklist...can we do something else
# for gcc ?
if(NOT Boost_INCLUDE_DIRS AND TARGET Boost::headers)
get_target_property(Boost_INCLUDE_DIRS Boost::headers INTERFACE_INCLUDE_DIRECTORIES)
endif()
message(STATUS "Adding [${Boost_INCLUDE_DIRS}] to sanitizer blacklist")
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/san_bl.txt "src:${Boost_INCLUDE_DIRS}/*")
target_compile_options(opts
INTERFACE
# ignore boost headers for sanitizing
-fsanitize-blacklist=${CMAKE_CURRENT_BINARY_DIR}/san_bl.txt)
endif()
target_link_libraries(
xrpl_boost
INTERFACE Boost::headers
Boost::chrono
Boost::container
Boost::coroutine
Boost::date_time
Boost::filesystem
Boost::json
Boost::process
Boost::program_options
Boost::regex
Boost::thread)
if (Boost_COMPILER)
target_link_libraries(xrpl_boost INTERFACE Boost::disable_autolinking)
endif ()
if (SANITIZERS_ENABLED AND is_clang)
# TODO: gcc does not support -fsanitize-blacklist...can we do something else for gcc ?
if (NOT Boost_INCLUDE_DIRS AND TARGET Boost::headers)
get_target_property(Boost_INCLUDE_DIRS Boost::headers INTERFACE_INCLUDE_DIRECTORIES)
endif ()
message(STATUS "Adding [${Boost_INCLUDE_DIRS}] to sanitizer blacklist")
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/san_bl.txt "src:${Boost_INCLUDE_DIRS}/*")
target_compile_options(opts INTERFACE # ignore boost headers for sanitizing
-fsanitize-blacklist=${CMAKE_CURRENT_BINARY_DIR}/san_bl.txt)
endif ()

View File

@@ -37,12 +37,12 @@ include(create_symbolic_link)
# `${CMAKE_CURRENT_BINARY_DIR}/include/${target}`.
#
# isolate_headers(target A B scope)
function(isolate_headers target A B scope)
file(RELATIVE_PATH C "${A}" "${B}")
set(X "${CMAKE_CURRENT_BINARY_DIR}/modules/${target}")
set(Y "${X}/${C}")
cmake_path(GET Y PARENT_PATH parent)
file(MAKE_DIRECTORY "${parent}")
create_symbolic_link("${B}" "${Y}")
target_include_directories(${target} ${scope} "$<BUILD_INTERFACE:${X}>")
endfunction()
function (isolate_headers target A B scope)
file(RELATIVE_PATH C "${A}" "${B}")
set(X "${CMAKE_CURRENT_BINARY_DIR}/modules/${target}")
set(Y "${X}/${C}")
cmake_path(GET Y PARENT_PATH parent)
file(MAKE_DIRECTORY "${parent}")
create_symbolic_link("${B}" "${Y}")
target_include_directories(${target} ${scope} "$<BUILD_INTERFACE:${X}>")
endfunction ()

View File

@@ -6,19 +6,19 @@
# target_link_libraries(project.libparent.b PUBLIC project.libparent.a)
# add_library(project.libparent)
# target_link_modules(parent PUBLIC a b)
function(target_link_modules parent scope)
set(library ${PROJECT_NAME}.lib${parent})
foreach(name ${ARGN})
set(module ${library}.${name})
get_target_property(sources ${library} SOURCES)
list(LENGTH sources before)
get_target_property(dupes ${module} SOURCES)
list(LENGTH dupes expected)
list(REMOVE_ITEM sources ${dupes})
list(LENGTH sources after)
math(EXPR actual "${before} - ${after}")
message(STATUS "${module} with ${expected} sources took ${actual} sources from ${library}")
set_target_properties(${library} PROPERTIES SOURCES "${sources}")
target_link_libraries(${library} ${scope} ${module})
endforeach()
endfunction()
function (target_link_modules parent scope)
set(library ${PROJECT_NAME}.lib${parent})
foreach (name ${ARGN})
set(module ${library}.${name})
get_target_property(sources ${library} SOURCES)
list(LENGTH sources before)
get_target_property(dupes ${module} SOURCES)
list(LENGTH dupes expected)
list(REMOVE_ITEM sources ${dupes})
list(LENGTH sources after)
math(EXPR actual "${before} - ${after}")
message(STATUS "${module} with ${expected} sources took ${actual} sources from ${library}")
set_target_properties(${library} PROPERTIES SOURCES "${sources}")
target_link_libraries(${library} ${scope} ${module})
endforeach ()
endfunction ()

View File

@@ -35,28 +35,20 @@ find_package(Protobuf REQUIRED)
# This prefix should appear at the start of all your consumer includes.
# ARGN:
# A list of .proto files.
function(target_protobuf_sources target prefix)
set(dir "${CMAKE_CURRENT_BINARY_DIR}/pb-${target}")
file(MAKE_DIRECTORY "${dir}/${prefix}")
function (target_protobuf_sources target prefix)
set(dir "${CMAKE_CURRENT_BINARY_DIR}/pb-${target}")
file(MAKE_DIRECTORY "${dir}/${prefix}")
protobuf_generate(
TARGET ${target}
PROTOC_OUT_DIR "${dir}/${prefix}"
"${ARGN}"
)
target_include_directories(${target} SYSTEM PUBLIC
# Allows #include <package/path/to/file.proto> used by consumer files.
$<BUILD_INTERFACE:${dir}>
# Allows #include "path/to/file.proto" used by generated files.
$<BUILD_INTERFACE:${dir}/${prefix}>
# Allows #include <package/path/to/file.proto> used by consumer files.
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
# Allows #include "path/to/file.proto" used by generated files.
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${prefix}>
)
install(
DIRECTORY ${dir}/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN "*.h"
)
endfunction()
protobuf_generate(TARGET ${target} PROTOC_OUT_DIR "${dir}/${prefix}" "${ARGN}")
target_include_directories(
${target} SYSTEM
PUBLIC # Allows #include <package/path/to/file.proto> used by consumer files.
$<BUILD_INTERFACE:${dir}>
# Allows #include "path/to/file.proto" used by generated files.
$<BUILD_INTERFACE:${dir}/${prefix}>
# Allows #include <package/path/to/file.proto> used by consumer files.
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
# Allows #include "path/to/file.proto" used by generated files.
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${prefix}>)
install(DIRECTORY ${dir}/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} FILES_MATCHING PATTERN "*.h")
endfunction ()

View File

@@ -3,7 +3,6 @@
"requires": [
"zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1765850150.075",
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987",
"wasmi/1.0.6#407c9db14601a8af1c7dd3b388f3e4cd%1768164779.349",
"sqlite3/3.49.1#8631739a4c9b93bd3d6b753bac548a63%1765850149.926",
"soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1765850149.46",
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1765850147.878",

View File

@@ -35,7 +35,6 @@ class Xrpl(ConanFile):
"openssl/3.5.4",
"secp256k1/0.7.0",
"soci/4.0.3",
"wasmi/1.0.6",
"zlib/1.3.1",
]
@@ -216,7 +215,6 @@ class Xrpl(ConanFile):
"soci::soci",
"secp256k1::secp256k1",
"sqlite3::sqlite",
"wasmi::wasmi",
"xxhash::xxhash",
"zlib::zlib",
]

View File

@@ -717,10 +717,6 @@ abs(Number x) noexcept
Number
power(Number const& f, unsigned n);
// logarithm with base 10
Number
log10(Number const& value, int iterations = 50);
// Returns f^(1/d)
// Uses NewtonRaphson iterations until the result stops changing
// to find the root of the polynomial g(x) = x^d - f

View File

@@ -49,18 +49,6 @@ public:
deliver_ = amount;
}
void
setGasUsed(std::optional<std::uint32_t> const gasUsed)
{
gasUsed_ = gasUsed;
}
void
setWasmReturnCode(std::int32_t const wasmReturnCode)
{
wasmReturnCode_ = wasmReturnCode;
}
/** Get the number of modified entries
*/
std::size_t
@@ -79,8 +67,6 @@ public:
private:
std::optional<STAmount> deliver_;
std::optional<std::uint32_t> gasUsed_;
std::optional<std::int32_t> wasmReturnCode_;
};
} // namespace xrpl

View File

@@ -53,8 +53,6 @@ public:
TER ter,
std::optional<STAmount> const& deliver,
std::optional<uint256 const> const& parentBatchId,
std::optional<std::uint32_t> const& gasUsed,
std::optional<std::int32_t> const& wasmReturnCode,
bool isDryRun,
beast::Journal j);

View File

@@ -5,8 +5,6 @@
namespace xrpl {
constexpr std::uint32_t MICRO_DROPS_PER_DROP{1'000'000};
/** Reflects the fee settings for a particular ledger.
The fees are always the same for any transactions applied
@@ -14,12 +12,9 @@ constexpr std::uint32_t MICRO_DROPS_PER_DROP{1'000'000};
*/
struct Fees
{
XRPAmount base{0}; // Reference tx cost (drops)
XRPAmount reserve{0}; // Reserve base (drops)
XRPAmount increment{0}; // Reserve increment (drops)
std::uint32_t extensionComputeLimit{0}; // Extension compute limit (instructions)
std::uint32_t extensionSizeLimit{0}; // Extension size limit (bytes)
std::uint32_t gasPrice{0}; // price of WASM gas (micro-drops)
XRPAmount base{0}; // Reference tx cost (drops)
XRPAmount reserve{0}; // Reserve base (drops)
XRPAmount increment{0}; // Reserve increment (drops)
explicit Fees() = default;
Fees(Fees const&) = default;

View File

@@ -206,12 +206,6 @@ page(Keylet const& root, std::uint64_t index = 0) noexcept
Keylet
escrow(AccountID const& src, std::uint32_t seq) noexcept;
inline Keylet
escrow(uint256 const& key) noexcept
{
return {ltESCROW, key};
}
/** A PaymentChannel */
Keylet
payChan(AccountID const& src, AccountID const& dst, std::uint32_t seq) noexcept;

View File

@@ -251,13 +251,6 @@ std::uint8_t constexpr vaultMaximumIOUScale = 18;
* another vault; counted from 0 */
std::uint8_t constexpr maxAssetCheckDepth = 5;
/** The maximum length of a Data field in Escrow object that can be updated by
* Wasm code */
std::size_t constexpr maxWasmDataLength = 4 * 1024;
/** The maximum length of a parameters passed from Wasm code*/
std::size_t constexpr maxWasmParamLength = 1024;
/** A ledger index. */
using LedgerIndex = std::uint32_t;

View File

@@ -122,8 +122,6 @@ enum TEMcodes : TERUnderlyingType {
temARRAY_TOO_LARGE,
temBAD_TRANSFER_FEE,
temINVALID_INNER_BATCH,
temBAD_WASM,
};
//------------------------------------------------------------------------------
@@ -168,8 +166,6 @@ enum TEFcodes : TERUnderlyingType {
tefNO_TICKET,
tefNFTOKEN_IS_NOT_TRANSFERABLE,
tefINVALID_LEDGER_FIX_TYPE,
tefNO_WASM,
tefWASM_FIELD_NOT_INCLUDED,
};
//------------------------------------------------------------------------------
@@ -351,7 +347,6 @@ enum TECcodes : TERUnderlyingType {
// backward compatibility with historical data on non-prod networks, can be
// reclaimed after those networks reset.
tecNO_DELEGATE_PERMISSION = 198,
tecWASM_REJECTED = 199,
};
//------------------------------------------------------------------------------

View File

@@ -85,12 +85,6 @@ public:
if (obj.isFieldPresent(sfParentBatchID))
parentBatchID_ = obj.getFieldH256(sfParentBatchID);
if (obj.isFieldPresent(sfGasUsed))
gasUsed_ = obj.getFieldU32(sfGasUsed);
if (obj.isFieldPresent(sfWasmReturnCode))
wasmReturnCode_ = obj.getFieldI32(sfWasmReturnCode);
}
std::optional<STAmount> const&
@@ -111,30 +105,6 @@ public:
parentBatchID_ = id;
}
void
setGasUsed(std::optional<std::uint32_t> const gasUsed)
{
gasUsed_ = gasUsed;
}
std::optional<std::uint32_t> const&
getGasUsed() const
{
return gasUsed_;
}
void
setWasmReturnCode(std::optional<std::int32_t> const wasmReturnCode)
{
wasmReturnCode_ = wasmReturnCode;
}
std::optional<std::int32_t> const&
getWasmReturnCode() const
{
return wasmReturnCode_;
}
private:
uint256 transactionID_;
std::uint32_t ledgerSeq_;
@@ -143,8 +113,6 @@ private:
std::optional<STAmount> deliveredAmount_;
std::optional<uint256> parentBatchID_;
std::optional<std::uint32_t> gasUsed_;
std::optional<std::int32_t> wasmReturnCode_;
STArray nodes_;
};

View File

@@ -16,7 +16,6 @@
// Add new amendments to the top of this list.
// Keep it sorted in reverse chronological order.
XRPL_FEATURE(SmartEscrow, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (BatchInnerSigs, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(LendingProtocol, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(PermissionDelegationV1_1, Supported::no, VoteBehavior::DefaultNo)
@@ -34,6 +33,7 @@ XRPL_FEATURE(PermissionedDEX, Supported::yes, VoteBehavior::DefaultNo
XRPL_FEATURE(Batch, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(SingleAssetVault, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (PayChanCancelAfter, Supported::yes, VoteBehavior::DefaultNo)
// Check flags in Credential transactions
XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (FrozenLPTokenTransfer, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(DeepFreeze, Supported::yes, VoteBehavior::DefaultNo)

View File

@@ -302,11 +302,6 @@ LEDGER_ENTRY(ltFEE_SETTINGS, 0x0073, FeeSettings, fee, ({
{sfBaseFeeDrops, soeOPTIONAL},
{sfReserveBaseDrops, soeOPTIONAL},
{sfReserveIncrementDrops, soeOPTIONAL},
// Smart Escrow fields
{sfExtensionComputeLimit, soeOPTIONAL},
{sfExtensionSizeLimit, soeOPTIONAL},
{sfGasPrice, soeOPTIONAL},
{sfPreviousTxnID, soeOPTIONAL},
{sfPreviousTxnLgrSeq, soeOPTIONAL},
}))
@@ -337,8 +332,6 @@ LEDGER_ENTRY(ltESCROW, 0x0075, Escrow, escrow, ({
{sfCondition, soeOPTIONAL},
{sfCancelAfter, soeOPTIONAL},
{sfFinishAfter, soeOPTIONAL},
{sfFinishFunction, soeOPTIONAL},
{sfData, soeOPTIONAL},
{sfSourceTag, soeOPTIONAL},
{sfDestinationTag, soeOPTIONAL},
{sfOwnerNode, soeREQUIRED},
@@ -585,7 +578,7 @@ LEDGER_ENTRY(ltLOAN, 0x0089, Loan, loan, ({
// The unrounded true total value of the loan.
//
// - TrueTotalPrincipalOutstanding can be computed using the algorithm
// in the xrpl::detail::loanPrincipalFromPeriodicPayment function.
// in the ripple::detail::loanPrincipalFromPeriodicPayment function.
//
// - TrueTotalInterestOutstanding = TrueTotalLoanValue -
// TrueTotalPrincipalOutstanding

View File

@@ -114,11 +114,6 @@ TYPED_SFIELD(sfInterestRate, UINT32, 65) // 1/10 basis points (bi
TYPED_SFIELD(sfLateInterestRate, UINT32, 66) // 1/10 basis points (bips)
TYPED_SFIELD(sfCloseInterestRate, UINT32, 67) // 1/10 basis points (bips)
TYPED_SFIELD(sfOverpaymentInterestRate, UINT32, 68) // 1/10 basis points (bips)
TYPED_SFIELD(sfExtensionComputeLimit, UINT32, 69)
TYPED_SFIELD(sfExtensionSizeLimit, UINT32, 70)
TYPED_SFIELD(sfGasPrice, UINT32, 71)
TYPED_SFIELD(sfComputationAllowance, UINT32, 72)
TYPED_SFIELD(sfGasUsed, UINT32, 73)
// 64-bit integers (common)
TYPED_SFIELD(sfIndexNext, UINT64, 1)
@@ -229,9 +224,8 @@ TYPED_SFIELD(sfTotalValueOutstanding, NUMBER, 15, SField::sMD_NeedsAsset
TYPED_SFIELD(sfPeriodicPayment, NUMBER, 16)
TYPED_SFIELD(sfManagementFeeOutstanding, NUMBER, 17, SField::sMD_NeedsAsset | SField::sMD_Default)
// 32-bit signed (common)
// int32
TYPED_SFIELD(sfLoanScale, INT32, 1)
TYPED_SFIELD(sfWasmReturnCode, INT32, 2)
// currency amount (common)
TYPED_SFIELD(sfAmount, AMOUNT, 1)
@@ -261,7 +255,7 @@ TYPED_SFIELD(sfBaseFeeDrops, AMOUNT, 22)
TYPED_SFIELD(sfReserveBaseDrops, AMOUNT, 23)
TYPED_SFIELD(sfReserveIncrementDrops, AMOUNT, 24)
// currency amount (more)
// currency amount (AMM)
TYPED_SFIELD(sfLPTokenOut, AMOUNT, 25)
TYPED_SFIELD(sfLPTokenIn, AMOUNT, 26)
TYPED_SFIELD(sfEPrice, AMOUNT, 27)
@@ -303,7 +297,6 @@ TYPED_SFIELD(sfAssetClass, VL, 28)
TYPED_SFIELD(sfProvider, VL, 29)
TYPED_SFIELD(sfMPTokenMetadata, VL, 30)
TYPED_SFIELD(sfCredentialType, VL, 31)
TYPED_SFIELD(sfFinishFunction, VL, 32)
// account (common)
TYPED_SFIELD(sfAccount, ACCOUNT, 1)

View File

@@ -50,13 +50,11 @@ TRANSACTION(ttESCROW_CREATE, 1, EscrowCreate,
noPriv,
({
{sfDestination, soeREQUIRED},
{sfDestinationTag, soeOPTIONAL},
{sfAmount, soeREQUIRED, soeMPTSupported},
{sfCondition, soeOPTIONAL},
{sfCancelAfter, soeOPTIONAL},
{sfFinishAfter, soeOPTIONAL},
{sfFinishFunction, soeOPTIONAL},
{sfData, soeOPTIONAL},
{sfDestinationTag, soeOPTIONAL},
}))
/** This transaction type completes an existing escrow. */
@@ -70,7 +68,6 @@ TRANSACTION(ttESCROW_FINISH, 2, EscrowFinish,
{sfFulfillment, soeOPTIONAL},
{sfCondition, soeOPTIONAL},
{sfCredentialIDs, soeOPTIONAL},
{sfComputationAllowance, soeOPTIONAL},
}))
@@ -1095,10 +1092,6 @@ TRANSACTION(ttFEE, 101, SetFee,
{sfBaseFeeDrops, soeOPTIONAL},
{sfReserveBaseDrops, soeOPTIONAL},
{sfReserveIncrementDrops, soeOPTIONAL},
// Smart Escrow fields
{sfExtensionComputeLimit, soeOPTIONAL},
{sfExtensionSizeLimit, soeOPTIONAL},
{sfGasPrice, soeOPTIONAL},
}))
/** This system-generated transaction type is used to update the network's negative UNL

View File

@@ -255,9 +255,6 @@ JSS(expected_date_UTC); // out: any (warnings)
JSS(expected_ledger_size); // out: TxQ
JSS(expiration); // out: AccountOffers, AccountChannels,
// ValidatorList, amm_info
JSS(extension_compute); // out: NetworkOps
JSS(extension_size); // out: NetworkOps
JSS(gas_price); // out: NetworkOps
JSS(fail_hard); // in: Sign, Submit
JSS(failed); // out: InboundLedger
JSS(feature); // in: Feature
@@ -712,11 +709,11 @@ JSS(write_load); // out: GetCounts
#pragma push_macro("LEDGER_ENTRY_DUPLICATE")
#undef LEDGER_ENTRY_DUPLICATE
#define LEDGER_ENTRY(tag, value, name, rpcName, fields) \
JSS(name); \
#define LEDGER_ENTRY(tag, value, name, rpcName, ...) \
JSS(name); \
JSS(rpcName);
#define LEDGER_ENTRY_DUPLICATE(tag, value, name, rpcName, fields) JSS(rpcName);
#define LEDGER_ENTRY_DUPLICATE(tag, value, name, rpcName, ...) JSS(rpcName);
#include <xrpl/protocol/detail/ledger_entries.macro>

View File

@@ -925,73 +925,6 @@ power(Number const& f, unsigned n)
return r;
}
// Series expansion method approximation of ln(x)
static Number
ln(Number const& x, int iterations = 50)
{
static Number const N0(0);
static Number const N2(2, 0);
static Number const N05(5, -1);
static Number const LN2(693'147'180'559'945'309ll, -18);
if (x <= 0)
throw std::runtime_error("Not a positive value");
else if (x == 1)
return N0;
int exponent = 0;
Number mantissa = x;
while (mantissa >= N2)
{
mantissa /= 2;
exponent += 1;
}
while (mantissa < N05)
{
mantissa *= 2;
exponent -= 1;
}
Number z = (mantissa - 1) / (mantissa + 1);
Number const zz = z * z;
Number sum;
for (int i = 1; i <= iterations; ++i)
{
sum = sum + z / (2 * i - 1);
z = z * zz;
}
return 2 * sum + exponent * LN2;
}
Number
log10(Number const& x, int iterations)
{
static Number const N0(0);
static Number const LN10(2'302'585'092'994'046ll, -15);
if (x <= 0)
throw std::runtime_error("Not a positive value");
else if (x == 1)
return N0;
if (x <= Number(10))
{
auto const r = ln(x, iterations) / LN10;
return r;
}
// (1 <= normalX < 10)
// ln(x) = ln(normalX * 10^norm) = ln(normalX) + norm * ln(10)
int diffExp = 15 + x.exponent();
Number const normalX = x / Number(1, diffExp);
auto const lnX = ln(normalX, iterations) + diffExp * LN10;
auto const lgX = lnX / LN10;
return lgX;
}
// Returns f^(1/d)
// Uses NewtonRaphson iterations until the result stops changing
// to find the non-negative root of the polynomial g(x) = x^d - f

View File

@@ -89,8 +89,6 @@ ApplyStateTable::apply(
TER ter,
std::optional<STAmount> const& deliver,
std::optional<uint256 const> const& parentBatchId,
std::optional<std::uint32_t> const& gasUsed,
std::optional<std::int32_t> const& wasmReturnCode,
bool isDryRun,
beast::Journal j)
{
@@ -105,8 +103,6 @@ ApplyStateTable::apply(
meta.setDeliveredAmount(deliver);
meta.setParentBatchID(parentBatchId);
meta.setGasUsed(gasUsed);
meta.setWasmReturnCode(wasmReturnCode);
Mods newMod;
for (auto& item : items_)

View File

@@ -15,7 +15,7 @@ ApplyViewImpl::apply(
bool isDryRun,
beast::Journal j)
{
return items_.apply(to, tx, ter, deliver_, parentBatchId, gasUsed_, wasmReturnCode_, isDryRun, j);
return items_.apply(to, tx, ter, deliver_, parentBatchId, isDryRun, j);
}
std::size_t

View File

@@ -58,10 +58,6 @@ STValidation::validationFormat()
{sfBaseFeeDrops, soeOPTIONAL},
{sfReserveBaseDrops, soeOPTIONAL},
{sfReserveIncrementDrops, soeOPTIONAL},
// featureSmartEscrow
{sfExtensionComputeLimit, soeOPTIONAL},
{sfExtensionSizeLimit, soeOPTIONAL},
{sfGasPrice, soeOPTIONAL},
};
// clang-format on

View File

@@ -106,7 +106,6 @@ transResults()
MAKE_ERROR(tecLIMIT_EXCEEDED, "Limit exceeded."),
MAKE_ERROR(tecPSEUDO_ACCOUNT, "This operation is not allowed against a pseudo-account."),
MAKE_ERROR(tecPRECISION_LOSS, "The amounts used by the transaction cannot interact."),
MAKE_ERROR(tecWASM_REJECTED, "The custom WASM code that was run rejected your transaction."),
MAKE_ERROR(tefALREADY, "The exact transaction was already in this ledger."),
MAKE_ERROR(tefBAD_ADD_AUTH, "Not authorized to add account."),
@@ -130,8 +129,6 @@ transResults()
MAKE_ERROR(tefNO_TICKET, "Ticket is not in ledger."),
MAKE_ERROR(tefNFTOKEN_IS_NOT_TRANSFERABLE, "The specified NFToken is not transferable."),
MAKE_ERROR(tefINVALID_LEDGER_FIX_TYPE, "The LedgerFixType field has an invalid value."),
MAKE_ERROR(tefNO_WASM, "There is no WASM code to run, but a WASM-specific field was included."),
MAKE_ERROR(tefWASM_FIELD_NOT_INCLUDED, "WASM code requires a field to be included that was not included."),
MAKE_ERROR(telLOCAL_ERROR, "Local failure."),
MAKE_ERROR(telBAD_DOMAIN, "Domain too long."),
@@ -201,7 +198,6 @@ transResults()
MAKE_ERROR(temARRAY_TOO_LARGE, "Malformed: Array is too large."),
MAKE_ERROR(temBAD_TRANSFER_FEE, "Malformed: Transfer fee is outside valid range."),
MAKE_ERROR(temINVALID_INNER_BATCH, "Malformed: Invalid inner batch transaction."),
MAKE_ERROR(temBAD_WASM, "Malformed: Provided WASM code is invalid."),
MAKE_ERROR(terRETRY, "Retry transaction."),
MAKE_ERROR(terFUNDS_SPENT, "DEPRECATED."),

View File

@@ -190,12 +190,6 @@ TxMeta::getAsObject() const
if (parentBatchID_.has_value())
metaData.setFieldH256(sfParentBatchID, *parentBatchID_);
if (gasUsed_.has_value())
metaData.setFieldU32(sfGasUsed, *gasUsed_);
if (wasmReturnCode_.has_value())
metaData.setFieldI32(sfWasmReturnCode, *wasmReturnCode_);
return metaData;
}

View File

@@ -5904,7 +5904,7 @@ private:
using namespace test::jtx;
auto const testCase = [&](std::string suffix, FeatureBitset features) {
testcase("Pseudo-account allocation failure " + suffix);
testcase("Fail pseudo-account allocation " + suffix);
std::string logs;
Env env{*this, features, std::make_unique<CaptureLogs>(&logs)};
env.fund(XRP(30'000), gw, alice);

File diff suppressed because it is too large Load Diff

View File

@@ -1374,7 +1374,7 @@ struct Escrow_test : public beast::unit_test::suite
Account const alice{"alice"};
Account const bob{"bob"};
Account const carol{"carol"};
Account const dillon{"dillon"};
Account const dillon{"dillon "};
Account const zelda{"zelda"};
char const credType[] = "abcde";
@@ -1524,8 +1524,6 @@ public:
FeatureBitset const all{testable_amendments()};
testWithFeats(all);
testWithFeats(all - featureTokenEscrow);
testWithFeats(all - featureSmartEscrow);
testWithFeats(all - featureTokenEscrow - featureSmartEscrow);
testTags(all - fixIncludeKeyletFields);
}
};

View File

@@ -12,8 +12,6 @@
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/SecretKey.h>
#include <source_location>
namespace xrpl {
namespace test {
@@ -26,13 +24,10 @@ struct FeeSettingsFields
std::optional<XRPAmount> baseFeeDrops = std::nullopt;
std::optional<XRPAmount> reserveBaseDrops = std::nullopt;
std::optional<XRPAmount> reserveIncrementDrops = std::nullopt;
std::optional<std::uint32_t> extensionComputeLimit = std::nullopt;
std::optional<std::uint32_t> extensionSizeLimit = std::nullopt;
std::optional<std::uint32_t> gasPrice = std::nullopt;
};
STTx
createFeeTx(Rules const& rules, std::uint32_t seq, FeeSettingsFields const& fields, bool forceAllFields = false)
createFeeTx(Rules const& rules, std::uint32_t seq, FeeSettingsFields const& fields)
{
auto fill = [&](auto& obj) {
obj.setAccountID(sfAccount, AccountID());
@@ -54,12 +49,6 @@ createFeeTx(Rules const& rules, std::uint32_t seq, FeeSettingsFields const& fiel
obj.setFieldU32(sfReserveIncrement, fields.reserveIncrement ? *fields.reserveIncrement : 0);
obj.setFieldU32(sfReferenceFeeUnits, fields.referenceFeeUnits ? *fields.referenceFeeUnits : 0);
}
if (rules.enabled(featureSmartEscrow) || forceAllFields)
{
obj.setFieldU32(sfExtensionComputeLimit, fields.extensionComputeLimit ? *fields.extensionComputeLimit : 0);
obj.setFieldU32(sfExtensionSizeLimit, fields.extensionSizeLimit ? *fields.extensionSizeLimit : 0);
obj.setFieldU32(sfGasPrice, fields.gasPrice ? *fields.gasPrice : 0);
}
};
return STTx(ttFEE, fill);
}
@@ -108,12 +97,6 @@ createInvalidFeeTx(
obj.setFieldU32(sfReserveIncrement, 50000);
obj.setFieldU32(sfReferenceFeeUnits, 10);
}
if (rules.enabled(featureSmartEscrow))
{
obj.setFieldU32(sfExtensionComputeLimit, 100 + uniqueValue);
obj.setFieldU32(sfExtensionSizeLimit, 200 + uniqueValue);
obj.setFieldU32(sfGasPrice, 300 + uniqueValue);
}
}
// If missingRequiredFields is true, we don't add the required fields
// (default behavior)
@@ -121,11 +104,11 @@ createInvalidFeeTx(
return STTx(ttFEE, fill);
}
TER
bool
applyFeeAndTestResult(jtx::Env& env, OpenView& view, STTx const& tx)
{
auto const res = apply(env.app(), view, tx, ApplyFlags::tapNONE, env.journal);
return res.ter;
return res.ter == tesSUCCESS;
}
bool
@@ -170,21 +153,6 @@ verifyFeeObject(std::shared_ptr<Ledger const> const& ledger, Rules const& rules,
if (!checkEquality(sfReferenceFeeUnits, expected.referenceFeeUnits))
return false;
}
if (rules.enabled(featureSmartEscrow))
{
if (!checkEquality(sfExtensionComputeLimit, expected.extensionComputeLimit.value_or(0)))
return false;
if (!checkEquality(sfExtensionSizeLimit, expected.extensionSizeLimit.value_or(0)))
return false;
if (!checkEquality(sfGasPrice, expected.gasPrice.value_or(0)))
return false;
}
else
{
if (feeObject->isFieldPresent(sfExtensionComputeLimit) || feeObject->isFieldPresent(sfExtensionSizeLimit) ||
feeObject->isFieldPresent(sfGasPrice))
return false;
}
return true;
}
@@ -207,7 +175,6 @@ class FeeVote_test : public beast::unit_test::suite
void
testSetup()
{
testcase("FeeVote setup");
FeeSetup const defaultSetup;
{
// defaults
@@ -216,82 +183,43 @@ class FeeVote_test : public beast::unit_test::suite
BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee);
BEAST_EXPECT(setup.account_reserve == defaultSetup.account_reserve);
BEAST_EXPECT(setup.owner_reserve == defaultSetup.owner_reserve);
BEAST_EXPECT(setup.extension_compute_limit == defaultSetup.extension_compute_limit);
BEAST_EXPECT(setup.extension_size_limit == defaultSetup.extension_size_limit);
BEAST_EXPECT(setup.gas_price == defaultSetup.gas_price);
}
{
Section config;
config.append(
{"reference_fee = 50",
"account_reserve = 1234567",
"owner_reserve = 1234",
"extension_compute_limit = 100",
"extension_size_limit = 200",
" gas_price = 300"});
config.append({"reference_fee = 50", "account_reserve = 1234567", "owner_reserve = 1234"});
auto setup = setup_FeeVote(config);
BEAST_EXPECT(setup.reference_fee == 50);
BEAST_EXPECT(setup.account_reserve == 1234567);
BEAST_EXPECT(setup.owner_reserve == 1234);
BEAST_EXPECT(setup.extension_compute_limit == 100);
BEAST_EXPECT(setup.extension_size_limit == 200);
BEAST_EXPECT(setup.gas_price == 300);
}
{
Section config;
config.append(
{"reference_fee = blah",
"account_reserve = yada",
"owner_reserve = foo",
"extension_compute_limit = bar",
"extension_size_limit = baz",
"gas_price = qux"});
config.append({"reference_fee = blah", "account_reserve = yada", "owner_reserve = foo"});
// Illegal values are ignored, and the defaults left unchanged
auto setup = setup_FeeVote(config);
BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee);
BEAST_EXPECT(setup.account_reserve == defaultSetup.account_reserve);
BEAST_EXPECT(setup.owner_reserve == defaultSetup.owner_reserve);
BEAST_EXPECT(setup.extension_compute_limit == defaultSetup.extension_compute_limit);
BEAST_EXPECT(setup.extension_size_limit == defaultSetup.extension_size_limit);
BEAST_EXPECT(setup.gas_price == defaultSetup.gas_price);
}
{
Section config;
config.append(
{"reference_fee = -50",
"account_reserve = -1234567",
"owner_reserve = -1234",
"extension_compute_limit = -100",
"extension_size_limit = -200",
"gas_price = -300"});
config.append({"reference_fee = -50", "account_reserve = -1234567", "owner_reserve = -1234"});
// Illegal values are ignored, and the defaults left unchanged
auto setup = setup_FeeVote(config);
BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee);
BEAST_EXPECT(setup.account_reserve == static_cast<std::uint32_t>(-1234567));
BEAST_EXPECT(setup.owner_reserve == static_cast<std::uint32_t>(-1234));
BEAST_EXPECT(setup.extension_compute_limit == static_cast<std::uint32_t>(-100));
BEAST_EXPECT(setup.extension_size_limit == static_cast<std::uint32_t>(-200));
BEAST_EXPECT(setup.gas_price == static_cast<std::uint32_t>(-300));
}
{
auto const big64 =
std::to_string(static_cast<std::uint64_t>(std::numeric_limits<XRPAmount::value_type>::max()) + 1);
Section config;
config.append(
{"reference_fee = " + big64,
"account_reserve = " + big64,
"owner_reserve = " + big64,
"extension_compute_limit = " + big64,
"extension_size_limit = " + big64,
"gas_price = " + big64});
config.append({"reference_fee = " + big64, "account_reserve = " + big64, "owner_reserve = " + big64});
// Illegal values are ignored, and the defaults left unchanged
auto setup = setup_FeeVote(config);
BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee);
BEAST_EXPECT(setup.account_reserve == defaultSetup.account_reserve);
BEAST_EXPECT(setup.owner_reserve == defaultSetup.owner_reserve);
BEAST_EXPECT(setup.extension_compute_limit == defaultSetup.extension_compute_limit);
BEAST_EXPECT(setup.extension_size_limit == defaultSetup.extension_size_limit);
BEAST_EXPECT(setup.gas_price == defaultSetup.gas_price);
}
}
@@ -302,7 +230,7 @@ class FeeVote_test : public beast::unit_test::suite
// Test with XRPFees disabled (legacy format)
{
jtx::Env env(*this, jtx::testable_amendments() - featureXRPFees - featureSmartEscrow);
jtx::Env env(*this, jtx::testable_amendments() - featureXRPFees);
auto ledger = std::make_shared<Ledger>(
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
@@ -316,7 +244,7 @@ class FeeVote_test : public beast::unit_test::suite
auto feeTx = createFeeTx(ledger->rules(), ledger->seq(), fields);
OpenView accum(ledger.get());
BEAST_EXPECT(isTesSuccess(applyFeeAndTestResult(env, accum, feeTx)));
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx));
accum.apply(*ledger);
// Verify fee object was created/updated correctly
@@ -325,7 +253,7 @@ class FeeVote_test : public beast::unit_test::suite
// Test with XRPFees enabled (new format)
{
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
auto ledger = std::make_shared<Ledger>(
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
@@ -340,63 +268,12 @@ class FeeVote_test : public beast::unit_test::suite
auto feeTx = createFeeTx(ledger->rules(), ledger->seq(), fields);
OpenView accum(ledger.get());
BEAST_EXPECT(isTesSuccess(applyFeeAndTestResult(env, accum, feeTx)));
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx));
accum.apply(*ledger);
// Verify fee object was created/updated correctly
BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields));
}
// Test with both XRPFees and SmartEscrow enabled
{
jtx::Env env(*this, jtx::testable_amendments());
auto ledger = std::make_shared<Ledger>(
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
// Create the next ledger to apply transaction to
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
FeeSettingsFields fields{
.baseFeeDrops = XRPAmount{10},
.reserveBaseDrops = XRPAmount{200000},
.reserveIncrementDrops = XRPAmount{50000},
.extensionComputeLimit = 100,
.extensionSizeLimit = 200,
.gasPrice = 300};
// Test successful fee transaction with new fields
auto feeTx = createFeeTx(ledger->rules(), ledger->seq(), fields);
OpenView accum(ledger.get());
BEAST_EXPECT(isTesSuccess(applyFeeAndTestResult(env, accum, feeTx)));
accum.apply(*ledger);
// Verify fee object was created/updated correctly
BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields));
}
// Test that the Smart Escrow fields are rejected if the
// feature is disabled
{
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
auto ledger = std::make_shared<Ledger>(
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
// Create the next ledger to apply transaction to
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
FeeSettingsFields fields{
.baseFeeDrops = XRPAmount{10},
.reserveBaseDrops = XRPAmount{200000},
.reserveIncrementDrops = XRPAmount{50000},
.extensionComputeLimit = 100,
.extensionSizeLimit = 200,
.gasPrice = 300};
// Test successful fee transaction with new fields
auto feeTx = createFeeTx(ledger->rules(), ledger->seq(), fields, true);
OpenView accum(ledger.get());
BEAST_EXPECT(!isTesSuccess(applyFeeAndTestResult(env, accum, feeTx)));
}
}
void
@@ -405,7 +282,7 @@ class FeeVote_test : public beast::unit_test::suite
testcase("Fee Transaction Validation");
{
jtx::Env env(*this, jtx::testable_amendments() - featureXRPFees - featureSmartEscrow);
jtx::Env env(*this, jtx::testable_amendments() - featureXRPFees);
auto ledger = std::make_shared<Ledger>(
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
@@ -415,15 +292,15 @@ class FeeVote_test : public beast::unit_test::suite
// Test transaction with missing required legacy fields
auto invalidTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), true, false, 1);
OpenView accum(ledger.get());
BEAST_EXPECT(!isTesSuccess(applyFeeAndTestResult(env, accum, invalidTx)));
BEAST_EXPECT(!applyFeeAndTestResult(env, accum, invalidTx));
// Test transaction with new format fields when XRPFees is disabled
auto disallowedTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), false, true, 2);
BEAST_EXPECT(!isTesSuccess(applyFeeAndTestResult(env, accum, disallowedTx)));
BEAST_EXPECT(!applyFeeAndTestResult(env, accum, disallowedTx));
}
{
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
auto ledger = std::make_shared<Ledger>(
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
@@ -433,29 +310,11 @@ class FeeVote_test : public beast::unit_test::suite
// Test transaction with missing required new fields
auto invalidTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), true, false, 3);
OpenView accum(ledger.get());
BEAST_EXPECT(!isTesSuccess(applyFeeAndTestResult(env, accum, invalidTx)));
BEAST_EXPECT(!applyFeeAndTestResult(env, accum, invalidTx));
// Test transaction with legacy fields when XRPFees is enabled
auto disallowedTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), false, true, 4);
BEAST_EXPECT(!isTesSuccess(applyFeeAndTestResult(env, accum, disallowedTx)));
}
{
jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees | featureSmartEscrow);
auto ledger = std::make_shared<Ledger>(
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
// Create the next ledger to apply transaction to
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
// Test transaction with missing required new fields
auto invalidTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), true, false, 5);
OpenView accum(ledger.get());
BEAST_EXPECT(!isTesSuccess(applyFeeAndTestResult(env, accum, invalidTx)));
// Test transaction with legacy fields when XRPFees is enabled
auto disallowedTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), false, true, 6);
BEAST_EXPECT(!isTesSuccess(applyFeeAndTestResult(env, accum, disallowedTx)));
BEAST_EXPECT(!applyFeeAndTestResult(env, accum, disallowedTx));
}
}
@@ -464,7 +323,7 @@ class FeeVote_test : public beast::unit_test::suite
{
testcase("Pseudo Transaction Properties");
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
jtx::Env env(*this, jtx::testable_amendments());
auto ledger = std::make_shared<Ledger>(
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
@@ -490,7 +349,7 @@ class FeeVote_test : public beast::unit_test::suite
// But can be applied to a closed ledger
{
OpenView closedAccum(ledger.get());
BEAST_EXPECT(isTesSuccess(applyFeeAndTestResult(env, closedAccum, feeTx)));
BEAST_EXPECT(applyFeeAndTestResult(env, closedAccum, feeTx));
}
}
@@ -499,7 +358,7 @@ class FeeVote_test : public beast::unit_test::suite
{
testcase("Multiple Fee Updates");
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
auto ledger = std::make_shared<Ledger>(
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
@@ -513,7 +372,7 @@ class FeeVote_test : public beast::unit_test::suite
{
OpenView accum(ledger.get());
BEAST_EXPECT(isTesSuccess(applyFeeAndTestResult(env, accum, feeTx1)));
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx1));
accum.apply(*ledger);
}
@@ -530,7 +389,7 @@ class FeeVote_test : public beast::unit_test::suite
{
OpenView accum(ledger.get());
BEAST_EXPECT(isTesSuccess(applyFeeAndTestResult(env, accum, feeTx2)));
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx2));
accum.apply(*ledger);
}
@@ -543,7 +402,7 @@ class FeeVote_test : public beast::unit_test::suite
{
testcase("Wrong Ledger Sequence");
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
auto ledger = std::make_shared<Ledger>(
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
@@ -562,7 +421,7 @@ class FeeVote_test : public beast::unit_test::suite
// The transaction should still succeed as long as other fields are
// valid
// The ledger sequence field is only used for informational purposes
BEAST_EXPECT(isTesSuccess(applyFeeAndTestResult(env, accum, feeTx)));
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx));
}
void
@@ -570,7 +429,7 @@ class FeeVote_test : public beast::unit_test::suite
{
testcase("Partial Field Updates");
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
auto ledger = std::make_shared<Ledger>(
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
@@ -584,7 +443,7 @@ class FeeVote_test : public beast::unit_test::suite
{
OpenView accum(ledger.get());
BEAST_EXPECT(isTesSuccess(applyFeeAndTestResult(env, accum, feeTx1)));
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx1));
accum.apply(*ledger);
}
@@ -598,7 +457,7 @@ class FeeVote_test : public beast::unit_test::suite
{
OpenView accum(ledger.get());
BEAST_EXPECT(isTesSuccess(applyFeeAndTestResult(env, accum, feeTx2)));
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx2));
accum.apply(*ledger);
}
@@ -611,7 +470,7 @@ class FeeVote_test : public beast::unit_test::suite
{
testcase("Single Invalid Transaction");
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
auto ledger = std::make_shared<Ledger>(
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
@@ -629,7 +488,7 @@ class FeeVote_test : public beast::unit_test::suite
});
OpenView accum(ledger.get());
BEAST_EXPECT(!isTesSuccess(applyFeeAndTestResult(env, accum, invalidTx)));
BEAST_EXPECT(!applyFeeAndTestResult(env, accum, invalidTx));
}
void
@@ -646,7 +505,7 @@ class FeeVote_test : public beast::unit_test::suite
// Test with XRPFees enabled
{
Env env(*this, testable_amendments() - featureSmartEscrow);
Env env(*this, testable_amendments() | featureXRPFees);
auto feeVote = make_FeeVote(setup, env.app().journal("FeeVote"));
auto ledger = std::make_shared<Ledger>(
@@ -672,7 +531,7 @@ class FeeVote_test : public beast::unit_test::suite
// Test with XRPFees disabled (legacy format)
{
Env env(*this, testable_amendments() - featureXRPFees - featureSmartEscrow);
Env env(*this, testable_amendments() - featureXRPFees);
auto feeVote = make_FeeVote(setup, env.app().journal("FeeVote"));
auto ledger = std::make_shared<Ledger>(
@@ -708,7 +567,7 @@ class FeeVote_test : public beast::unit_test::suite
setup.account_reserve = 1234567;
setup.owner_reserve = 7654321;
Env env(*this, testable_amendments() - featureSmartEscrow);
Env env(*this, testable_amendments() | featureXRPFees);
// establish what the current fees are
BEAST_EXPECT(env.current()->fees().base == XRPAmount{UNIT_TEST_REFERENCE_FEE});
@@ -778,127 +637,6 @@ class FeeVote_test : public beast::unit_test::suite
BEAST_EXPECT(feeTx.getFieldAmount(sfReserveIncrementDrops) == XRPAmount{setup.owner_reserve});
}
void
testDoVotingSmartEscrow()
{
testcase("doVoting with Smart Escrow");
using namespace jtx;
Env env(*this, testable_amendments() | featureXRPFees | featureSmartEscrow);
// establish what the current fees are
BEAST_EXPECT(env.current()->fees().base == XRPAmount{UNIT_TEST_REFERENCE_FEE});
BEAST_EXPECT(env.current()->fees().reserve == XRPAmount{200'000'000});
BEAST_EXPECT(env.current()->fees().increment == XRPAmount{50'000'000});
BEAST_EXPECT(env.current()->fees().extensionComputeLimit == 0);
BEAST_EXPECT(env.current()->fees().extensionSizeLimit == 0);
BEAST_EXPECT(env.current()->fees().gasPrice == 0);
auto const createFeeTxFromVoting = [&](FeeSetup const& setup) -> std::pair<STTx, std::shared_ptr<Ledger>> {
auto feeVote = make_FeeVote(setup, env.app().journal("FeeVote"));
auto ledger = std::make_shared<Ledger>(
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
// doVoting requires a flag ledger (every 256th ledger)
// We need to create a ledger at sequence 256 to make it a flag
// ledger
for (int i = 0; i < 256 - 1; ++i)
{
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
}
BEAST_EXPECT(ledger->isFlagLedger());
// Create some mock validations with fee votes
std::vector<std::shared_ptr<STValidation>> validations;
for (int i = 0; i < 5; i++)
{
auto sec = randomSecretKey();
auto pub = derivePublicKey(KeyType::secp256k1, sec);
auto val = std::make_shared<STValidation>(
env.app().timeKeeper().now(), pub, sec, calcNodeID(pub), [&](STValidation& v) {
v.setFieldU32(sfLedgerSequence, ledger->seq());
// Vote for different fees than current
v.setFieldAmount(sfBaseFeeDrops, XRPAmount{setup.reference_fee});
v.setFieldAmount(sfReserveBaseDrops, XRPAmount{setup.account_reserve});
v.setFieldAmount(sfReserveIncrementDrops, XRPAmount{setup.owner_reserve});
v.setFieldU32(sfExtensionComputeLimit, setup.extension_compute_limit);
v.setFieldU32(sfExtensionSizeLimit, setup.extension_size_limit);
v.setFieldU32(sfGasPrice, setup.gas_price);
});
if (i % 2)
val->setTrusted();
validations.push_back(val);
}
auto txSet = std::make_shared<SHAMap>(SHAMapType::TRANSACTION, env.app().getNodeFamily());
// This should not throw since we have a flag ledger
feeVote->doVoting(ledger, validations, txSet);
auto const txs = getTxs(txSet);
BEAST_EXPECT(txs.size() == 1);
return {txs[0], ledger};
};
auto checkFeeTx = [&](FeeSetup const& setup,
STTx const& feeTx,
std::shared_ptr<Ledger> const& ledger,
std::source_location const loc = std::source_location::current()) {
auto const line = " (" + std::to_string(loc.line()) + ")";
BEAST_EXPECTS(feeTx.getTxnType() == ttFEE, line);
BEAST_EXPECTS(feeTx.getAccountID(sfAccount) == AccountID(), line);
BEAST_EXPECTS(feeTx.getFieldU32(sfLedgerSequence) == ledger->seq() + 1, line);
BEAST_EXPECTS(feeTx.isFieldPresent(sfBaseFeeDrops), line);
BEAST_EXPECTS(feeTx.isFieldPresent(sfReserveBaseDrops), line);
BEAST_EXPECTS(feeTx.isFieldPresent(sfReserveIncrementDrops), line);
// The legacy fields should NOT be present
BEAST_EXPECTS(!feeTx.isFieldPresent(sfBaseFee), line);
BEAST_EXPECTS(!feeTx.isFieldPresent(sfReserveBase), line);
BEAST_EXPECTS(!feeTx.isFieldPresent(sfReserveIncrement), line);
BEAST_EXPECTS(!feeTx.isFieldPresent(sfReferenceFeeUnits), line);
// Check the values
BEAST_EXPECTS(feeTx.getFieldAmount(sfBaseFeeDrops) == XRPAmount{setup.reference_fee}, line);
BEAST_EXPECTS(feeTx.getFieldAmount(sfReserveBaseDrops) == XRPAmount{setup.account_reserve}, line);
BEAST_EXPECTS(feeTx.getFieldAmount(sfReserveIncrementDrops) == XRPAmount{setup.owner_reserve}, line);
BEAST_EXPECTS(feeTx.getFieldU32(sfExtensionComputeLimit) == setup.extension_compute_limit, line);
BEAST_EXPECTS(feeTx.getFieldU32(sfExtensionSizeLimit) == setup.extension_size_limit, line);
BEAST_EXPECTS(feeTx.getFieldU32(sfGasPrice) == setup.gas_price, line);
};
{
FeeSetup setup;
setup.reference_fee = 42;
setup.account_reserve = 1234567;
setup.owner_reserve = 7654321;
setup.extension_compute_limit = 100;
setup.extension_size_limit = 200;
setup.gas_price = 300;
auto const [feeTx, ledger] = createFeeTxFromVoting(setup);
checkFeeTx(setup, feeTx, ledger);
}
{
FeeSetup setup;
setup.reference_fee = 42;
setup.account_reserve = 1234567;
setup.owner_reserve = 7654321;
setup.extension_compute_limit = 0;
setup.extension_size_limit = 0;
setup.gas_price = 300;
auto const [feeTx, ledger] = createFeeTxFromVoting(setup);
checkFeeTx(setup, feeTx, ledger);
}
}
void
run() override
{
@@ -912,7 +650,6 @@ class FeeVote_test : public beast::unit_test::suite
testSingleInvalidTransaction();
testDoValidation();
testDoVoting();
testDoVotingSmartEscrow();
}
};

File diff suppressed because it is too large Load Diff

View File

@@ -33,12 +33,6 @@ struct PseudoTx_test : public beast::unit_test::suite
obj[sfReserveIncrement] = 0;
obj[sfReferenceFeeUnits] = 0;
}
if (rules.enabled(featureSmartEscrow))
{
obj[sfExtensionComputeLimit] = 0;
obj[sfExtensionSizeLimit] = 0;
obj[sfGasPrice] = 0;
}
}));
res.emplace_back(STTx(ttAMENDMENT, [&](auto& obj) {
@@ -103,9 +97,7 @@ struct PseudoTx_test : public beast::unit_test::suite
FeatureBitset const all{testable_amendments()};
FeatureBitset const xrpFees{featureXRPFees};
testPrevented(all - featureXRPFees - featureSmartEscrow);
testPrevented(all - featureXRPFees);
testPrevented(all - featureSmartEscrow);
testPrevented(all);
testAllowed();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,964 +0,0 @@
#ifdef _DEBUG
// #define DEBUG_OUTPUT 1
#endif
#include <test/app/TestHostFunctions.h>
#include <xrpld/app/wasm/HostFuncWrapper.h>
#include <source_location>
namespace xrpl {
namespace test {
bool
testGetDataIncrement();
using Add_proto = int32_t(int32_t, int32_t);
static wasm_trap_t*
Add(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results)
{
int32_t Val1 = params->data[0].of.i32;
int32_t Val2 = params->data[1].of.i32;
// printf("Host function \"Add\": %d + %d\n", Val1, Val2);
results->data[0] = WASM_I32_VAL(Val1 + Val2);
return nullptr;
}
std::vector<uint8_t> const
hexToBytes(std::string const& hex)
{
auto const ws = boost::algorithm::unhex(hex);
return Bytes(ws.begin(), ws.end());
}
std::optional<int32_t>
runFinishFunction(std::string const& code)
{
auto& engine = WasmEngine::instance();
auto const wasm = hexToBytes(code);
auto const re = engine.run(wasm, "finish");
if (re.has_value())
{
return std::optional<int32_t>(re->result);
}
else
{
return std::nullopt;
}
}
struct Wasm_test : public beast::unit_test::suite
{
void
checkResult(
Expected<WasmResult<int32_t>, TER> re,
int32_t expectedResult,
int64_t expectedCost,
std::source_location const location = std::source_location::current())
{
auto const lineStr = " (" + std::to_string(location.line()) + ")";
if (BEAST_EXPECTS(re.has_value(), transToken(re.error()) + lineStr))
{
BEAST_EXPECTS(re->result == expectedResult, std::to_string(re->result) + lineStr);
BEAST_EXPECTS(re->cost == expectedCost, std::to_string(re->cost) + lineStr);
}
}
void
testGetDataHelperFunctions()
{
testcase("getData helper functions");
BEAST_EXPECT(testGetDataIncrement());
}
void
testWasmLib()
{
testcase("wasmtime lib test");
// clang-format off
/* The WASM module buffer. */
Bytes const wasm = {/* WASM header */
0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00,
/* Type section */
0x01, 0x07, 0x01,
/* function type {i32, i32} -> {i32} */
0x60, 0x02, 0x7F, 0x7F, 0x01, 0x7F,
/* Import section */
0x02, 0x13, 0x01,
/* module name: "extern" */
0x06, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6E,
/* extern name: "func-add" */
0x08, 0x66, 0x75, 0x6E, 0x63, 0x2D, 0x61, 0x64, 0x64,
/* import desc: func 0 */
0x00, 0x00,
/* Function section */
0x03, 0x02, 0x01, 0x00,
/* Export section */
0x07, 0x0A, 0x01,
/* export name: "addTwo" */
0x06, 0x61, 0x64, 0x64, 0x54, 0x77, 0x6F,
/* export desc: func 0 */
0x00, 0x01,
/* Code section */
0x0A, 0x0A, 0x01,
/* code body */
0x08, 0x00, 0x20, 0x00, 0x20, 0x01, 0x10, 0x00, 0x0B};
// clang-format on
auto& vm = WasmEngine::instance();
std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
WasmImpFunc<Add_proto>(*imports, "func-add", reinterpret_cast<void*>(&Add));
auto re = vm.run(wasm, "addTwo", wasmParams(1234, 5678), imports);
// if (res) printf("invokeAdd get the result: %d\n", res.value());
checkResult(re, 6'912, 59);
}
void
testBadWasm()
{
testcase("bad wasm test");
using namespace test::jtx;
Env env{*this};
std::shared_ptr<HostFunctions> hfs(new HostFunctions(env.journal));
{
auto wasm = hexToBytes("00000000");
std::string funcName("mock_escrow");
auto re = runEscrowWasm(wasm, hfs, funcName, {}, 15);
BEAST_EXPECT(!re);
}
{
auto wasm = hexToBytes("00112233445566778899AA");
std::string funcName("mock_escrow");
auto const re = preflightEscrowWasm(wasm, hfs, funcName);
BEAST_EXPECT(!isTesSuccess(re));
}
{
// FinishFunction wrong function name
// pub fn bad() -> bool {
// unsafe { host_lib::getLedgerSqn() >= 5 }
// }
auto const badWasm = hexToBytes(
"0061736d010000000105016000017f02190108686f73745f6c69620c6765"
"744c656467657253716e00000302010005030100100611027f00418080c0"
"000b7f00418080c0000b072b04066d656d6f727902000362616400010a5f"
"5f646174615f656e6403000b5f5f686561705f6261736503010a09010700"
"100041044a0b004d0970726f64756365727302086c616e67756167650104"
"52757374000c70726f6365737365642d6279010572757374631d312e3835"
"2e31202834656231363132353020323032352d30332d31352900490f7461"
"726765745f6665617475726573042b0f6d757461626c652d676c6f62616c"
"732b087369676e2d6578742b0f7265666572656e63652d74797065732b0a"
"6d756c746976616c7565");
auto const re = preflightEscrowWasm(badWasm, hfs, ESCROW_FUNCTION_NAME);
BEAST_EXPECT(!isTesSuccess(re));
}
}
void
testWasmLedgerSqn()
{
testcase("Wasm get ledger sequence");
auto ledgerSqnWasm = hexToBytes(ledgerSqnWasmHex);
using namespace test::jtx;
Env env{*this};
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
auto imports = std::make_shared<ImportVec>();
WASM_IMPORT_FUNC2(*imports, getLedgerSqn, "get_ledger_sqn", hfs.get(), 33);
auto& engine = WasmEngine::instance();
auto re = engine.run(ledgerSqnWasm, ESCROW_FUNCTION_NAME, {}, imports, hfs, 1'000'000, env.journal);
checkResult(re, 0, 151);
env.close();
env.close();
// empty module - run the same instance
re = engine.run({}, ESCROW_FUNCTION_NAME, {}, imports, hfs, 1'000'000, env.journal);
checkResult(re, 5, 190);
}
void
testWasmFib()
{
testcase("Wasm fibo");
auto const fibWasm = hexToBytes(fibWasmHex);
auto& engine = WasmEngine::instance();
auto const re = engine.run(fibWasm, "fib", wasmParams(10));
checkResult(re, 55, 1'137);
}
void
testWasmSha()
{
testcase("Wasm sha");
auto const sha512Wasm = hexToBytes(sha512PureWasmHex);
auto& engine = WasmEngine::instance();
auto const re = engine.run(sha512Wasm, "sha512_process", wasmParams(sha512PureWasmHex));
checkResult(re, 34'432, 151'155);
}
void
testWasmB58()
{
testcase("Wasm base58");
auto const b58Wasm = hexToBytes(b58WasmHex);
auto& engine = WasmEngine::instance();
Bytes outb;
outb.resize(1024);
auto const minsz = std::min(static_cast<std::uint32_t>(512), static_cast<std::uint32_t>(b58WasmHex.size()));
auto const s = std::string_view(b58WasmHex.c_str(), minsz);
auto const re = engine.run(b58Wasm, "b58enco", wasmParams(outb, s));
checkResult(re, 700, 2'886'069);
}
void
testHFCost()
{
testcase("wasm test host functions cost");
using namespace test::jtx;
Env env(*this);
{
auto const allHostFuncWasm = hexToBytes(allHostFunctionsWasmHex);
auto& engine = WasmEngine::instance();
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
auto imp = createWasmImport(*hfs);
for (auto& i : *imp)
i.second.gas = 0;
auto re = engine.run(allHostFuncWasm, ESCROW_FUNCTION_NAME, {}, imp, hfs, 1'000'000, env.journal);
checkResult(re, 1, 25'503);
env.close();
}
env.close();
env.close();
env.close();
env.close();
env.close();
{
auto const allHostFuncWasm = hexToBytes(allHostFunctionsWasmHex);
auto& engine = WasmEngine::instance();
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
auto const imp = createWasmImport(*hfs);
auto re = engine.run(allHostFuncWasm, ESCROW_FUNCTION_NAME, {}, imp, hfs, 1'000'000, env.journal);
checkResult(re, 1, 64'263);
env.close();
}
// not enough gas
{
auto const allHostFuncWasm = hexToBytes(allHostFunctionsWasmHex);
auto& engine = WasmEngine::instance();
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
auto const imp = createWasmImport(*hfs);
auto re = engine.run(allHostFuncWasm, ESCROW_FUNCTION_NAME, {}, imp, hfs, 200, env.journal);
if (BEAST_EXPECT(!re))
{
BEAST_EXPECTS(re.error() == tecFAILED_PROCESSING, std::to_string(TERtoInt(re.error())));
}
env.close();
}
}
void
testEscrowWasmDN()
{
testcase("escrow wasm devnet test");
auto const allHFWasm = hexToBytes(allHostFunctionsWasmHex);
using namespace test::jtx;
Env env{*this};
{
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
auto re = runEscrowWasm(allHFWasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
checkResult(re, 1, 64'263);
}
{
// max<int64_t>() gas
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
auto re = runEscrowWasm(allHFWasm, hfs, ESCROW_FUNCTION_NAME, {}, -1);
checkResult(re, 1, 64'263);
}
{ // fail because trying to access nonexistent field
struct BadTestHostFunctions : public TestHostFunctions
{
explicit BadTestHostFunctions(Env& env) : TestHostFunctions(env)
{
}
Expected<Bytes, HostFunctionError>
getTxField(SField const& fname) override
{
return Unexpected(HostFunctionError::FIELD_NOT_FOUND);
}
};
std::shared_ptr<HostFunctions> hfs(new BadTestHostFunctions(env));
auto re = runEscrowWasm(allHFWasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
checkResult(re, -201, 28'148);
}
{ // fail because trying to allocate more than MAX_PAGES memory
struct BadTestHostFunctions : public TestHostFunctions
{
explicit BadTestHostFunctions(Env& env) : TestHostFunctions(env)
{
}
Expected<Bytes, HostFunctionError>
getTxField(SField const& fname) override
{
return Bytes((128 + 1) * 64 * 1024, 1);
}
};
std::shared_ptr<HostFunctions> hfs(new BadTestHostFunctions(env));
auto re = runEscrowWasm(allHFWasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
checkResult(re, -201, 28'148);
}
{ // fail because recursion too deep
auto const deepWasm = hexToBytes(deepRecursionHex);
std::shared_ptr<TestHostFunctionsSink> hfs(new TestHostFunctionsSink(env));
std::string funcName("finish");
auto re = runEscrowWasm(deepWasm, hfs, funcName, {}, 1'000'000'000);
BEAST_EXPECT(!re && re.error());
// std::cout << "bad case (deep recursion) result " << re.error()
// << std::endl;
auto const& sink = hfs->getSink();
auto countSubstr = [](std::string const& str, std::string const& substr) {
std::size_t pos = 0;
int occurrences = 0;
while ((pos = str.find(substr, pos)) != std::string::npos)
{
occurrences++;
pos += substr.length();
}
return occurrences;
};
auto const s = sink.messages().str();
BEAST_EXPECT(countSubstr(s, "WASMI Error: failure to call func") == 1);
BEAST_EXPECT(countSubstr(s, "exception: <finish> failure") > 0);
}
{ // infinite loop
auto const infiniteLoopWasm = hexToBytes(infiniteLoopWasmHex);
std::string const funcName("loop");
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
// infinite loop should be caught and fail
auto const re = runEscrowWasm(infiniteLoopWasm, hfs, funcName, {}, 1'000'000);
if (BEAST_EXPECT(!re.has_value()))
{
BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
}
}
{
// expected import not provided
auto const lgrSqnWasm = hexToBytes(ledgerSqnWasmHex);
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
WASM_IMPORT_FUNC2(*imports, getLedgerSqn, "get_ledger_sqn2", hfs.get());
auto& engine = WasmEngine::instance();
auto re = engine.run(lgrSqnWasm, ESCROW_FUNCTION_NAME, {}, imports, hfs, 1'000'000, env.journal);
BEAST_EXPECT(!re);
}
{
// bad import format
auto const lgrSqnWasm = hexToBytes(ledgerSqnWasmHex);
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
WASM_IMPORT_FUNC2(*imports, getLedgerSqn, "get_ledger_sqn", hfs.get());
(*imports)[0].first = nullptr;
auto& engine = WasmEngine::instance();
auto re = engine.run(lgrSqnWasm, ESCROW_FUNCTION_NAME, {}, imports, hfs, 1'000'000, env.journal);
BEAST_EXPECT(!re);
}
{
// bad function name
auto const lgrSqnWasm = hexToBytes(ledgerSqnWasmHex);
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
WASM_IMPORT_FUNC2(*imports, getLedgerSqn, "get_ledger_sqn", hfs.get());
auto& engine = WasmEngine::instance();
auto re = engine.run(lgrSqnWasm, "func1", {}, imports, hfs, 1'000'000, env.journal);
BEAST_EXPECT(!re);
}
}
void
testFloat()
{
testcase("float point");
std::string const funcName("finish");
using namespace test::jtx;
Env env(*this);
{
auto const floatTestWasm = hexToBytes(floatTestsWasmHex);
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
auto re = runEscrowWasm(floatTestWasm, hfs, funcName, {}, 200'000);
checkResult(re, 1, 110'699);
env.close();
}
{
auto const float0Wasm = hexToBytes(float0Hex);
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
auto re = runEscrowWasm(float0Wasm, hfs, funcName, {}, 100'000);
checkResult(re, 1, 4'259);
env.close();
}
}
void
perfTest()
{
testcase("Perf test host functions");
using namespace jtx;
using namespace std::chrono;
// std::string const funcName("test");
auto const perfWasm = hexToBytes(hfPerfTest);
// std::string const credType = "abcde";
// std::string const credType2 = "fghijk";
// std::string const credType3 = "0123456";
// char const uri[] = "uri";
Account const alan{"alan"};
Account const bob{"bob"};
Account const issuer{"issuer"};
{
Env env(*this);
// Env env(*this, envconfig(), {}, nullptr,
// beast::severities::kTrace);
env.fund(XRP(5000), alan, bob, issuer);
env.close();
// // create escrow
// auto const seq = env.seq(alan);
// auto const k = keylet::escrow(alan, seq);
// // auto const allowance = 3'600;
// auto escrowCreate = escrow::create(alan, bob, XRP(1000));
// XRPAmount txnFees = env.current()->fees().base + 1000;
// env(escrowCreate,
// escrow::finish_function(wasmHex),
// escrow::finish_time(env.now() + 11s),
// escrow::cancel_time(env.now() + 100s),
// escrow::data("1000000000"), // 1000 XRP in drops
// memodata("memo1234567"),
// memodata("2memo1234567"),
// fee(txnFees));
// // create depositPreauth
// auto const k = keylet::depositPreauth(
// bob,
// {{issuer.id(), makeSlice(credType)},
// {issuer.id(), makeSlice(credType2)},
// {issuer.id(), makeSlice(credType3)}});
// env(deposit::authCredentials(
// bob,
// {{issuer, credType},
// {issuer, credType2},
// {issuer, credType3}}));
// create nft
[[maybe_unused]] uint256 const nft0{token::getNextID(env, alan, 0u)};
env(token::mint(alan, 0u));
auto const k = keylet::nftoffer(alan, 0);
[[maybe_unused]] uint256 const nft1{token::getNextID(env, alan, 0u)};
env(token::mint(alan, 0u),
token::uri("https://github.com/XRPLF/XRPL-Standards/discussions/"
"279?id=github.com/XRPLF/XRPL-Standards/discussions/"
"279&ut=github.com/XRPLF/XRPL-Standards/discussions/"
"279&sid=github.com/XRPLF/XRPL-Standards/discussions/"
"279&aot=github.com/XRPLF/XRPL-Standards/disc"));
[[maybe_unused]] uint256 const nft2{token::getNextID(env, alan, 0u)};
env(token::mint(alan, 0u));
env.close();
std::shared_ptr<HostFunctions> hfs(new PerfHostFunctions(env, k, env.tx()));
auto re = runEscrowWasm(perfWasm, hfs, ESCROW_FUNCTION_NAME);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECT(re->result);
std::cout << "Res: " << re->result << " cost: " << re->cost << std::endl;
}
// env(escrow::finish(alan, alan, seq),
// escrow::comp_allowance(allowance),
// fee(txnFees),
// ter(tesSUCCESS));
env.close();
}
}
void
testCodecovWasm()
{
testcase("Codecov wasm test");
using namespace test::jtx;
Env env{*this};
auto const codecovWasm = hexToBytes(codecovTestsWasmHex);
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
auto const allowance = 324'931;
auto re = runEscrowWasm(codecovWasm, hfs, ESCROW_FUNCTION_NAME, {}, allowance);
checkResult(re, 1, allowance);
}
void
testDisabledFloat()
{
testcase("disabled float");
using namespace test::jtx;
Env env{*this};
auto disabledFloatWasm = hexToBytes(disabledFloatHex);
std::string const funcName("finish");
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
{
// f32 set constant, opcode disabled exception
auto const re = runEscrowWasm(disabledFloatWasm, hfs, funcName, {}, 1'000'000);
if (BEAST_EXPECT(!re.has_value()))
{
BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
}
}
{
// f32 add, can't create module exception
disabledFloatWasm[0x117] = 0x92;
auto const re = runEscrowWasm(disabledFloatWasm, hfs, funcName, {}, 1'000'000);
if (BEAST_EXPECT(!re.has_value()))
{
BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
}
}
}
void
testWasmMemory()
{
testcase("Wasm additional memory limit tests");
BEAST_EXPECT(runFinishFunction(memoryPointerAtLimitHex).value() == 1);
BEAST_EXPECT(runFinishFunction(memoryPointerOverLimitHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(memoryOffsetOverLimitHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(memoryEndOfWordOverLimitHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(memoryGrow0To1PageHex).value() == 1);
BEAST_EXPECT(runFinishFunction(memoryGrow1To0PageHex).value() == -1);
BEAST_EXPECT(runFinishFunction(memoryLastByteOf8MBHex).value() == 1);
BEAST_EXPECT(runFinishFunction(memoryGrow1MoreThan8MBHex).value() == -1);
BEAST_EXPECT(runFinishFunction(memoryGrow0MoreThan8MBHex).value() == 1);
BEAST_EXPECT(runFinishFunction(memoryInit1MoreThan8MBHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(memoryNegativeAddressHex).has_value() == false);
}
void
testWasmTable()
{
testcase("Wasm table limit tests");
BEAST_EXPECT(runFinishFunction(table64ElementsHex).value() == 1);
BEAST_EXPECT(runFinishFunction(table65ElementsHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(table2TablesHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(table0ElementsHex).value() == 1);
BEAST_EXPECT(runFinishFunction(tableUintMaxHex).has_value() == false);
}
void
testWasmProposal()
{
testcase("Wasm disabled proposal tests");
BEAST_EXPECT(runFinishFunction(proposalMutableGlobalHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(proposalGcStructNewHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(proposalMultiValueHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(proposalSignExtHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(proposalFloatToIntHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(proposalBulkMemoryHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(proposalRefTypesHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(proposalTailCallHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(proposalExtendedConstHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(proposalMultiMemoryHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(proposalCustomPageSizesHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(proposalMemory64Hex).has_value() == false);
BEAST_EXPECT(runFinishFunction(proposalWideArithmeticHex).has_value() == false);
}
void
testWasmTrap()
{
testcase("Wasm trap tests");
BEAST_EXPECT(runFinishFunction(trapDivideBy0Hex).has_value() == false);
BEAST_EXPECT(runFinishFunction(trapIntOverflowHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(trapUnreachableHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(trapNullCallHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(trapFuncSigMismatchHex).has_value() == false);
}
void
testWasmWasi()
{
testcase("Wasm Wasi tests");
BEAST_EXPECT(runFinishFunction(wasiGetTimeHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(wasiPrintHex).has_value() == false);
}
void
testWasmSectionCorruption()
{
testcase("Wasm Section Corruption tests");
BEAST_EXPECT(runFinishFunction(badMagicNumberHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(badVersionNumberHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(lyingHeaderHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(neverEndingNumberHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(vectorLieHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(sectionOrderingHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(ghostPayloadHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(junkAfterSectionHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(invalidSectionIdHex).has_value() == false);
BEAST_EXPECT(runFinishFunction(localVariableBombHex).has_value() == false);
}
void
testStartFunctionLoop()
{
testcase("infinite loop in start function");
using namespace test::jtx;
Env env(*this);
auto const startLoopWasm = hexToBytes(startLoopHex);
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
auto& engine = WasmEngine::instance();
auto checkRes = engine.check(startLoopWasm, "finish", {}, imports, hfs, env.journal);
BEAST_EXPECTS(checkRes == tesSUCCESS, std::to_string(TERtoInt(checkRes)));
auto re = engine.run(startLoopWasm, ESCROW_FUNCTION_NAME, {}, imports, hfs, 1'000'000, env.journal);
BEAST_EXPECTS(re.error() == tecFAILED_PROCESSING, std::to_string(TERtoInt(re.error())));
}
void
testBadAlloc()
{
testcase("Wasm Bad Alloc");
// bad_alloc.c
auto const badAllocWasm = hexToBytes(badAllocHex);
using namespace test::jtx;
Env env{*this};
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
// std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
uint8_t buf1[8] = {7, 8, 9, 10, 11, 12, 13, 14};
{ // forged "allocate" return valid address
std::vector<WasmParam> params = {{.type = WT_U8V, .of = {.u8v = {.d = buf1, .sz = sizeof(buf1)}}}};
auto& engine = WasmEngine::instance();
auto re = engine.run(badAllocWasm, "test", params, {}, hfs, 1'000'000, env.journal);
if (BEAST_EXPECT(re))
{
BEAST_EXPECTS(re->result == 7, std::to_string(re->result));
BEAST_EXPECTS(re->cost == 430, std::to_string(re->cost));
}
}
{ // return 0 whithout calling wasm
std::vector<WasmParam> params = {{.type = WT_U8V, .of = {.u8v = {.d = buf1, .sz = 0}}}};
auto& engine = WasmEngine::instance();
auto re = engine.run(badAllocWasm, "test", params, {}, hfs, 1'000'000, env.journal);
BEAST_EXPECT(!re) && BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
}
{ // forged "allocate" return 8Mb (which is more than memory limit)
std::vector<WasmParam> params = {{.type = WT_U8V, .of = {.u8v = {.d = buf1, .sz = 1}}}};
auto& engine = WasmEngine::instance();
auto re = engine.run(badAllocWasm, "test", params, {}, hfs, 1'000'000, env.journal);
BEAST_EXPECT(!re) && BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
}
{ // forged "allocate" return 0
std::vector<WasmParam> params = {{.type = WT_U8V, .of = {.u8v = {.d = buf1, .sz = 2}}}};
auto& engine = WasmEngine::instance();
auto re = engine.run(badAllocWasm, "test", params, {}, hfs, 1'000'000, env.journal);
BEAST_EXPECT(!re) && BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
}
{ // forged "allocate" return -1
std::vector<WasmParam> params = {{.type = WT_U8V, .of = {.u8v = {.d = buf1, .sz = 3}}}};
auto& engine = WasmEngine::instance();
auto re = engine.run(badAllocWasm, "test", params, {}, hfs, 1'000'000, env.journal);
BEAST_EXPECT(!re) && BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
}
{
std::string what;
try
{
char const test[] = "test";
std::size_t sz = std::numeric_limits<int32_t>::max() + 1ull;
auto p = wasmParams(std::string_view(test, sz));
}
catch (std::exception const& e)
{
what = e.what();
}
BEAST_EXPECT(what.find("can't allocate memory, size: 2147483648") != std::string::npos);
}
env.close();
}
void
testBadAlign()
{
testcase("Wasm Bad Align");
// bad_align.c
auto const badAlignWasm = hexToBytes(badAlignHex);
using namespace test::jtx;
Env env{*this};
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
auto imports = createWasmImport(*hfs);
{ // Calls float_from_uint with bad aligment.
// Can be checked through codecov
auto& engine = WasmEngine::instance();
auto re = engine.run(badAlignWasm, "test", {}, imports, hfs, 1'000'000, env.journal);
BEAST_EXPECT(re && re->result == 0xbab88d46);
}
env.close();
}
void
testReturnType()
{
using namespace test::jtx;
Env env(*this);
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
// return int64.
{ // (module
// (memory (export "memory") 1)
// (func (export "finish") (result i64)
// i64.const 0x100000000))
auto const wasmHex =
"0061736d010000000105016000017e030201000503010001"
"071302066d656d6f727902000666696e69736800000a0a01"
"08004280808080100b";
auto const wasm = hexToBytes(wasmHex);
auto const re = runEscrowWasm(wasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
BEAST_EXPECT(!re);
}
// return void. wasmi return execution error
{ //(module
// (type (;0;) (func))
// (func (;0;) (type 0)
// return)
// (memory (;0;) 1)
// (export "memory" (memory 0))
// (export "finish" (func 0)))
auto const wasmHex =
"0061736d01000000010401600000030201000503010001071302066d656d6f"
"727902000666696e69736800000a050103000f0b";
auto const wasm = hexToBytes(wasmHex);
auto const re = runEscrowWasm(wasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
BEAST_EXPECT(!re);
}
// return i32, i32. wasmi doesn't create module
{ //(module
// (memory (export "memory") 1)
// (func (export "finish") (result i32 i32)
// i32.const 0x10000000
// i32.const 0x100000FF))
auto const wasmHex =
"0061736d010000000106016000027f7f030201000503010001071302066d65"
"6d6f727902000666696e69736800000a10010e0041808080800141ff818080"
"010b";
auto const wasm = hexToBytes(wasmHex);
auto const re = runEscrowWasm(wasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
BEAST_EXPECT(!re);
}
}
void
testSwapBytes()
{
testcase("Wasm swap bytes");
uint64_t const SWAP_DATAU64 = 0x123456789abcdeffull;
uint64_t const REVERSE_SWAP_DATAU64 = 0xffdebc9a78563412ull;
int64_t const SWAP_DATAI64 = 0x123456789abcdeffll;
int64_t const REVERSE_SWAP_DATAI64 = 0xffdebc9a78563412ll;
uint32_t const SWAP_DATAU32 = 0x12789aff;
uint32_t const REVERSE_SWAP_DATAU32 = 0xff9a7812;
int32_t const SWAP_DATAI32 = 0x12789aff;
int32_t const REVERSE_SWAP_DATAI32 = 0xff9a7812;
uint16_t const SWAP_DATAU16 = 0x12ff;
uint16_t const REVERSE_SWAP_DATAU16 = 0xff12;
int16_t const SWAP_DATAI16 = 0x12ff;
int16_t const REVERSE_SWAP_DATAI16 = 0xff12;
uint64_t b1 = SWAP_DATAU64;
int64_t b2 = SWAP_DATAI64;
b1 = adjustWasmEndianessHlp(b1);
b2 = adjustWasmEndianessHlp(b2);
BEAST_EXPECT(b1 == REVERSE_SWAP_DATAU64);
BEAST_EXPECT(b2 == REVERSE_SWAP_DATAI64);
b1 = adjustWasmEndianessHlp(b1);
b2 = adjustWasmEndianessHlp(b2);
BEAST_EXPECT(b1 == SWAP_DATAU64);
BEAST_EXPECT(b2 == SWAP_DATAI64);
uint32_t b3 = SWAP_DATAU32;
int32_t b4 = SWAP_DATAI32;
b3 = adjustWasmEndianessHlp(b3);
b4 = adjustWasmEndianessHlp(b4);
BEAST_EXPECT(b3 == REVERSE_SWAP_DATAU32);
BEAST_EXPECT(b4 == REVERSE_SWAP_DATAI32);
b3 = adjustWasmEndianessHlp(b3);
b4 = adjustWasmEndianessHlp(b4);
BEAST_EXPECT(b3 == SWAP_DATAU32);
BEAST_EXPECT(b4 == SWAP_DATAI32);
uint16_t b5 = SWAP_DATAU16;
int16_t b6 = SWAP_DATAI16;
b5 = adjustWasmEndianessHlp(b5);
b6 = adjustWasmEndianessHlp(b6);
BEAST_EXPECT(b5 == REVERSE_SWAP_DATAU16);
BEAST_EXPECT(b6 == REVERSE_SWAP_DATAI16);
b5 = adjustWasmEndianessHlp(b5);
b6 = adjustWasmEndianessHlp(b6);
BEAST_EXPECT(b5 == SWAP_DATAU16);
BEAST_EXPECT(b6 == SWAP_DATAI16);
}
void
run() override
{
using namespace test::jtx;
testGetDataHelperFunctions();
testWasmLib();
testBadWasm();
testWasmLedgerSqn();
testWasmFib();
testWasmSha();
testWasmB58();
testHFCost();
testEscrowWasmDN();
testFloat();
testCodecovWasm();
testDisabledFloat();
testWasmMemory();
testWasmTable();
testWasmProposal();
testWasmTrap();
testWasmWasi();
testWasmSectionCorruption();
testStartFunctionLoop();
testBadAlloc();
testBadAlign();
testReturnType();
testSwapBytes();
// perfTest();
}
};
BEAST_DEFINE_TESTSUITE(Wasm, app, xrpl);
} // namespace test
} // namespace xrpl

View File

@@ -1,3 +0,0 @@
**/target
**/debug
*.wasm

View File

@@ -1,171 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "all_host_functions"
version = "0.1.0"
dependencies = [
"xrpl-wasm-stdlib",
]
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "bs58"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4"
dependencies = [
"tinyvec",
]
[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "cpufeatures"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "generic-array"
version = "0.14.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "libc"
version = "0.2.177"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
[[package]]
name = "proc-macro2"
version = "1.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
dependencies = [
"proc-macro2",
]
[[package]]
name = "sha2"
version = "0.10.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "syn"
version = "2.0.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tinyvec"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "typenum"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
[[package]]
name = "unicode-ident"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "xrpl-address-macro"
version = "0.7.1"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git#d27d3e0b4abf3c0215aade729d89053805efe48e"
dependencies = [
"bs58",
"quote",
"sha2",
"syn",
]
[[package]]
name = "xrpl-wasm-stdlib"
version = "0.7.1"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git#d27d3e0b4abf3c0215aade729d89053805efe48e"
dependencies = [
"xrpl-address-macro",
]

View File

@@ -1,21 +0,0 @@
[package]
name = "all_host_functions"
version = "0.1.0"
edition = "2024"
# This empty workspace definition keeps this project independent of the parent workspace
[workspace]
[lib]
crate-type = ["cdylib"]
[dependencies]
xrpl-std = { git = "https://github.com/ripple/xrpl-wasm-stdlib.git", package = "xrpl-wasm-stdlib" }
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
opt-level = "z"
lto = true

View File

@@ -1,772 +0,0 @@
#![cfg_attr(target_arch = "wasm32", no_std)]
#[cfg(not(target_arch = "wasm32"))]
extern crate std;
//
// Host Functions Test
// Tests 26 host functions (across 7 categories)
//
// With craft you can run this test with:
// craft test --project host_functions_test --test-case host_functions_test
//
// Amount Format Update:
// - XRP amounts now return as 8-byte serialized rippled objects
// - IOU and MPT amounts return in variable-length serialized format
// - Format details: https://xrpl.org/docs/references/protocol/binary-format#amount-fields
//
// Error Code Ranges:
// -100 to -199: Ledger Header Functions (3 functions)
// -200 to -299: Transaction Data Functions (5 functions)
// -300 to -399: Current Ledger Object Functions (4 functions)
// -400 to -499: Any Ledger Object Functions (5 functions)
// -500 to -599: Keylet Generation Functions (4 functions)
// -600 to -699: Utility Functions (4 functions)
// -700 to -799: Data Update Functions (1 function)
//
use xrpl_std::core::current_tx::escrow_finish::EscrowFinish;
use xrpl_std::core::current_tx::traits::TransactionCommonFields;
use xrpl_std::host;
use xrpl_std::host::trace::{trace, trace_account_buf, trace_data, trace_num, DataRepr};
use xrpl_std::sfield;
#[unsafe(no_mangle)]
pub extern "C" fn finish() -> i32 {
let _ = trace("=== HOST FUNCTIONS TEST ===");
let _ = trace("Testing 26 host functions");
// Category 1: Ledger Header Data Functions (3 functions)
// Error range: -100 to -199
match test_ledger_header_functions() {
0 => (),
err => return err,
}
// Category 2: Transaction Data Functions (5 functions)
// Error range: -200 to -299
match test_transaction_data_functions() {
0 => (),
err => return err,
}
// Category 3: Current Ledger Object Functions (4 functions)
// Error range: -300 to -399
match test_current_ledger_object_functions() {
0 => (),
err => return err,
}
// Category 4: Any Ledger Object Functions (5 functions)
// Error range: -400 to -499
match test_any_ledger_object_functions() {
0 => (),
err => return err,
}
// Category 5: Keylet Generation Functions (4 functions)
// Error range: -500 to -599
match test_keylet_generation_functions() {
0 => (),
err => return err,
}
// Category 6: Utility Functions (4 functions)
// Error range: -600 to -699
match test_utility_functions() {
0 => (),
err => return err,
}
// Category 7: Data Update Functions (1 function)
// Error range: -700 to -799
match test_data_update_functions() {
0 => (),
err => return err,
}
let _ = trace("SUCCESS: All host function tests passed!");
1 // Success return code for WASM finish function
}
/// Test Category 1: Ledger Header Data Functions (3 functions)
/// - get_ledger_sqn() - Get ledger sequence number
/// - get_parent_ledger_time() - Get parent ledger timestamp
/// - get_parent_ledger_hash() - Get parent ledger hash
fn test_ledger_header_functions() -> i32 {
let _ = trace("--- Category 1: Ledger Header Functions ---");
// Test 1.1: get_ledger_sqn() - should return current ledger sequence number
let sqn_result = unsafe { host::get_ledger_sqn() };
if sqn_result <= 0 {
let _ = trace_num("ERROR: get_ledger_sqn failed:", sqn_result as i64);
return -101; // Ledger sequence number test failed
}
let _ = trace_num("Ledger sequence number:", sqn_result as i64);
// Test 1.2: get_parent_ledger_time() - should return parent ledger timestamp
let time_result = unsafe { host::get_parent_ledger_time() };
if time_result <= 0 {
let _ = trace_num("ERROR: get_parent_ledger_time failed:", time_result as i64);
return -102; // Parent ledger time test failed
}
let _ = trace_num("Parent ledger time:", time_result as i64);
// Test 1.3: get_parent_ledger_hash() - should return parent ledger hash (32 bytes)
let mut hash_buffer = [0u8; 32];
let hash_result =
unsafe { host::get_parent_ledger_hash(hash_buffer.as_mut_ptr(), hash_buffer.len()) };
if hash_result != 32 {
let _ = trace_num(
"ERROR: get_parent_ledger_hash wrong length:",
hash_result as i64,
);
return -103; // Parent ledger hash test failed - should be exactly 32 bytes
}
let _ = trace_data("Parent ledger hash:", &hash_buffer, DataRepr::AsHex);
let _ = trace("SUCCESS: Ledger header functions");
0
}
/// Test Category 2: Transaction Data Functions (5 functions)
/// Tests all functions for accessing current transaction data
fn test_transaction_data_functions() -> i32 {
let _ = trace("--- Category 2: Transaction Data Functions ---");
// Test 2.1: get_tx_field() - Basic transaction field access
// Test with Account field (required, 20 bytes)
let mut account_buffer = [0u8; 20];
let account_len = unsafe {
host::get_tx_field(
sfield::Account,
account_buffer.as_mut_ptr(),
account_buffer.len(),
)
};
if account_len != 20 {
let _ = trace_num(
"ERROR: get_tx_field(Account) wrong length:",
account_len as i64,
);
return -201; // Basic transaction field test failed
}
let _ = trace_account_buf("Transaction Account:", &account_buffer);
// Test with Fee field (XRP amount - 8 bytes in new serialized format)
// New format: XRP amounts are always 8 bytes (positive: value | cPositive flag, negative: just value)
let mut fee_buffer = [0u8; 8];
let fee_len =
unsafe { host::get_tx_field(sfield::Fee, fee_buffer.as_mut_ptr(), fee_buffer.len()) };
if fee_len != 8 {
let _ = trace_num(
"ERROR: get_tx_field(Fee) wrong length (expected 8 bytes for XRP):",
fee_len as i64,
);
return -202; // Fee field test failed - XRP amounts should be exactly 8 bytes
}
let _ = trace_num("Transaction Fee length:", fee_len as i64);
let _ = trace_data(
"Transaction Fee (serialized XRP amount):",
&fee_buffer,
DataRepr::AsHex,
);
// Test with Sequence field (required, 4 bytes uint32)
let mut seq_buffer = [0u8; 4];
let seq_len =
unsafe { host::get_tx_field(sfield::Sequence, seq_buffer.as_mut_ptr(), seq_buffer.len()) };
if seq_len != 4 {
let _ = trace_num(
"ERROR: get_tx_field(Sequence) wrong length:",
seq_len as i64,
);
return -203; // Sequence field test failed
}
let _ = trace_data("Transaction Sequence:", &seq_buffer, DataRepr::AsHex);
// NOTE: get_tx_field2() through get_tx_field6() have been deprecated.
// Use get_tx_field() with appropriate parameters for all transaction field access.
// Test 2.2: get_tx_nested_field() - Nested field access with locator
let locator = [0x01, 0x00]; // Simple locator for first element
let mut nested_buffer = [0u8; 32];
let nested_result = unsafe {
host::get_tx_nested_field(
locator.as_ptr(),
locator.len(),
nested_buffer.as_mut_ptr(),
nested_buffer.len(),
)
};
if nested_result < 0 {
let _ = trace_num(
"INFO: get_tx_nested_field not applicable:",
nested_result as i64,
);
// Expected - locator may not match transaction structure
} else {
let _ = trace_num("Nested field length:", nested_result as i64);
let _ = trace_data(
"Nested field:",
&nested_buffer[..nested_result as usize],
DataRepr::AsHex,
);
}
// Test 2.3: get_tx_array_len() - Get array length
let signers_len = unsafe { host::get_tx_array_len(sfield::Signers) };
let _ = trace_num("Signers array length:", signers_len as i64);
let memos_len = unsafe { host::get_tx_array_len(sfield::Memos) };
let _ = trace_num("Memos array length:", memos_len as i64);
// Test 2.4: get_tx_nested_array_len() - Get nested array length with locator
let nested_array_len =
unsafe { host::get_tx_nested_array_len(locator.as_ptr(), locator.len()) };
if nested_array_len < 0 {
let _ = trace_num(
"INFO: get_tx_nested_array_len not applicable:",
nested_array_len as i64,
);
} else {
let _ = trace_num("Nested array length:", nested_array_len as i64);
}
let _ = trace("SUCCESS: Transaction data functions");
0
}
/// Test Category 3: Current Ledger Object Functions (4 functions)
/// Tests functions that access the current ledger object being processed
fn test_current_ledger_object_functions() -> i32 {
let _ = trace("--- Category 3: Current Ledger Object Functions ---");
// Test 3.1: get_current_ledger_obj_field() - Access field from current ledger object
// Test with Balance field (XRP amount - 8 bytes in new serialized format)
let mut balance_buffer = [0u8; 8];
let balance_result = unsafe {
host::get_current_ledger_obj_field(
sfield::Balance,
balance_buffer.as_mut_ptr(),
balance_buffer.len(),
)
};
if balance_result <= 0 {
let _ = trace_num(
"INFO: get_current_ledger_obj_field(Balance) failed (may be expected):",
balance_result as i64,
);
// This might fail if current ledger object doesn't have balance field
} else if balance_result == 8 {
let _ = trace_num(
"Current object balance length (XRP amount):",
balance_result as i64,
);
let _ = trace_data(
"Current object balance (serialized XRP amount):",
&balance_buffer,
DataRepr::AsHex,
);
} else {
let _ = trace_num(
"Current object balance length (non-XRP amount):",
balance_result as i64,
);
let _ = trace_data(
"Current object balance:",
&balance_buffer[..balance_result as usize],
DataRepr::AsHex,
);
}
// Test with Account field
let mut current_account_buffer = [0u8; 20];
let current_account_result = unsafe {
host::get_current_ledger_obj_field(
sfield::Account,
current_account_buffer.as_mut_ptr(),
current_account_buffer.len(),
)
};
if current_account_result <= 0 {
let _ = trace_num(
"INFO: get_current_ledger_obj_field(Account) failed:",
current_account_result as i64,
);
} else {
let _ = trace_account_buf("Current ledger object account:", &current_account_buffer);
}
// Test 3.2: get_current_ledger_obj_nested_field() - Nested field access
let locator = [0x01, 0x00]; // Simple locator
let mut current_nested_buffer = [0u8; 32];
let current_nested_result = unsafe {
host::get_current_ledger_obj_nested_field(
locator.as_ptr(),
locator.len(),
current_nested_buffer.as_mut_ptr(),
current_nested_buffer.len(),
)
};
if current_nested_result < 0 {
let _ = trace_num(
"INFO: get_current_ledger_obj_nested_field not applicable:",
current_nested_result as i64,
);
} else {
let _ = trace_num("Current nested field length:", current_nested_result as i64);
let _ = trace_data(
"Current nested field:",
&current_nested_buffer[..current_nested_result as usize],
DataRepr::AsHex,
);
}
// Test 3.3: get_current_ledger_obj_array_len() - Array length in current object
let current_array_len = unsafe { host::get_current_ledger_obj_array_len(sfield::Signers) };
let _ = trace_num(
"Current object Signers array length:",
current_array_len as i64,
);
// Test 3.4: get_current_ledger_obj_nested_array_len() - Nested array length
let current_nested_array_len =
unsafe { host::get_current_ledger_obj_nested_array_len(locator.as_ptr(), locator.len()) };
if current_nested_array_len < 0 {
let _ = trace_num(
"INFO: get_current_ledger_obj_nested_array_len not applicable:",
current_nested_array_len as i64,
);
} else {
let _ = trace_num(
"Current nested array length:",
current_nested_array_len as i64,
);
}
let _ = trace("SUCCESS: Current ledger object functions");
0
}
/// Test Category 4: Any Ledger Object Functions (5 functions)
/// Tests functions that work with cached ledger objects
fn test_any_ledger_object_functions() -> i32 {
let _ = trace("--- Category 4: Any Ledger Object Functions ---");
// First we need to cache a ledger object to test the other functions
// Get the account from transaction and generate its keylet
let escrow_finish = EscrowFinish;
let account_id = escrow_finish.get_account().unwrap();
// Test 4.1: cache_ledger_obj() - Cache a ledger object
let mut keylet_buffer = [0u8; 32];
let keylet_result = unsafe {
host::account_keylet(
account_id.0.as_ptr(),
account_id.0.len(),
keylet_buffer.as_mut_ptr(),
keylet_buffer.len(),
)
};
if keylet_result != 32 {
let _ = trace_num(
"ERROR: account_keylet failed for caching test:",
keylet_result as i64,
);
return -401; // Keylet generation failed for caching test
}
let cache_result =
unsafe { host::cache_ledger_obj(keylet_buffer.as_ptr(), keylet_result as usize, 0) };
if cache_result <= 0 {
let _ = trace_num(
"INFO: cache_ledger_obj failed (expected with test fixtures):",
cache_result as i64,
);
// Test fixtures may not contain the account object - this is expected
// We'll test the interface but expect failures
// Test 4.2-4.5 with invalid slot (should fail gracefully)
let mut test_buffer = [0u8; 32];
// Test get_ledger_obj_field with invalid slot
let field_result = unsafe {
host::get_ledger_obj_field(
1,
sfield::Balance,
test_buffer.as_mut_ptr(),
test_buffer.len(),
)
};
if field_result < 0 {
let _ = trace_num(
"INFO: get_ledger_obj_field failed as expected (no cached object):",
field_result as i64,
);
}
// Test get_ledger_obj_nested_field with invalid slot
let locator = [0x01, 0x00];
let nested_result = unsafe {
host::get_ledger_obj_nested_field(
1,
locator.as_ptr(),
locator.len(),
test_buffer.as_mut_ptr(),
test_buffer.len(),
)
};
if nested_result < 0 {
let _ = trace_num(
"INFO: get_ledger_obj_nested_field failed as expected:",
nested_result as i64,
);
}
// Test get_ledger_obj_array_len with invalid slot
let array_result = unsafe { host::get_ledger_obj_array_len(1, sfield::Signers) };
if array_result < 0 {
let _ = trace_num(
"INFO: get_ledger_obj_array_len failed as expected:",
array_result as i64,
);
}
// Test get_ledger_obj_nested_array_len with invalid slot
let nested_array_result =
unsafe { host::get_ledger_obj_nested_array_len(1, locator.as_ptr(), locator.len()) };
if nested_array_result < 0 {
let _ = trace_num(
"INFO: get_ledger_obj_nested_array_len failed as expected:",
nested_array_result as i64,
);
}
let _ = trace("SUCCESS: Any ledger object functions (interface tested)");
return 0;
}
// If we successfully cached an object, test the access functions
let slot = cache_result;
let _ = trace_num("Successfully cached object in slot:", slot as i64);
// Test 4.2: get_ledger_obj_field() - Access field from cached object
let mut cached_balance_buffer = [0u8; 8];
let cached_balance_result = unsafe {
host::get_ledger_obj_field(
slot,
sfield::Balance,
cached_balance_buffer.as_mut_ptr(),
cached_balance_buffer.len(),
)
};
if cached_balance_result <= 0 {
let _ = trace_num(
"INFO: get_ledger_obj_field(Balance) failed:",
cached_balance_result as i64,
);
} else if cached_balance_result == 8 {
let _ = trace_num(
"Cached object balance length (XRP amount):",
cached_balance_result as i64,
);
let _ = trace_data(
"Cached object balance (serialized XRP amount):",
&cached_balance_buffer,
DataRepr::AsHex,
);
} else {
let _ = trace_num(
"Cached object balance length (non-XRP amount):",
cached_balance_result as i64,
);
let _ = trace_data(
"Cached object balance:",
&cached_balance_buffer[..cached_balance_result as usize],
DataRepr::AsHex,
);
}
// Test 4.3: get_ledger_obj_nested_field() - Nested field from cached object
let locator = [0x01, 0x00];
let mut cached_nested_buffer = [0u8; 32];
let cached_nested_result = unsafe {
host::get_ledger_obj_nested_field(
slot,
locator.as_ptr(),
locator.len(),
cached_nested_buffer.as_mut_ptr(),
cached_nested_buffer.len(),
)
};
if cached_nested_result < 0 {
let _ = trace_num(
"INFO: get_ledger_obj_nested_field not applicable:",
cached_nested_result as i64,
);
} else {
let _ = trace_num("Cached nested field length:", cached_nested_result as i64);
let _ = trace_data(
"Cached nested field:",
&cached_nested_buffer[..cached_nested_result as usize],
DataRepr::AsHex,
);
}
// Test 4.4: get_ledger_obj_array_len() - Array length from cached object
let cached_array_len = unsafe { host::get_ledger_obj_array_len(slot, sfield::Signers) };
let _ = trace_num(
"Cached object Signers array length:",
cached_array_len as i64,
);
// Test 4.5: get_ledger_obj_nested_array_len() - Nested array length from cached object
let cached_nested_array_len =
unsafe { host::get_ledger_obj_nested_array_len(slot, locator.as_ptr(), locator.len()) };
if cached_nested_array_len < 0 {
let _ = trace_num(
"INFO: get_ledger_obj_nested_array_len not applicable:",
cached_nested_array_len as i64,
);
} else {
let _ = trace_num(
"Cached nested array length:",
cached_nested_array_len as i64,
);
}
let _ = trace("SUCCESS: Any ledger object functions");
0
}
/// Test Category 5: Keylet Generation Functions (4 functions)
/// Tests keylet generation functions for different ledger entry types
fn test_keylet_generation_functions() -> i32 {
let _ = trace("--- Category 5: Keylet Generation Functions ---");
let escrow_finish = EscrowFinish;
let account_id = escrow_finish.get_account().unwrap();
// Test 5.1: account_keylet() - Generate keylet for account
let mut account_keylet_buffer = [0u8; 32];
let account_keylet_result = unsafe {
host::account_keylet(
account_id.0.as_ptr(),
account_id.0.len(),
account_keylet_buffer.as_mut_ptr(),
account_keylet_buffer.len(),
)
};
if account_keylet_result != 32 {
let _ = trace_num(
"ERROR: account_keylet failed:",
account_keylet_result as i64,
);
return -501; // Account keylet generation failed
}
let _ = trace_data("Account keylet:", &account_keylet_buffer, DataRepr::AsHex);
// Test 5.2: credential_keylet() - Generate keylet for credential
let mut credential_keylet_buffer = [0u8; 32];
let credential_keylet_result = unsafe {
host::credential_keylet(
account_id.0.as_ptr(), // Subject
account_id.0.len(),
account_id.0.as_ptr(), // Issuer - same account for test
account_id.0.len(),
b"TestType".as_ptr(), // Credential type
9usize, // Length of "TestType"
credential_keylet_buffer.as_mut_ptr(),
credential_keylet_buffer.len(),
)
};
if credential_keylet_result <= 0 {
let _ = trace_num(
"INFO: credential_keylet failed (expected - interface issue):",
credential_keylet_result as i64,
);
// This is expected to fail due to unusual parameter types
} else {
let _ = trace_data(
"Credential keylet:",
&credential_keylet_buffer[..credential_keylet_result as usize],
DataRepr::AsHex,
);
}
// Test 5.3: escrow_keylet() - Generate keylet for escrow
let mut escrow_keylet_buffer = [0u8; 32];
let escrow_keylet_result = unsafe {
host::escrow_keylet(
account_id.0.as_ptr(),
account_id.0.len(),
1000, // Sequence number
escrow_keylet_buffer.as_mut_ptr(),
escrow_keylet_buffer.len(),
)
};
if escrow_keylet_result != 32 {
let _ = trace_num("ERROR: escrow_keylet failed:", escrow_keylet_result as i64);
return -503; // Escrow keylet generation failed
}
let _ = trace_data("Escrow keylet:", &escrow_keylet_buffer, DataRepr::AsHex);
// Test 5.4: oracle_keylet() - Generate keylet for oracle
let mut oracle_keylet_buffer = [0u8; 32];
let oracle_keylet_result = unsafe {
host::oracle_keylet(
account_id.0.as_ptr(),
account_id.0.len(),
42, // Document ID
oracle_keylet_buffer.as_mut_ptr(),
oracle_keylet_buffer.len(),
)
};
if oracle_keylet_result != 32 {
let _ = trace_num("ERROR: oracle_keylet failed:", oracle_keylet_result as i64);
return -504; // Oracle keylet generation failed
}
let _ = trace_data("Oracle keylet:", &oracle_keylet_buffer, DataRepr::AsHex);
let _ = trace("SUCCESS: Keylet generation functions");
0
}
/// Test Category 6: Utility Functions (4 functions)
/// Tests utility functions for hashing, NFT access, and tracing
fn test_utility_functions() -> i32 {
let _ = trace("--- Category 6: Utility Functions ---");
// Test 6.1: compute_sha512_half() - SHA512 hash computation (first 32 bytes)
let test_data = b"Hello, XRPL WASM world!";
let mut hash_output = [0u8; 32];
let hash_result = unsafe {
host::compute_sha512_half(
test_data.as_ptr(),
test_data.len(),
hash_output.as_mut_ptr(),
hash_output.len(),
)
};
if hash_result != 32 {
let _ = trace_num("ERROR: compute_sha512_half failed:", hash_result as i64);
return -601; // SHA512 half computation failed
}
let _ = trace_data("Input data:", test_data, DataRepr::AsHex);
let _ = trace_data("SHA512 half hash:", &hash_output, DataRepr::AsHex);
// Test 6.2: get_nft() - NFT data retrieval
let escrow_finish = EscrowFinish;
let account_id = escrow_finish.get_account().unwrap();
let nft_id = [0u8; 32]; // Dummy NFT ID for testing
let mut nft_buffer = [0u8; 256];
let nft_result = unsafe {
host::get_nft(
account_id.0.as_ptr(),
account_id.0.len(),
nft_id.as_ptr(),
nft_id.len(),
nft_buffer.as_mut_ptr(),
nft_buffer.len(),
)
};
if nft_result <= 0 {
let _ = trace_num(
"INFO: get_nft failed (expected - no such NFT):",
nft_result as i64,
);
// This is expected - test account likely doesn't own the dummy NFT
} else {
let _ = trace_num("NFT data length:", nft_result as i64);
let _ = trace_data(
"NFT data:",
&nft_buffer[..nft_result as usize],
DataRepr::AsHex,
);
}
// Test 6.3: trace() - Debug logging with data
let trace_message = b"Test trace message";
let trace_data_payload = b"payload";
let trace_result = unsafe {
host::trace(
trace_message.as_ptr(),
trace_message.len(),
trace_data_payload.as_ptr(),
trace_data_payload.len(),
1, // as_hex = true
)
};
if trace_result < 0 {
let _ = trace_num("ERROR: trace() failed:", trace_result as i64);
return -603; // Trace function failed
}
let _ = trace_num("Trace function bytes written:", trace_result as i64);
// Test 6.4: trace_num() - Debug logging with number
let test_number = 42i64;
let trace_num_result = trace_num("Test number trace", test_number);
use xrpl_std::host::Result;
match trace_num_result {
Result::Ok(_) => {
let _ = trace_num("Trace_num function succeeded", 0);
}
Result::Err(_) => {
let _ = trace_num("ERROR: trace_num() failed:", -604);
return -604; // Trace number function failed
}
}
let _ = trace("SUCCESS: Utility functions");
0
}
/// Test Category 7: Data Update Functions (1 function)
/// Tests the function for modifying the current ledger entry
fn test_data_update_functions() -> i32 {
let _ = trace("--- Category 7: Data Update Functions ---");
// Test 7.1: update_data() - Update current ledger entry data
let update_payload = b"Updated ledger entry data from WASM test";
let update_result = unsafe { host::update_data(update_payload.as_ptr(), update_payload.len()) };
if update_result != update_payload.len() as i32 {
let _ = trace_num("ERROR: update_data failed:", update_result as i64);
return -701; // Data update failed
}
let _ = trace_data(
"Successfully updated ledger entry with:",
update_payload,
DataRepr::AsHex,
);
let _ = trace("SUCCESS: Data update functions");
0
}

View File

@@ -1,171 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "all_keylets"
version = "0.0.1"
dependencies = [
"xrpl-wasm-stdlib",
]
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "bs58"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4"
dependencies = [
"tinyvec",
]
[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "cpufeatures"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "generic-array"
version = "0.14.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "libc"
version = "0.2.177"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
[[package]]
name = "proc-macro2"
version = "1.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
dependencies = [
"proc-macro2",
]
[[package]]
name = "sha2"
version = "0.10.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "syn"
version = "2.0.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tinyvec"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "typenum"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
[[package]]
name = "unicode-ident"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "xrpl-address-macro"
version = "0.7.1"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git#d27d3e0b4abf3c0215aade729d89053805efe48e"
dependencies = [
"bs58",
"quote",
"sha2",
"syn",
]
[[package]]
name = "xrpl-wasm-stdlib"
version = "0.7.1"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git#d27d3e0b4abf3c0215aade729d89053805efe48e"
dependencies = [
"xrpl-address-macro",
]

View File

@@ -1,21 +0,0 @@
[package]
edition = "2024"
name = "all_keylets"
version = "0.0.1"
# This empty workspace definition keeps this project independent of the parent workspace
[workspace]
[lib]
crate-type = ["cdylib"]
[profile.release]
lto = true
opt-level = 's'
panic = "abort"
[dependencies]
xrpl-std = { git = "https://github.com/ripple/xrpl-wasm-stdlib.git", package = "xrpl-wasm-stdlib" }
[profile.dev]
panic = "abort"

View File

@@ -1,181 +0,0 @@
#![cfg_attr(target_arch = "wasm32", no_std)]
#[cfg(not(target_arch = "wasm32"))]
extern crate std;
use crate::host::{Error, Result, Result::Err, Result::Ok};
use xrpl_std::core::ledger_objects::current_escrow::get_current_escrow;
use xrpl_std::core::ledger_objects::current_escrow::CurrentEscrow;
use xrpl_std::core::ledger_objects::ledger_object;
use xrpl_std::core::ledger_objects::traits::CurrentEscrowFields;
use xrpl_std::core::types::account_id::AccountID;
use xrpl_std::core::types::currency::Currency;
use xrpl_std::core::types::issue::{IouIssue, Issue, XrpIssue};
use xrpl_std::core::types::keylets;
use xrpl_std::core::types::mpt_id::MptId;
use xrpl_std::core::types::uint::Hash256;
use xrpl_std::host;
use xrpl_std::host::trace::{trace, trace_account, trace_data, trace_num, DataRepr};
use xrpl_std::sfield;
#[unsafe(no_mangle)]
pub fn object_exists(
keylet_result: Result<keylets::KeyletBytes>,
keylet_type: &str,
field: i32,
) -> Result<bool> {
match keylet_result {
Ok(keylet) => {
let _ = trace_data(keylet_type, &keylet, DataRepr::AsHex);
let slot = unsafe { host::cache_ledger_obj(keylet.as_ptr(), keylet.len(), 0) };
if slot <= 0 {
let _ = trace_num("Error: ", slot.into());
return Err(Error::from_code(slot));
}
if field == 0 {
let new_field = sfield::PreviousTxnID;
let _ = trace_num("Getting field: ", new_field.into());
match ledger_object::get_field::<Hash256>(slot, new_field) {
Ok(data) => {
let _ = trace_data("Field data: ", &data.0, DataRepr::AsHex);
}
Err(result_code) => {
let _ = trace_num("Error getting field: ", result_code.into());
return Err(result_code);
}
}
} else {
let _ = trace_num("Getting field: ", field.into());
match ledger_object::get_field::<AccountID>(slot, field) {
Ok(data) => {
let _ = trace_data("Field data: ", &data.0, DataRepr::AsHex);
}
Err(result_code) => {
let _ = trace_num("Error getting field: ", result_code.into());
return Err(result_code);
}
}
}
Ok(true)
}
Err(error) => {
let _ = trace_num("Error getting keylet: ", error.into());
Err(error)
}
}
}
#[unsafe(no_mangle)]
pub extern "C" fn finish() -> i32 {
let _ = trace("$$$$$ STARTING WASM EXECUTION $$$$$");
let escrow: CurrentEscrow = get_current_escrow();
let account = escrow.get_account().unwrap_or_panic();
let _ = trace_account("Account:", &account);
let destination = escrow.get_destination().unwrap_or_panic();
let _ = trace_account("Destination:", &destination);
let mut seq = 5;
macro_rules! check_object_exists {
($keylet:expr, $type:expr, $field:expr) => {
match object_exists($keylet, $type, $field) {
Ok(_exists) => {
// false isn't returned
let _ = trace(concat!(
$type,
" object exists, proceeding with escrow finish."
));
}
Err(error) => {
let _ = trace_num("Current seq value:", seq.try_into().unwrap());
return error.code();
}
}
};
}
let account_keylet = keylets::account_keylet(&account);
check_object_exists!(account_keylet, "Account", sfield::Account);
let currency_code: &[u8; 3] = b"USD";
let currency: Currency = Currency::from(*currency_code);
let line_keylet = keylets::line_keylet(&account, &destination, &currency);
check_object_exists!(line_keylet, "Trustline", sfield::Generic);
seq += 1;
let asset1 = Issue::XRP(XrpIssue {});
let asset2 = Issue::IOU(IouIssue::new(destination, currency));
check_object_exists!(
keylets::amm_keylet(&asset1, &asset2),
"AMM",
sfield::Account
);
let check_keylet = keylets::check_keylet(&account, seq);
check_object_exists!(check_keylet, "Check", sfield::Account);
seq += 1;
let cred_type: &[u8] = b"termsandconditions";
let credential_keylet = keylets::credential_keylet(&account, &account, cred_type);
check_object_exists!(credential_keylet, "Credential", sfield::Subject);
seq += 1;
let delegate_keylet = keylets::delegate_keylet(&account, &destination);
check_object_exists!(delegate_keylet, "Delegate", sfield::Account);
seq += 1;
let deposit_preauth_keylet = keylets::deposit_preauth_keylet(&account, &destination);
check_object_exists!(deposit_preauth_keylet, "DepositPreauth", sfield::Account);
seq += 1;
let did_keylet = keylets::did_keylet(&account);
check_object_exists!(did_keylet, "DID", sfield::Account);
seq += 1;
let escrow_keylet = keylets::escrow_keylet(&account, seq);
check_object_exists!(escrow_keylet, "Escrow", sfield::Account);
seq += 1;
let mpt_issuance_keylet = keylets::mpt_issuance_keylet(&account, seq);
let mpt_id = MptId::new(seq.try_into().unwrap(), account);
check_object_exists!(mpt_issuance_keylet, "MPTIssuance", sfield::Issuer);
seq += 1;
let mptoken_keylet = keylets::mptoken_keylet(&mpt_id, &destination);
check_object_exists!(mptoken_keylet, "MPToken", sfield::Account);
let nft_offer_keylet = keylets::nft_offer_keylet(&destination, 6);
check_object_exists!(nft_offer_keylet, "NFTokenOffer", sfield::Owner);
let offer_keylet = keylets::offer_keylet(&account, seq);
check_object_exists!(offer_keylet, "Offer", sfield::Account);
seq += 1;
let paychan_keylet = keylets::paychan_keylet(&account, &destination, seq);
check_object_exists!(paychan_keylet, "PayChannel", sfield::Account);
seq += 1;
let pd_keylet = keylets::permissioned_domain_keylet(&account, seq);
check_object_exists!(pd_keylet, "PermissionedDomain", sfield::Owner);
seq += 1;
let signers_keylet = keylets::signers_keylet(&account);
check_object_exists!(signers_keylet, "SignerList", sfield::Generic);
seq += 1;
seq += 1; // ticket sequence number is one greater
let ticket_keylet = keylets::ticket_keylet(&account, seq);
check_object_exists!(ticket_keylet, "Ticket", sfield::Account);
seq += 1;
let vault_keylet = keylets::vault_keylet(&account, seq);
check_object_exists!(vault_keylet, "Vault", sfield::Account);
// seq += 1;
1 // All keylets exist, finish the escrow.
}

View File

@@ -1,72 +0,0 @@
#include <stdint.h>
static char const b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
uint8_t e_data[32 * 1024];
void*
allocate(int sz)
{
static int idx = 0;
if (idx >= 32)
return 0;
if (sz > 1024)
return 0;
return &e_data[idx++ << 10];
}
void
deallocate(void* p)
{
}
extern int32_t
b58enco(char* b58, int32_t b58sz, void const* data, int32_t binsz)
{
uint8_t const* bin = data;
int32_t carry;
int32_t i, j, high, zcount = 0;
int32_t size;
while (zcount < binsz && !bin[zcount])
++zcount;
size = (binsz - zcount) * 138 / 100 + 1;
uint8_t* buf = allocate(size);
if (!buf)
return 0;
// memset(buf, 0, size);
for (i = 0; i < size; ++i)
buf[i] = 0;
for (i = zcount, high = size - 1; i < binsz; ++i, high = j)
{
for (carry = bin[i], j = size - 1; (j > high) || carry; --j)
{
carry += 256 * buf[j];
buf[j] = carry % 58;
carry /= 58;
if (!j)
break;
}
}
for (j = 0; j < size && !buf[j]; ++j)
;
if (b58sz <= zcount + size - j)
return 0;
if (zcount)
{
// memset(b58, '1', zcount);
for (i = 0; i < zcount; ++i)
b58[i] = '1';
}
for (i = zcount; j < size; ++i, ++j)
b58[i] = b58digits_ordered[buf[j]];
b58[i] = '\0';
return i + 1;
}

View File

@@ -1,23 +0,0 @@
#include <stdint.h>
int32_t
float_from_uint(uint8_t const*, int32_t, uint8_t*, int32_t, int32_t);
int32_t
get_tx_nested_field(uint8_t const*, int32_t, uint8_t*, int32_t);
uint8_t e_data[32 * 1024];
int32_t
test()
{
e_data[1] = 0xFF;
e_data[2] = 0xFF;
e_data[3] = 0xFF;
e_data[4] = 0xFF;
e_data[5] = 0xFF;
e_data[6] = 0xFF;
e_data[7] = 0xFF;
e_data[8] = 0xFF;
float_from_uint(&e_data[1], 8, &e_data[35], 12, 0);
return *((int32_t*)(&e_data[36]));
}

View File

@@ -1,27 +0,0 @@
#include <stdint.h>
char buf[1024];
void*
allocate(int sz)
{
if (!sz)
return 0;
if (sz == 1)
return ((void*)(8 * 1024 * 1024));
if (sz == 2)
return 0;
if (sz == 3)
return ((void*)(0xFFFFFFFF));
return &buf[sz];
}
int32_t
test(char* p, int32_t sz)
{
if (!sz)
return 0;
return p[0];
}

View File

@@ -1,171 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "bs58"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4"
dependencies = [
"tinyvec",
]
[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "codecov_tests"
version = "0.0.1"
dependencies = [
"xrpl-wasm-stdlib",
]
[[package]]
name = "cpufeatures"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "generic-array"
version = "0.14.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "libc"
version = "0.2.177"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
[[package]]
name = "proc-macro2"
version = "1.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
dependencies = [
"proc-macro2",
]
[[package]]
name = "sha2"
version = "0.10.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "syn"
version = "2.0.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tinyvec"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "typenum"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
[[package]]
name = "unicode-ident"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "xrpl-address-macro"
version = "0.7.1"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git#d27d3e0b4abf3c0215aade729d89053805efe48e"
dependencies = [
"bs58",
"quote",
"sha2",
"syn",
]
[[package]]
name = "xrpl-wasm-stdlib"
version = "0.7.1"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git#d27d3e0b4abf3c0215aade729d89053805efe48e"
dependencies = [
"xrpl-address-macro",
]

View File

@@ -1,18 +0,0 @@
[package]
edition = "2024"
name = "codecov_tests"
version = "0.0.1"
# This empty workspace definition keeps this project independent of the parent workspace
[workspace]
[lib]
crate-type = ["cdylib"]
[profile.release]
lto = true
opt-level = 's'
panic = "abort"
[dependencies]
xrpl-std = { git = "https://github.com/ripple/xrpl-wasm-stdlib.git", package = "xrpl-wasm-stdlib" }

View File

@@ -1,47 +0,0 @@
//TODO add docs after discussing the interface
//Note that Craft currently does not honor the rounding modes
#[allow(unused)]
pub const FLOAT_ROUNDING_MODES_TO_NEAREST: i32 = 0;
#[allow(unused)]
pub const FLOAT_ROUNDING_MODES_TOWARDS_ZERO: i32 = 1;
#[allow(unused)]
pub const FLOAT_ROUNDING_MODES_DOWNWARD: i32 = 2;
#[allow(unused)]
pub const FLOAT_ROUNDING_MODES_UPWARD: i32 = 3;
// pub enum RippledRoundingModes{
// ToNearest = 0,
// TowardsZero = 1,
// DOWNWARD = 2,
// UPWARD = 3
// }
#[allow(unused)]
#[link(wasm_import_module = "host_lib")]
unsafe extern "C" {
pub fn get_parent_ledger_hash(out_buff_ptr: i32, out_buff_len: i32) -> i32;
pub fn cache_ledger_obj(keylet_ptr: i32, keylet_len: i32, cache_num: i32) -> i32;
pub fn get_tx_nested_array_len(locator_ptr: i32, locator_len: i32) -> i32;
pub fn account_keylet(
account_ptr: i32,
account_len: i32,
out_buff_ptr: *mut u8,
out_buff_len: usize,
) -> i32;
pub fn line_keylet(
account1_ptr: *const u8,
account1_len: usize,
account2_ptr: *const u8,
account2_len: usize,
currency_ptr: i32,
currency_len: i32,
out_buff_ptr: *mut u8,
out_buff_len: usize,
) -> i32;
pub fn trace_num(msg_read_ptr: i32, msg_read_len: i32, number: i64) -> i32;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,134 +0,0 @@
import os
import sys
import subprocess
import re
OPT = "-Oz"
def update_fixture(project_name, wasm):
fixture_name = (
re.sub(r"_([a-z])", lambda m: m.group(1).upper(), project_name) + "WasmHex"
)
print(f"Updating fixture: {fixture_name}")
cpp_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "fixtures.cpp"))
h_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "fixtures.h"))
with open(cpp_path, "r", encoding="utf8") as f:
cpp_content = f.read()
pattern = rf'extern std::string const {fixture_name} =[ \n]+"[^;]*;'
if re.search(pattern, cpp_content, flags=re.MULTILINE):
updated_cpp_content = re.sub(
pattern,
f'extern std::string const {fixture_name} = "{wasm}";',
cpp_content,
flags=re.MULTILINE,
)
else:
with open(h_path, "r", encoding="utf8") as f:
h_content = f.read()
updated_h_content = (
h_content.rstrip() + f"\n\n extern std::string const {fixture_name};\n"
)
with open(h_path, "w", encoding="utf8") as f:
f.write(updated_h_content)
updated_cpp_content = (
cpp_content.rstrip()
+ f'\n\nextern std::string const {fixture_name} = "{wasm}";\n'
)
with open(cpp_path, "w", encoding="utf8") as f:
f.write(updated_cpp_content)
def process_rust(project_name):
project_path = os.path.abspath(
os.path.join(os.path.dirname(__file__), project_name)
)
wasm_location = f"target/wasm32v1-none/release/{project_name}.wasm"
build_cmd = (
f"(cd {project_path} "
f"&& cargo build --target wasm32v1-none --release "
f"&& wasm-opt {wasm_location} {OPT} -o {wasm_location}"
")"
)
try:
result = subprocess.run(
build_cmd, shell=True, check=True, capture_output=True, text=True
)
print(f"stdout: {result.stdout}")
if result.stderr:
print(f"stderr: {result.stderr}")
print(f"WASM file for {project_name} has been built and optimized.")
except subprocess.CalledProcessError as e:
print(f"exec error: {e}")
sys.exit(1)
src_path = os.path.abspath(
os.path.join(
os.path.dirname(__file__),
f"{project_name}/target/wasm32v1-none/release/{project_name}.wasm",
)
)
with open(src_path, "rb") as f:
data = f.read()
wasm = data.hex()
update_fixture(project_name, wasm)
def process_c(project_name):
project_path = os.path.abspath(
os.path.join(os.path.dirname(__file__), f"{project_name}.c")
)
wasm_path = os.path.abspath(
os.path.join(os.path.dirname(__file__), f"{project_name}.wasm")
)
build_cmd = (
f"$CC --sysroot=$SYSROOT "
f"-O3 -ffast-math --target=wasm32 -fno-exceptions -fno-threadsafe-statics -fvisibility=default -Wl,--export-all -Wl,--no-entry -Wl,--allow-undefined -DNDEBUG --no-standard-libraries -fno-builtin-memset "
f"-o {wasm_path} {project_path}"
f"&& wasm-opt {wasm_path} {OPT} -o {wasm_path}"
)
try:
result = subprocess.run(
build_cmd, shell=True, check=True, capture_output=True, text=True
)
print(f"stdout: {result.stdout}")
if result.stderr:
print(f"stderr: {result.stderr}")
print(
f"WASM file for {project_name} has been built with WASI support using clang."
)
except subprocess.CalledProcessError as e:
print(f"exec error: {e}")
sys.exit(1)
with open(wasm_path, "rb") as f:
data = f.read()
wasm = data.hex()
update_fixture(project_name, wasm)
if __name__ == "__main__":
if len(sys.argv) > 2:
print("Usage: python copyFixtures.py [<project_name>]")
sys.exit(1)
if len(sys.argv) == 2:
if os.path.isdir(os.path.join(os.path.dirname(__file__), sys.argv[1])):
process_rust(sys.argv[1])
else:
process_c(sys.argv[1])
print("Fixture has been processed.")
else:
dirs = [
d
for d in os.listdir(os.path.dirname(__file__))
if os.path.isdir(os.path.join(os.path.dirname(__file__), d))
]
c_files = [f for f in os.listdir(os.path.dirname(__file__)) if f.endswith(".c")]
for d in dirs:
process_rust(d)
for c in c_files:
process_c(c[:-2])
print("All fixtures have been processed.")

View File

@@ -1,34 +0,0 @@
(module
(type (;0;) (func))
(type (;1;) (func (result i32)))
(func (;0;) (type 0))
(func (;1;) (type 1) (result i32)
f32.const -2048
f32.const 2050
f32.sub
drop
i32.const 1)
(memory (;0;) 2)
(global (;0;) i32 (i32.const 1024))
(global (;1;) i32 (i32.const 1024))
(global (;2;) i32 (i32.const 2048))
(global (;3;) i32 (i32.const 2048))
(global (;4;) i32 (i32.const 67584))
(global (;5;) i32 (i32.const 1024))
(global (;6;) i32 (i32.const 67584))
(global (;7;) i32 (i32.const 131072))
(global (;8;) i32 (i32.const 0))
(global (;9;) i32 (i32.const 1))
(export "memory" (memory 0))
(export "__wasm_call_ctors" (func 0))
(export "finish" (func 1))
(export "buf" (global 0))
(export "__dso_handle" (global 1))
(export "__data_end" (global 2))
(export "__stack_low" (global 3))
(export "__stack_high" (global 4))
(export "__global_base" (global 5))
(export "__heap_base" (global 6))
(export "__heap_end" (global 7))
(export "__memory_base" (global 8))
(export "__table_base" (global 9)))

View File

@@ -1,12 +0,0 @@
// typedef long long mint;
typedef int mint;
mint
fib(mint n)
{
if (!n)
return 0;
if (n <= 2)
return 1;
return fib(n - 1) + fib(n - 2);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,143 +0,0 @@
#pragma once
// TODO: consider moving these to separate files (and figure out the build)
#include <cstdint>
#include <string>
#include <vector>
// WASM binary format constants and helpers for building test modules
namespace wasm_constants {
// Magic + version header
static constexpr uint8_t WASM_HEADER[] = {
0x00,
0x61,
0x73,
0x6d, // magic: \0asm
0x01,
0x00,
0x00,
0x00 // version: 1
};
// Type section: () -> ()
static constexpr uint8_t TYPE_EMPTY_FUNC[] = {0x01, 0x04, 0x01, 0x60, 0x00, 0x00};
// Function section: one function using type 0
static constexpr uint8_t FUNC_TYPE0[] = {0x03, 0x02, 0x01, 0x00};
// Export section: export func 0 as "finish"
static constexpr uint8_t EXPORT_FINISH[] = {0x07, 0x0a, 0x01, 0x06, 'f', 'i', 'n', 'i', 's', 'h', 0x00, 0x00};
// Empty function body: 0 locals, end
static constexpr uint8_t EMPTY_BODY[] = {0x00, 0x0b};
// Data segment offset: i32.const 0, end
static constexpr uint8_t DATA_OFFSET_ZERO[] = {0x41, 0x00, 0x0b};
// Section IDs
static constexpr uint8_t SECTION_MEMORY = 0x05;
static constexpr uint8_t SECTION_CODE = 0x0a;
static constexpr uint8_t SECTION_DATA = 0x0b;
// Instructions
static constexpr uint8_t INSTR_NOP = 0x01;
static constexpr uint8_t INSTR_END = 0x0b;
// Fill byte for data section bloat
static constexpr uint8_t DATA_FILL_BYTE = 0xEE;
// Generator for WASM module with large code section (many NOPs)
std::vector<uint8_t>
generateCodeBlob(uint32_t num_instructions);
// Generator for WASM module with large data section
std::vector<uint8_t>
generateDataBlob(uint32_t data_size);
} // namespace wasm_constants
extern std::string const ledgerSqnWasmHex;
extern std::string const allHostFunctionsWasmHex;
extern std::string const deepRecursionHex;
extern std::string const fibWasmHex;
extern std::string const b58WasmHex;
extern std::string const sha512PureWasmHex;
extern std::string const hfPerfTest;
extern std::string const allKeyletsWasmHex;
extern std::string const codecovTestsWasmHex;
extern std::string const floatTestsWasmHex;
extern std::string const float0Hex;
extern std::string const disabledFloatHex;
extern std::string const memoryPointerAtLimitHex;
extern std::string const memoryPointerOverLimitHex;
extern std::string const memoryOffsetOverLimitHex;
extern std::string const memoryEndOfWordOverLimitHex;
extern std::string const memoryGrow0To1PageHex;
extern std::string const memoryGrow1To0PageHex;
extern std::string const memoryLastByteOf8MBHex;
extern std::string const memoryGrow1MoreThan8MBHex;
extern std::string const memoryGrow0MoreThan8MBHex;
extern std::string const memoryInit1MoreThan8MBHex;
extern std::string const memoryNegativeAddressHex;
extern std::string const table64ElementsHex;
extern std::string const table65ElementsHex;
extern std::string const table2TablesHex;
extern std::string const table0ElementsHex;
extern std::string const tableUintMaxHex;
extern std::string const proposalMutableGlobalHex;
extern std::string const proposalGcStructNewHex;
extern std::string const proposalMultiValueHex;
extern std::string const proposalSignExtHex;
extern std::string const proposalFloatToIntHex;
extern std::string const proposalBulkMemoryHex;
extern std::string const proposalRefTypesHex;
extern std::string const proposalTailCallHex;
extern std::string const proposalExtendedConstHex;
extern std::string const proposalMultiMemoryHex;
extern std::string const proposalCustomPageSizesHex;
extern std::string const proposalMemory64Hex;
extern std::string const proposalWideArithmeticHex;
extern std::string const trapDivideBy0Hex;
extern std::string const trapIntOverflowHex;
extern std::string const trapUnreachableHex;
extern std::string const trapNullCallHex;
extern std::string const trapFuncSigMismatchHex;
extern std::string const wasiGetTimeHex;
extern std::string const wasiPrintHex;
extern std::string const badMagicNumberHex;
extern std::string const badVersionNumberHex;
extern std::string const lyingHeaderHex;
extern std::string const neverEndingNumberHex;
extern std::string const vectorLieHex;
extern std::string const sectionOrderingHex;
extern std::string const ghostPayloadHex;
extern std::string const junkAfterSectionHex;
extern std::string const invalidSectionIdHex;
extern std::string const localVariableBombHex;
extern std::string const infiniteLoopWasmHex;
extern std::string const startLoopHex;
extern std::string const badAllocHex;
extern std::string const badAlignHex;
extern std::string const updateDataWasmHex;

View File

@@ -1,171 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "bs58"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4"
dependencies = [
"tinyvec",
]
[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "cpufeatures"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "float_tests"
version = "0.0.1"
dependencies = [
"xrpl-wasm-stdlib",
]
[[package]]
name = "generic-array"
version = "0.14.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "libc"
version = "0.2.177"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
[[package]]
name = "proc-macro2"
version = "1.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
dependencies = [
"proc-macro2",
]
[[package]]
name = "sha2"
version = "0.10.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "syn"
version = "2.0.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tinyvec"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "typenum"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
[[package]]
name = "unicode-ident"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "xrpl-address-macro"
version = "0.7.1"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git#d27d3e0b4abf3c0215aade729d89053805efe48e"
dependencies = [
"bs58",
"quote",
"sha2",
"syn",
]
[[package]]
name = "xrpl-wasm-stdlib"
version = "0.7.1"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git#d27d3e0b4abf3c0215aade729d89053805efe48e"
dependencies = [
"xrpl-address-macro",
]

View File

@@ -1,21 +0,0 @@
[package]
name = "float_tests"
version = "0.0.1"
edition = "2024"
# This empty workspace definition keeps this project independent of the parent workspace
[workspace]
[lib]
crate-type = ["cdylib"]
[profile.release]
lto = true
opt-level = 's'
panic = "abort"
[dependencies]
xrpl-std = { git = "https://github.com/ripple/xrpl-wasm-stdlib.git", package = "xrpl-wasm-stdlib" }
[profile.dev]
panic = "abort"

View File

@@ -1,461 +0,0 @@
#![allow(unused_imports)]
#![allow(unused_variables)]
#![cfg_attr(target_arch = "wasm32", no_std)]
#[cfg(not(target_arch = "wasm32"))]
extern crate std;
use xrpl_std::core::locator::Locator;
use xrpl_std::core::types::opaque_float::{FLOAT_NEGATIVE_ONE, FLOAT_ONE};
use xrpl_std::decode_hex_32;
use xrpl_std::host::trace::DataRepr::AsHex;
use xrpl_std::host::trace::{trace, trace_data, trace_float, trace_num, DataRepr};
use xrpl_std::host::{
cache_ledger_obj, float_add, float_compare, float_divide, float_from_int, float_from_uint,
float_log, float_multiply, float_pow, float_root, float_set, float_subtract,
get_ledger_obj_array_len, get_ledger_obj_field, get_ledger_obj_nested_field,
trace_opaque_float, FLOAT_ROUNDING_MODES_TO_NEAREST,
};
use xrpl_std::sfield;
use xrpl_std::sfield::{
Account, AccountTxnID, Balance, Domain, EmailHash, Flags, LedgerEntryType, MessageKey,
OwnerCount, PreviousTxnID, PreviousTxnLgrSeq, RegularKey, Sequence, TicketCount, TransferRate,
};
fn test_float_from_wasm() {
let _ = trace("\n$$$ test_float_from_wasm $$$");
let mut f: [u8; 8] = [0u8; 8];
if 8 == unsafe { float_from_int(12300, f.as_mut_ptr(), 8, FLOAT_ROUNDING_MODES_TO_NEAREST) } {
let _ = trace_float(" float from i64 12300:", &f);
let _ = trace_data(" float from i64 12300 as HEX:", &f, AsHex);
} else {
let _ = trace(" float from i64 12300: failed");
}
let u64_value: u64 = 12300;
if 8 == unsafe {
float_from_uint(
&u64_value as *const u64 as *const u8,
8,
f.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
} {
let _ = trace_float(" float from u64 12300:", &f);
} else {
let _ = trace(" float from u64 12300: failed");
}
if 8 == unsafe { float_set(2, 123, f.as_mut_ptr(), 8, FLOAT_ROUNDING_MODES_TO_NEAREST) } {
let _ = trace_float(" float from exp 2, mantissa 123:", &f);
} else {
let _ = trace(" float from exp 2, mantissa 3: failed");
}
let _ = trace_float(" float from const 1:", &FLOAT_ONE);
let _ = trace_float(" float from const -1:", &FLOAT_NEGATIVE_ONE);
}
fn test_float_compare() {
let _ = trace("\n$$$ test_float_compare $$$");
let mut f1: [u8; 8] = [0u8; 8];
if 8 != unsafe { float_from_int(1, f1.as_mut_ptr(), 8, FLOAT_ROUNDING_MODES_TO_NEAREST) } {
let _ = trace(" float from 1: failed");
} else {
let _ = trace_float(" float from 1:", &f1);
}
if 0 == unsafe { float_compare(f1.as_ptr(), 8, FLOAT_ONE.as_ptr(), 8) } {
let _ = trace(" float from 1 == FLOAT_ONE");
} else {
let _ = trace(" float from 1 != FLOAT_ONE");
}
if 1 == unsafe { float_compare(f1.as_ptr(), 8, FLOAT_NEGATIVE_ONE.as_ptr(), 8) } {
let _ = trace(" float from 1 > FLOAT_NEGATIVE_ONE");
} else {
let _ = trace(" float from 1 !> FLOAT_NEGATIVE_ONE");
}
if 2 == unsafe { float_compare(FLOAT_NEGATIVE_ONE.as_ptr(), 8, f1.as_ptr(), 8) } {
let _ = trace(" FLOAT_NEGATIVE_ONE < float from 1");
} else {
let _ = trace(" FLOAT_NEGATIVE_ONE !< float from 1");
}
}
fn test_float_add_subtract() {
let _ = trace("\n$$$ test_float_add_subtract $$$");
let mut f_compute: [u8; 8] = FLOAT_ONE;
for i in 0..9 {
unsafe {
float_add(
f_compute.as_ptr(),
8,
FLOAT_ONE.as_ptr(),
8,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
// let _ = trace_float(" float:", &f_compute);
}
let mut f10: [u8; 8] = [0u8; 8];
if 8 != unsafe { float_from_int(10, f10.as_mut_ptr(), 8, FLOAT_ROUNDING_MODES_TO_NEAREST) } {
// let _ = trace(" float from 10: failed");
}
if 0 == unsafe { float_compare(f10.as_ptr(), 8, f_compute.as_ptr(), 8) } {
let _ = trace(" repeated add: good");
} else {
let _ = trace(" repeated add: bad");
}
for i in 0..11 {
unsafe {
float_subtract(
f_compute.as_ptr(),
8,
FLOAT_ONE.as_ptr(),
8,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
}
if 0 == unsafe { float_compare(f_compute.as_ptr(), 8, FLOAT_NEGATIVE_ONE.as_ptr(), 8) } {
let _ = trace(" repeated subtract: good");
} else {
let _ = trace(" repeated subtract: bad");
}
}
fn test_float_multiply_divide() {
let _ = trace("\n$$$ test_float_multiply_divide $$$");
let mut f10: [u8; 8] = [0u8; 8];
unsafe { float_from_int(10, f10.as_mut_ptr(), 8, FLOAT_ROUNDING_MODES_TO_NEAREST) };
let mut f_compute: [u8; 8] = FLOAT_ONE;
for i in 0..6 {
unsafe {
float_multiply(
f_compute.as_ptr(),
8,
f10.as_ptr(),
8,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
// let _ = trace_float(" float:", &f_compute);
}
let mut f1000000: [u8; 8] = [0u8; 8];
unsafe {
float_from_int(
1000000,
f1000000.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
if 0 == unsafe { float_compare(f1000000.as_ptr(), 8, f_compute.as_ptr(), 8) } {
let _ = trace(" repeated multiply: good");
} else {
let _ = trace(" repeated multiply: bad");
}
for i in 0..7 {
unsafe {
float_divide(
f_compute.as_ptr(),
8,
f10.as_ptr(),
8,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
}
let mut f01: [u8; 8] = [0u8; 8];
unsafe { float_set(-1, 1, f01.as_mut_ptr(), 8, FLOAT_ROUNDING_MODES_TO_NEAREST) };
if 0 == unsafe { float_compare(f_compute.as_ptr(), 8, f01.as_ptr(), 8) } {
let _ = trace(" repeated divide: good");
} else {
let _ = trace(" repeated divide: bad");
}
}
fn test_float_pow() {
let _ = trace("\n$$$ test_float_pow $$$");
let mut f_compute: [u8; 8] = [0u8; 8];
unsafe {
float_pow(
FLOAT_ONE.as_ptr(),
8,
3,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float cube of 1:", &f_compute);
unsafe {
float_pow(
FLOAT_NEGATIVE_ONE.as_ptr(),
8,
6,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float 6th power of -1:", &f_compute);
let mut f9: [u8; 8] = [0u8; 8];
unsafe { float_from_int(9, f9.as_mut_ptr(), 8, FLOAT_ROUNDING_MODES_TO_NEAREST) };
unsafe {
float_pow(
f9.as_ptr(),
8,
2,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float square of 9:", &f_compute);
unsafe {
float_pow(
f9.as_ptr(),
8,
0,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float 0th power of 9:", &f_compute);
let mut f0: [u8; 8] = [0u8; 8];
unsafe { float_from_int(0, f0.as_mut_ptr(), 8, FLOAT_ROUNDING_MODES_TO_NEAREST) };
unsafe {
float_pow(
f0.as_ptr(),
8,
2,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float square of 0:", &f_compute);
let r = unsafe {
float_pow(
f0.as_ptr(),
8,
0,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_num(
" float 0th power of 0 (expecting INVALID_PARAMS error):",
r as i64,
);
}
fn test_float_root() {
let _ = trace("\n$$$ test_float_root $$$");
let mut f9: [u8; 8] = [0u8; 8];
unsafe { float_from_int(9, f9.as_mut_ptr(), 8, FLOAT_ROUNDING_MODES_TO_NEAREST) };
let mut f_compute: [u8; 8] = [0u8; 8];
unsafe {
float_root(
f9.as_ptr(),
8,
2,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float sqrt of 9:", &f_compute);
unsafe {
float_root(
f9.as_ptr(),
8,
3,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float cbrt of 9:", &f_compute);
let mut f1000000: [u8; 8] = [0u8; 8];
unsafe {
float_from_int(
1000000,
f1000000.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
unsafe {
float_root(
f1000000.as_ptr(),
8,
3,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float cbrt of 1000000:", &f_compute);
unsafe {
float_root(
f1000000.as_ptr(),
8,
6,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float 6th root of 1000000:", &f_compute);
}
fn test_float_log() {
let _ = trace("\n$$$ test_float_log $$$");
let mut f1000000: [u8; 8] = [0u8; 8];
unsafe {
float_from_int(
1000000,
f1000000.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let mut f_compute: [u8; 8] = [0u8; 8];
unsafe {
float_log(
f1000000.as_ptr(),
8,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" log_10 of 1000000:", &f_compute);
}
fn test_float_negate() {
let _ = trace("\n$$$ test_float_negate $$$");
let mut f_compute: [u8; 8] = [0u8; 8];
unsafe {
float_multiply(
FLOAT_ONE.as_ptr(),
8,
FLOAT_NEGATIVE_ONE.as_ptr(),
8,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
// let _ = trace_float(" float:", &f_compute);
if 0 == unsafe { float_compare(FLOAT_NEGATIVE_ONE.as_ptr(), 8, f_compute.as_ptr(), 8) } {
let _ = trace(" negate const 1: good");
} else {
let _ = trace(" negate const 1: bad");
}
unsafe {
float_multiply(
FLOAT_NEGATIVE_ONE.as_ptr(),
8,
FLOAT_NEGATIVE_ONE.as_ptr(),
8,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
// let _ = trace_float(" float:", &f_compute);
if 0 == unsafe { float_compare(FLOAT_ONE.as_ptr(), 8, f_compute.as_ptr(), 8) } {
let _ = trace(" negate const -1: good");
} else {
let _ = trace(" negate const -1: bad");
}
}
fn test_float_invert() {
let _ = trace("\n$$$ test_float_invert $$$");
let mut f_compute: [u8; 8] = [0u8; 8];
let mut f10: [u8; 8] = [0u8; 8];
unsafe { float_from_int(10, f10.as_mut_ptr(), 8, FLOAT_ROUNDING_MODES_TO_NEAREST) };
unsafe {
float_divide(
FLOAT_ONE.as_ptr(),
8,
f10.as_ptr(),
8,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" invert a float from 10:", &f_compute);
unsafe {
float_divide(
FLOAT_ONE.as_ptr(),
8,
f_compute.as_ptr(),
8,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" invert again:", &f_compute);
// if f10's value is 7, then invert twice won't match the original value
if 0 == unsafe { float_compare(f10.as_ptr(), 8, f_compute.as_ptr(), 8) } {
let _ = trace(" invert twice: good");
} else {
let _ = trace(" invert twice: bad");
}
}
#[unsafe(no_mangle)]
pub extern "C" fn finish() -> i32 {
test_float_from_wasm();
test_float_compare();
test_float_add_subtract();
test_float_multiply_divide();
test_float_pow();
test_float_root();
test_float_log();
test_float_negate();
test_float_invert();
1
}

View File

@@ -1,8 +0,0 @@
int
loop()
{
int volatile x = 0;
while (1)
x++;
return x;
}

View File

@@ -1,27 +0,0 @@
#include <stdint.h>
int32_t
get_ledger_sqn();
// int32_t trace(uint8_t const*, int32_t, uint8_t const*, int32_t, int32_t);
// int32_t trace_num(uint8_t const*, int32_t, int64_t);
// uint8_t buf[1024];
// char const test_res[] = "sqn: ";
// char const test_name[] = "TEST get_ledger_sqn";
int
finish()
{
// trace((uint8_t const *)test_name, sizeof(test_name) - 1, 0, 0, 0);
// memset(buf, 0, sizeof(buf));
// for(int i = 0; i < sizeof(buf); ++i) buf[i] = 0;
int x = get_ledger_sqn();
// if (x >= 0)
// x = *((int32_t*)buf);
// trace_num((uint8_t const *)test`_res, sizeof(test_res) - 1, x);
return x < 0 ? x : (x >= 5 ? x : 0);
}

View File

@@ -1,133 +0,0 @@
#include <stdint.h>
#include <stdlib.h>
static uint64_t const K512[] = {
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538,
0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe,
0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 0x983e5152ee66dfab,
0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed,
0x53380d139d95b3df, 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 0x19a4c116b8d2d0c8, 0x1e376c085141ab53,
0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373,
0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 0xca273eceea26619c,
0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 0x0a637dc5a2c898a6,
0x113f9804bef90dae, 0x1b710b35131c471b, 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817};
#define ROTATE(x, y) (((x) >> (y)) | ((x) << (64 - (y))))
#define Sigma0(x) (ROTATE((x), 28) ^ ROTATE((x), 34) ^ ROTATE((x), 39))
#define Sigma1(x) (ROTATE((x), 14) ^ ROTATE((x), 18) ^ ROTATE((x), 41))
#define sigma0(x) (ROTATE((x), 1) ^ ROTATE((x), 8) ^ ((x) >> 7))
#define sigma1(x) (ROTATE((x), 19) ^ ROTATE((x), 61) ^ ((x) >> 6))
#define Ch(x, y, z) (((x) & (y)) ^ ((~(x)) & (z)))
#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
static inline uint64_t
B2U64(uint8_t val, uint8_t sh)
{
return ((uint64_t)val) << sh;
}
void*
allocate(int sz)
{
return malloc(sz);
}
void
deallocate(void* p)
{
free(p);
}
uint8_t e_data[32 * 1024];
uint8_t*
sha512_process(uint8_t const* data, int32_t length)
{
static uint64_t state[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint64_t a, b, c, d, e, f, g, h, s0, s1, T1, T2;
uint64_t X[16];
uint64_t blocks = length / 128;
while (blocks--)
{
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
f = state[5];
g = state[6];
h = state[7];
unsigned i;
for (i = 0; i < 16; i++)
{
X[i] = B2U64(data[0], 56) | B2U64(data[1], 48) | B2U64(data[2], 40) | B2U64(data[3], 32) |
B2U64(data[4], 24) | B2U64(data[5], 16) | B2U64(data[6], 8) | B2U64(data[7], 0);
data += 8;
T1 = h;
T1 += Sigma1(e);
T1 += Ch(e, f, g);
T1 += K512[i];
T1 += X[i];
T2 = Sigma0(a);
T2 += Maj(a, b, c);
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = T1 + T2;
}
for (i = 16; i < 80; i++)
{
s0 = X[(i + 1) & 0x0f];
s0 = sigma0(s0);
s1 = X[(i + 14) & 0x0f];
s1 = sigma1(s1);
T1 = X[i & 0xf] += s0 + s1 + X[(i + 9) & 0xf];
T1 += h + Sigma1(e) + Ch(e, f, g) + K512[i];
T2 = Sigma0(a) + Maj(a, b, c);
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = T1 + T2;
}
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
state[5] += f;
state[6] += g;
state[7] += h;
}
return (uint8_t*)(state);
}
// int main ()
//{
// return 0;
// }

View File

@@ -1,13 +0,0 @@
#include <stdint.h>
int32_t
update_data(uint8_t const*, int32_t);
int
finish()
{
uint8_t buf[] = "Data";
update_data(buf, sizeof(buf) - 1);
return -256;
}

View File

@@ -1,13 +0,0 @@
(module
;; Define a memory with 1 initial page.
;; CRITICAL: We explicitly set the page size to 1 kilobyte.
;; Standard Wasm implies (pagesize 65536).
(memory 1 (pagesize 1024))
(func $finish (result i32)
;; If this module instantiates, the runtime accepted the custom page size.
i32.const 1
)
(export "finish" (func $finish))
)

View File

@@ -1,29 +0,0 @@
(module
;; Define a Mutable Global Variable to act as our counter.
;; We initialize it to 1,000,000.
(global $counter (mut i32) (i32.const 1000000))
(func $finish (result i32)
;; 1. Check if counter == 0 (Base Case)
global.get $counter
i32.eqz
if
;; If counter is 0, we are done. Return 1.
i32.const 1
return
end
;; 2. Decrement the Global Counter
global.get $counter
i32.const 1
i32.sub
global.set $counter
;; 3. Recursive Step: Call SELF
;; This puts an i32 (1) on the stack when it returns.
call $finish
)
;; Export the only function we have
(export "finish" (func $finish))
)

View File

@@ -1,21 +0,0 @@
(module
;; Define a 64-bit memory (index type i64)
;; Start with 1 page.
(memory i64 1)
(func $finish (result i32)
;; 1. Perform a store using a 64-bit address.
;; Even if the value is small (0), the type MUST be i64.
i64.const 0 ;; Address (64-bit)
i32.const 42 ;; Value (32-bit)
i32.store8 ;; Opcode doesn't change, but validation rules do.
;; 2. check memory size
;; memory.size now returns an i64.
memory.size
i64.const 1
i64.eq ;; Returns i32 (1 if true)
)
(export "finish" (func $finish))
)

View File

@@ -1,28 +0,0 @@
(module
;; 1. Define Memory: 1 Page = 64KB = 65,536 bytes
(memory 1)
;; Export memory so the host can inspect it if needed
(export "memory" (memory 0))
(func $test_straddle (result i32)
;; Push the address onto the stack.
;; 65534 is valid, but it is only 2 bytes away from the end.
i32.const 65534
;; Attempt to load an i32 (4 bytes) from that address.
;; This requires bytes 65534, 65535, 65536, and 65537.
;; Since 65536 is the first invalid byte, this MUST trap.
i32.load
;; Clean up the stack.
;; The load pushed a value, but we don't care what it is.
drop
;; Return 1 to signal "I survived the memory access"
i32.const 1
)
;; Export the function so you can call it from your host (JS, Python, etc.)
(export "finish" (func $test_straddle))
)

View File

@@ -1,29 +0,0 @@
(module
;; Start at your limit: 128 pages (8MB)
(memory 128)
(export "memory" (memory 0))
(func $try_grow_beyond_limit (result i32)
;; Attempt to grow by 0 page
i32.const 0
memory.grow
;; memory.grow returns:
;; -1 if the growth failed (Correct behavior for your limit)
;; 128 (old size) if growth succeeded (Means limit was bypassed)
;; Check if result == -1
i32.const -1
i32.eq
if
;; Growth FAILED (Host blocked it). Return -1.
i32.const -1
return
end
;; Growth SUCCEEDED (Host allowed it). Return 1.
i32.const 1
)
(export "finish" (func $try_grow_beyond_limit))
)

View File

@@ -1,26 +0,0 @@
(module
;; 1. Define Memory: Start with 0 pages
(memory 0)
;; Export memory to host
(export "memory" (memory 0))
(func $grow_from_zero (result i32)
;; We have 0 pages. We want to add 1 page.
;; Push delta (1) onto stack.
i32.const 1
;; Grow the memory.
;; If successful: memory becomes 64KB, returns old size (0).
;; If failed: memory stays 0, returns -1.
memory.grow
;; Drop the return value of memory.grow
drop
;; Return 1 (as requested)
i32.const 1
)
(export "finish" (func $grow_from_zero))
)

View File

@@ -1,29 +0,0 @@
(module
;; Start at your limit: 128 pages (8MB)
(memory 128)
(export "memory" (memory 0))
(func $try_grow_beyond_limit (result i32)
;; Attempt to grow by 1 page
i32.const 1
memory.grow
;; memory.grow returns:
;; -1 if the growth failed (Correct behavior for your limit)
;; 128 (old size) if growth succeeded (Means limit was bypassed)
;; Check if result == -1
i32.const -1
i32.eq
if
;; Growth FAILED (Host blocked it). Return -1.
i32.const -1
return
end
;; Growth SUCCEEDED (Host allowed it). Return 1.
i32.const 1
)
(export "finish" (func $try_grow_beyond_limit))
)

View File

@@ -1,33 +0,0 @@
(module
;; 1. Define Memory: Start with 1 page (64KB)
(memory 1)
;; Export memory to host
(export "memory" (memory 0))
(func $grow_negative (result i32)
;; The user pushed -1. In Wasm, this is interpreted as unsigned MAX_UINT32.
;; This is requesting to add 4,294,967,295 pages (approx 256 TB).
;; A secure runtime MUST fail this request (return -1) without crashing.
i32.const -1
;; Grow the memory.
;; Returns: old_size if success, -1 if failure.
memory.grow
;; Check if result == -1 (Failure)
i32.const -1
i32.eq
if
;; If memory.grow returned -1, we return -1 to signal "Correctly failed".
i32.const -1
return
end
;; If we are here, memory.grow somehow SUCCEEDED (Vulnerability).
;; We return 1 to signal "Unexpected Success".
i32.const 1
)
(export "finish" (func $grow_negative))
)

View File

@@ -1,27 +0,0 @@
(module
;; Define memory: 129 pages (> 8MB limit) min, 129 pages max
(memory 129 129)
;; Export memory so host can verify size
(export "memory" (memory 0))
;; access last byte of 8MB limit
(func $access_last_byte (result i32)
;; Math: 128 pages * 64,536 bytes/page = 8,388,608 bytes
;; Valid indices: 0 to 8,388,607
;; Push the address of the LAST valid byte
i32.const 8388607
;; Load byte from that address
i32.load8_u
;; Drop the value (we don't care what it is, just that we could read it)
drop
;; Return 1 to indicate success
i32.const 1
)
(export "finish" (func $access_last_byte))
)

View File

@@ -1,26 +0,0 @@
(module
;; Define memory: 128 pages (8MB) min, 128 pages max
(memory 128 128)
;; Export memory so host can verify size
(export "memory" (memory 0))
(func $access_last_byte (result i32)
;; Math: 128 pages * 64,536 bytes/page = 8,388,608 bytes
;; Valid indices: 0 to 8,388,607
;; Push the address of the LAST valid byte
i32.const 8388607
;; Load byte from that address
i32.load8_u
;; Drop the value (we don't care what it is, just that we could read it)
drop
;; Return 1 to indicate success
i32.const 1
)
(export "finish" (func $access_last_byte))
)

View File

@@ -1,23 +0,0 @@
(module
;; Define memory: 128 pages (8MB) min, 128 pages max
(memory 128 128)
;; Export memory so host can verify size
(export "memory" (memory 0))
(func $access_last_byte (result i32)
;; Push a negative address
i32.const -1
;; Load byte from that address
i32.load8_u
;; Drop the value
drop
;; Return 1 to indicate success
i32.const 1
)
(export "finish" (func $access_last_byte))
)

View File

@@ -1,27 +0,0 @@
(module
;; 1. Define Memory: 1 Page = 64KB
(memory 1)
(export "memory" (memory 0))
(func $test_offset_overflow (result i32)
;; 1. Push the base address onto the stack.
;; We use '0', which is the safest, most valid address possible.
i32.const 0
;; 2. Attempt to load using a static offset.
;; syntax: i32.load offset=N align=N
;; We set the offset to 65536 (the size of the memory).
;; The effective address becomes 0 + 65536 = 65536.
i32.load offset=65536
;; Clean up the stack.
;; The load pushed a value, but we don't care what it is.
drop
;; Return 1 to signal "I survived the memory access"
i32.const 1
)
(export "finish" (func $test_offset_overflow))
)

View File

@@ -1,22 +0,0 @@
(module
;; Define 1 page of memory (64KB = 65,536 bytes)
(memory 1)
(func $read_edge (result i32)
;; Push the index of the LAST valid byte
i32.const 65535
;; Load 1 byte (unsigned)
i32.load8_u
;; Clean up the stack.
;; The load pushed a value, but we don't care what it is.
drop
;; Return 1 to signal "I survived the memory access"
i32.const 1
)
;; Export as "finish" as requested
(export "finish" (func $read_edge))
)

View File

@@ -1,23 +0,0 @@
(module
;; Define 1 page of memory (64KB = 65,536 bytes)
(memory 1)
(func $read_overflow (result i32)
;; Push the index of the FIRST invalid byte
;; Memory is 0..65535, so 65536 is out of bounds.
i32.const 65536
;; Load 1 byte (unsigned)
i32.load8_u
;; Clean up the stack.
;; The load pushed a value, but we don't care what it is.
drop
;; Return 1 to signal "I survived the memory access"
i32.const 1
)
;; Export as "finish" as requested
(export "finish" (func $read_overflow))
)

View File

@@ -1,16 +0,0 @@
(module
;; Memory 0: Index 0 (Empty)
(memory 0)
;; Memory 1: Index 1 (Size 1 page)
;; If multi-memory is disabled, this line causes a validation error (max 1 memory).
(memory 1)
(func $finish (result i32)
;; Query size of Memory Index 1.
;; Should return 1 (success).
memory.size 1
)
(export "finish" (func $finish))
)

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