mirror of
https://github.com/Xahau/xahaud.git
synced 2026-08-26 01:30:52 +00:00
Compare commits
63 Commits
sync-3.0.0
...
jshookz
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7694602d10 | ||
|
|
f3e9d2b6a7 | ||
|
|
ff7de7207a | ||
|
|
1b3722c012 | ||
|
|
e2f87c0b03 | ||
|
|
6d6f011b5b | ||
|
|
8e7a7f48f9 | ||
|
|
07962562f6 | ||
|
|
50615166b1 | ||
|
|
f14e9236d2 | ||
|
|
2b493ed881 | ||
|
|
b9d0434e96 | ||
|
|
3d5844e0ed | ||
|
|
ad85d170c6 | ||
|
|
32baf652ee | ||
|
|
7bf8cd75e5 | ||
|
|
e910177838 | ||
|
|
d1cd4b22f0 | ||
|
|
277bad787d | ||
|
|
dce17e2fa6 | ||
|
|
e6403f1596 | ||
|
|
ee0b677c2e | ||
|
|
a4a43578de | ||
|
|
b6b57e3ec3 | ||
|
|
41400f1cc6 | ||
|
|
77a1c2d65d | ||
|
|
e4f4b28e0f | ||
|
|
9870e5df67 | ||
|
|
dfc2a8ed83 | ||
|
|
9de7ba734d | ||
|
|
359c3e7990 | ||
|
|
650b2d6e1c | ||
|
|
94c61cc626 | ||
|
|
b7881302e3 | ||
|
|
4e87ccd924 | ||
|
|
df86bebd5f | ||
|
|
670e77d4c0 | ||
|
|
ba54d7fd77 | ||
|
|
78929910ee | ||
|
|
3436c241e2 | ||
|
|
398f6f01d7 | ||
|
|
aeea7a8251 | ||
|
|
33510213d3 | ||
|
|
bb136e616a | ||
|
|
e4ccc443c1 | ||
|
|
0b38795617 | ||
|
|
f3ed814dcf | ||
|
|
7c66f94a90 | ||
|
|
240f33d398 | ||
|
|
a868a46848 | ||
|
|
b86112bca4 | ||
|
|
92832aac10 | ||
|
|
8e7def3739 | ||
|
|
552d1cf1e0 | ||
|
|
f35d8591d8 | ||
|
|
124235d92e | ||
|
|
56a456a7ff | ||
|
|
70814197f5 | ||
|
|
d5334234fc | ||
|
|
d406e336a4 | ||
|
|
4c58f4223c | ||
|
|
2d48d21cc6 | ||
|
|
7dd63aaac9 |
@@ -1,21 +1,5 @@
|
||||
---
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterClass: true
|
||||
AfterControlStatement: true
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
IndentBraces: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MaxEmptyLinesToKeep: 1
|
||||
---
|
||||
Language: Cpp
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
AlignConsecutiveAssignments: false
|
||||
@@ -34,41 +18,51 @@ AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BraceWrapping:
|
||||
AfterClass: true
|
||||
AfterControlStatement: true
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
IndentBraces: false
|
||||
BreakBeforeBinaryOperators: false
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: true
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: "^ IWYU pragma:"
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
ForEachMacros: [Q_FOREACH, BOOST_FOREACH]
|
||||
IncludeBlocks: Regroup
|
||||
ForEachMacros: [ Q_FOREACH, BOOST_FOREACH ]
|
||||
IncludeCategories:
|
||||
- Regex: "^<(test)/"
|
||||
Priority: 0
|
||||
- Regex: "^<(xrpld)/"
|
||||
Priority: 1
|
||||
- Regex: "^<(xrpl)/"
|
||||
Priority: 2
|
||||
- Regex: "^<(boost)/"
|
||||
Priority: 3
|
||||
- Regex: "^.*/"
|
||||
Priority: 4
|
||||
- Regex: '^.*\.h'
|
||||
Priority: 5
|
||||
- Regex: ".*"
|
||||
Priority: 6
|
||||
IncludeIsMainRegex: "$"
|
||||
- Regex: '^<(test)/'
|
||||
Priority: 0
|
||||
- Regex: '^<(xrpld)/'
|
||||
Priority: 1
|
||||
- Regex: '^<(xrpl)/'
|
||||
Priority: 2
|
||||
- Regex: '^<(boost)/'
|
||||
Priority: 3
|
||||
- Regex: '.*'
|
||||
Priority: 4
|
||||
IncludeIsMainRegex: '$'
|
||||
IndentCaseLabels: true
|
||||
IndentFunctionDeclarationAfterType: false
|
||||
IndentRequiresClause: true
|
||||
IndentWidth: 4
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: false
|
||||
@@ -79,25 +73,19 @@ PenaltyBreakString: 1000
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
ReflowComments: true
|
||||
RequiresClausePosition: OwnLine
|
||||
SortIncludes: true
|
||||
SortIncludes: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: false
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
QualifierAlignment: Right
|
||||
---
|
||||
Language: Proto
|
||||
BasedOnStyle: Google
|
||||
ColumnLimit: 0
|
||||
IndentWidth: 2
|
||||
Standard: Cpp11
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
codecov:
|
||||
require_ci_to_pass: true
|
||||
# This integration branch uploads the normal suite and JSHookz E2E coverage.
|
||||
notify:
|
||||
after_n_builds: 2
|
||||
|
||||
comment:
|
||||
behavior: default
|
||||
@@ -27,12 +30,11 @@ github_checks:
|
||||
parsers:
|
||||
cobertura:
|
||||
partials_as_hits: true
|
||||
handle_missing_conditions: true
|
||||
handle_missing_conditions : true
|
||||
|
||||
slack_app: false
|
||||
|
||||
ignore:
|
||||
- "src/test/"
|
||||
- "src/tests/"
|
||||
- "include/xrpl/beast/test/"
|
||||
- "include/xrpl/beast/unit_test/"
|
||||
|
||||
@@ -23,9 +23,3 @@ e61880699997398f5a746e6c4034edc7632661f5
|
||||
d25b5dcd568bb96c18e347d55fac10fe901a1bfb
|
||||
# Reformat code with clang-format-18
|
||||
02749feea88ce61c1f7eeb2d61a57d8ecf07ab11
|
||||
# chore: Run prettier on all files (#5657) (rippled)
|
||||
97f0747e103f13e26e45b731731059b32f7679ac
|
||||
# chore: Reverts formatting changes to external files, adds formatting changes to proto files (#5711) (rippled)
|
||||
b13370ac0d207217354f1fc1c29aef87769fb8a1
|
||||
# chore: Fix file formatting (#5718) (rippled)
|
||||
896b8c3b54a22b0497cb0d1ce95e1095f9a227ce
|
||||
|
||||
6
.gitattributes
vendored
6
.gitattributes
vendored
@@ -11,3 +11,9 @@ LICENSE binary
|
||||
*.vcxproj text eol=crlf
|
||||
*.props text eol=crlf
|
||||
*.filters text eol=crlf
|
||||
|
||||
# JSHookz projections checked for freshness by the integration workflow.
|
||||
external/quickjs-provider/jshookz_provider.manifest.cmake linguist-generated=true
|
||||
external/quickjs-provider/jshookz_provider.manifest.json linguist-generated=true
|
||||
external/quickjs-provider/jshookz_provider.native-abi.json linguist-generated=true
|
||||
src/test/app/JSHooks_test_hooks.h linguist-generated=true
|
||||
|
||||
13
.github/ISSUE_TEMPLATE/bug_report.md
vendored
13
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -2,35 +2,30 @@
|
||||
name: Bug Report
|
||||
about: Create a report to help us improve rippled
|
||||
title: "[Title with short description] (Version: [rippled version])"
|
||||
labels: ""
|
||||
assignees: ""
|
||||
---
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
<!-- Please search existing issues to avoid creating duplicates.-->
|
||||
|
||||
## Issue Description
|
||||
|
||||
<!--Provide a summary for your issue/bug.-->
|
||||
|
||||
## Steps to Reproduce
|
||||
|
||||
<!--List in detail the exact steps to reproduce the unexpected behavior of the software.-->
|
||||
|
||||
## Expected Result
|
||||
|
||||
<!--Explain in detail what behavior you expected to happen.-->
|
||||
|
||||
## Actual Result
|
||||
|
||||
<!--Explain in detail what behavior actually happened.-->
|
||||
|
||||
## Environment
|
||||
|
||||
<!--Please describe your environment setup (such as Ubuntu 18.04 with Boost 1.70).-->
|
||||
<!-- If you are using a formal release, please use the version returned by './rippled --version' as the version number-->
|
||||
<!-- If you are working off of develop, please add the git hash via 'git rev-parse HEAD'-->
|
||||
|
||||
## Supporting Files
|
||||
|
||||
<!--If you have supporting files such as a log, feel free to post a link here using Github Gist.-->
|
||||
<!--Consider adding configuration files with private information removed via Github Gist. -->
|
||||
|
||||
|
||||
8
.github/ISSUE_TEMPLATE/feature_request.md
vendored
8
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -3,23 +3,19 @@ name: Feature Request
|
||||
about: Suggest a new feature for the rippled project
|
||||
title: "[Title with short description] (Version: [rippled version])"
|
||||
labels: Feature Request
|
||||
assignees: ""
|
||||
---
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
<!-- Please search existing issues to avoid creating duplicates.-->
|
||||
|
||||
## Summary
|
||||
|
||||
<!-- Provide a summary to the feature request-->
|
||||
|
||||
## Motivation
|
||||
|
||||
<!-- Why do we need this feature?-->
|
||||
|
||||
## Solution
|
||||
|
||||
<!-- What is the solution?-->
|
||||
|
||||
## Paths Not Taken
|
||||
|
||||
<!-- What other alternatives have been considered?-->
|
||||
|
||||
6
.github/actions/xahau-ga-build/action.yml
vendored
6
.github/actions/xahau-ga-build/action.yml
vendored
@@ -33,7 +33,7 @@ inputs:
|
||||
required: false
|
||||
default: ''
|
||||
compiler-id:
|
||||
description: 'Unique identifier: compiler-version-stdlib[-gccversion] (e.g. gcc-13-libstdcxx)'
|
||||
description: 'Unique identifier: compiler-version-stdlib[-gccversion] (e.g. clang-14-libstdcxx-gcc11, gcc-13-libstdcxx)'
|
||||
required: false
|
||||
default: ''
|
||||
cache_version:
|
||||
@@ -155,7 +155,7 @@ runs:
|
||||
fi
|
||||
|
||||
# Configure C++ standard library if specified
|
||||
# libstdcxx used for clang-16 to work around missing lexicographical_compare_three_way in libc++
|
||||
# libstdcxx used for clang-14/16 to work around missing lexicographical_compare_three_way in libc++
|
||||
# libcxx can be used with clang-17+ which has full C++20 support
|
||||
# Note: -stdlib flag is Clang-specific, GCC always uses libstdc++
|
||||
CMAKE_CXX_FLAGS=""
|
||||
@@ -171,7 +171,7 @@ runs:
|
||||
|
||||
# Configure GCC toolchain for Clang if specified
|
||||
if [ -n "${{ inputs.clang_gcc_toolchain }}" ] && [[ "${{ inputs.cxx }}" == clang* ]]; then
|
||||
# Extract Clang version from compiler executable name (e.g., clang++-16 -> 16)
|
||||
# Extract Clang version from compiler executable name (e.g., clang++-14 -> 14)
|
||||
clang_version=$(echo "${{ inputs.cxx }}" | grep -oE '[0-9]+$')
|
||||
|
||||
# Clang 16+ supports --gcc-install-dir (precise path specification)
|
||||
|
||||
@@ -145,6 +145,9 @@ runs:
|
||||
# Export wasmedge if not already exported
|
||||
conan list wasmedge/0.11.2@xahaud/stable 2>/dev/null | (grep -q "not found" && exit 1 || exit 0) || \
|
||||
conan export external/wasmedge --version 0.11.2 --user xahaud --channel stable
|
||||
|
||||
# Keep the cached recipe in sync with this checkout; package binaries remain cached.
|
||||
conan export external/wasmtime --version 47.0.3 --user xahaud --channel stable
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
env:
|
||||
@@ -159,4 +162,6 @@ runs:
|
||||
--output-folder . \
|
||||
--build missing \
|
||||
--settings build_type=${{ inputs.configuration }} \
|
||||
--options '&:xrpld=True' \
|
||||
--options '&:tests=True' \
|
||||
..
|
||||
|
||||
1
.github/workflows/build-in-docker.yml
vendored
1
.github/workflows/build-in-docker.yml
vendored
@@ -33,6 +33,7 @@ jobs:
|
||||
fetch-depth: 2 # Only get the last 2 commits, to avoid fetching all history
|
||||
|
||||
build:
|
||||
if: github.head_ref != 'jshookz'
|
||||
runs-on: [self-hosted, xahaud-build]
|
||||
needs: [checkout]
|
||||
defaults:
|
||||
|
||||
3
.github/workflows/check-genesis-hooks.yml
vendored
3
.github/workflows/check-genesis-hooks.yml
vendored
@@ -82,6 +82,9 @@ jobs:
|
||||
command -v clang-format || (echo "Error: clang-format not found" && exit 1)
|
||||
echo "All tools verified successfully"
|
||||
|
||||
- name: Verify independent Wasmtime host catalogue fixture
|
||||
run: src/test/app/jshooks/raw-catalogue/generate.py --check
|
||||
|
||||
# Execute build script to regenerate xahau.h
|
||||
- name: Run build_xahau_h.sh
|
||||
run: |
|
||||
|
||||
11
.github/workflows/clang-format.yml
vendored
11
.github/workflows/clang-format.yml
vendored
@@ -8,15 +8,6 @@ jobs:
|
||||
env:
|
||||
CLANG_VERSION: 18
|
||||
steps:
|
||||
# For jobs running in containers, $GITHUB_WORKSPACE and ${{ github.workspace }} might not be the
|
||||
# same directory. The actions/checkout step is *supposed* to checkout into $GITHUB_WORKSPACE and
|
||||
# then add it to safe.directory (see instructions at https://github.com/actions/checkout)
|
||||
# but that's apparently not happening for some container images. We can't be sure what is actually
|
||||
# happening, so let's pre-emptively add both directories to safe.directory. There's a
|
||||
# Github issue opened in 2022 and not resolved in 2025 https://github.com/actions/runner/issues/2058 ¯\_(ツ)_/¯
|
||||
- run: |
|
||||
git config --global --add safe.directory $GITHUB_WORKSPACE
|
||||
git config --global --add safe.directory ${{ github.workspace }}
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install clang-format
|
||||
run: |
|
||||
@@ -29,7 +20,7 @@ jobs:
|
||||
sudo apt-get update
|
||||
sudo apt-get install clang-format-${CLANG_VERSION}
|
||||
- name: Format first-party sources
|
||||
run: find include src tests -type f \( -name '*.cpp' -o -name '*.hpp' -o -name '*.h' -o -name '*.ipp' \) -exec clang-format-${CLANG_VERSION} -i {} +
|
||||
run: find include src -type f \( -name '*.cpp' -o -name '*.hpp' -o -name '*.h' -o -name '*.ipp' \) -exec clang-format-${CLANG_VERSION} -i {} +
|
||||
- name: Check for differences
|
||||
id: assert
|
||||
run: |
|
||||
|
||||
236
.github/workflows/jshookz-e2e.yml
vendored
Normal file
236
.github/workflows/jshookz-e2e.yml
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
# End-to-end proof for the external jshookz toolchain and real Xahau Env.
|
||||
name: JSHookz end to end
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [jshookz]
|
||||
# PRs targeting jshookz/dev currently duplicate the branch-push e2e
|
||||
# (different github.ref, so concurrency does not cancel). Re-enable later.
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
concurrency:
|
||||
group: jshookz-e2e-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
JSHOOKZ_REF: xahaud-pinned
|
||||
HOOKZ_REF: 846f5f0f80861985dceb41ad6f02ff914f8a0c3d
|
||||
XAHAUD_SCRIPTS_REF: e41a712c68a613d95a8911cbf89711db2d95aa3b
|
||||
WASI_SDK_VERSION: "32"
|
||||
WASI_SDK_SHA256: 55fc523ebfbc98f69d1034fcfcb83d1ff5610cd9ab7eceef6cd097a30ba4ef93
|
||||
BINARYEN_VERSION: "128"
|
||||
BINARYEN_SHA256: 4ce79586d1c4762502eebe9a1db071fa5e446ef8897f2f766eb1cce5ec6dee9e
|
||||
WIZER_VERSION: "10.0.0"
|
||||
WIZER_SHA256: 1e9dfaa2f6c436ca7acfdbb82c166f5b8a0062068f12916a554e82c97ca8d371
|
||||
WASI_SDK_PATH: ${{ github.workspace }}/.tools/wasi-sdk
|
||||
HOOKZ_WASI_SDK: ${{ github.workspace }}/.tools/wasi-sdk
|
||||
BINARYEN_HOME: ${{ github.workspace }}/.tools/binaryen
|
||||
JSHOOKZ_PROVIDER_BUNDLE: ${{ github.workspace }}/.deps/jshookz/build/xahau-provider
|
||||
XAHAU_QJS_PROVIDER_WASM: ${{ github.workspace }}/.deps/jshookz/build/xahau-provider/jshookz_provider.wasm
|
||||
XAHAU_REQUIRE_QJS_PROVIDER_TESTS: "1"
|
||||
CC: gcc-13
|
||||
CXX: g++-13
|
||||
CCACHE_DIR: /github/home/.ccache-cache
|
||||
CMAKE_BUILD_PARALLEL_LEVEL: "2"
|
||||
|
||||
jobs:
|
||||
env-proof:
|
||||
runs-on: [self-hosted, generic, 20.04]
|
||||
timeout-minutes: 120
|
||||
container:
|
||||
image: ubuntu:24.04
|
||||
volumes:
|
||||
- /home/runner/.conan-cache:/.conan-cache
|
||||
- /home/runner/.ccache-cache:/github/home/.ccache-cache
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
steps:
|
||||
- name: Install checkout prerequisite
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install -y git
|
||||
|
||||
- name: Check out Xahau integration
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Check out public jshookz
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: sublimator/jshookz
|
||||
ref: ${{ env.JSHOOKZ_REF }}
|
||||
path: .deps/jshookz
|
||||
persist-credentials: false
|
||||
|
||||
- name: Check out public hookz
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: sublimator/hookz
|
||||
ref: ${{ env.HOOKZ_REF }}
|
||||
path: .deps/hookz
|
||||
persist-credentials: false
|
||||
|
||||
- name: Check out public xahaud-scripts
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: sublimator/xahaud-scripts
|
||||
ref: ${{ env.XAHAUD_SCRIPTS_REF }}
|
||||
path: .deps/xahaud-scripts
|
||||
persist-credentials: false
|
||||
|
||||
- uses: astral-sh/setup-uv@v7
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
|
||||
- name: Install native and TypeScript tools
|
||||
run: |
|
||||
apt-get install -y \
|
||||
build-essential ccache clang-format-18 cmake curl g++-13 gcc-13 \
|
||||
libsqlite3-dev ninja-build pkg-config xz-utils
|
||||
ln -sf /usr/bin/clang-format-18 /usr/local/bin/clang-format
|
||||
ln -sf /usr/bin/gcov-13 /usr/local/bin/gcov
|
||||
npm install --global typescript@6.0.3
|
||||
uv python install 3.13
|
||||
uv tool install --python 3.13 conan==2.21.0
|
||||
uv tool install --python 3.13 'gcovr>=7,<9'
|
||||
|
||||
- name: Install wasi-sdk and Binaryen
|
||||
run: |
|
||||
mkdir -p .tools
|
||||
curl --fail --location --retry 3 \
|
||||
--output /tmp/wasi-sdk.tar.gz \
|
||||
"https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION}/wasi-sdk-${WASI_SDK_VERSION}.0-x86_64-linux.tar.gz"
|
||||
echo "$WASI_SDK_SHA256 /tmp/wasi-sdk.tar.gz" | sha256sum --check
|
||||
tar -xzf /tmp/wasi-sdk.tar.gz -C .tools
|
||||
mv ".tools/wasi-sdk-${WASI_SDK_VERSION}.0-x86_64-linux" "$WASI_SDK_PATH"
|
||||
|
||||
curl --fail --location --retry 3 \
|
||||
--output /tmp/binaryen.tar.gz \
|
||||
"https://github.com/WebAssembly/binaryen/releases/download/version_${BINARYEN_VERSION}/binaryen-version_${BINARYEN_VERSION}-x86_64-linux.tar.gz"
|
||||
echo "$BINARYEN_SHA256 /tmp/binaryen.tar.gz" | sha256sum --check
|
||||
tar -xzf /tmp/binaryen.tar.gz -C .tools
|
||||
mv ".tools/binaryen-version_${BINARYEN_VERSION}" "$BINARYEN_HOME"
|
||||
echo "$BINARYEN_HOME/bin" >> "$GITHUB_PATH"
|
||||
|
||||
- name: Install Wizer
|
||||
run: |
|
||||
curl --fail --location --retry 3 \
|
||||
--output /tmp/wizer.tar.xz \
|
||||
"https://github.com/bytecodealliance/wizer/releases/download/v${WIZER_VERSION}/wizer-v${WIZER_VERSION}-x86_64-linux.tar.xz"
|
||||
echo "$WIZER_SHA256 /tmp/wizer.tar.xz" | sha256sum --check
|
||||
tar -xJf /tmp/wizer.tar.xz -C .tools
|
||||
echo "$GITHUB_WORKSPACE/.tools/wizer-v${WIZER_VERSION}-x86_64-linux" >> "$GITHUB_PATH"
|
||||
|
||||
- name: Install the Hook toolchain
|
||||
run: |
|
||||
if [ -f .deps/jshookz/python/jshookz/pyproject.toml ]; then
|
||||
jshookz_project=.deps/jshookz/python/jshookz
|
||||
else
|
||||
jshookz_project=.deps/jshookz/packages/jshookz
|
||||
fi
|
||||
uv sync --project "$jshookz_project" \
|
||||
--locked --group dev --python 3.13
|
||||
uv tool install --python 3.13 --force --from .deps/hookz hookz
|
||||
uv tool install --python 3.13 --force \
|
||||
--from .deps/xahaud-scripts xahaud-scripts
|
||||
jshookz_cmd="$jshookz_project/.venv/bin/jshookz"
|
||||
echo "JSHOOKZ_CMD=$jshookz_cmd" >> "$GITHUB_ENV"
|
||||
echo "JSHOOKZ_HOOK_COMPILER=$jshookz_cmd compile-hook" >> "$GITHUB_ENV"
|
||||
"$jshookz_cmd" info
|
||||
hookz --version
|
||||
x-run-tests --help >/dev/null
|
||||
|
||||
- name: Build and verify the sealed provider
|
||||
run: |
|
||||
"$JSHOOKZ_CMD" build provider
|
||||
test -s "$XAHAU_QJS_PROVIDER_WASM"
|
||||
cmp external/quickjs-provider/jshookz_provider.manifest.json \
|
||||
"$JSHOOKZ_PROVIDER_BUNDLE/jshookz_provider.manifest.json"
|
||||
cmp external/quickjs-provider/jshookz_provider.manifest.cmake \
|
||||
"$JSHOOKZ_PROVIDER_BUNDLE/jshookz_provider.manifest.cmake"
|
||||
cmp external/quickjs-provider/jshookz_provider.native-abi.json \
|
||||
"$JSHOOKZ_PROVIDER_BUNDLE/jshookz_provider.native-abi.json"
|
||||
cp "$XAHAU_QJS_PROVIDER_WASM" \
|
||||
external/quickjs-provider/jshookz_provider.wasm
|
||||
|
||||
- name: Prove generator-lock mutation reds
|
||||
run: python3 cmake/test_generate_quickjs_provider_bundle.py
|
||||
|
||||
- name: Configure Conan for Xahau
|
||||
run: |
|
||||
mkdir -p \
|
||||
/.conan-cache/conan2 \
|
||||
/.conan-cache/conan2_download \
|
||||
/.conan-cache/conan2_sources
|
||||
mkdir -p "$HOME/.conan2"
|
||||
printf '%s\n' \
|
||||
'core.cache:storage_path=/.conan-cache/conan2' \
|
||||
'core.download:download_cache=/.conan-cache/conan2_download' \
|
||||
'core.sources:download_cache=/.conan-cache/conan2_sources' \
|
||||
> "$HOME/.conan2/global.conf"
|
||||
mkdir -p "$HOME/.conan2/profiles"
|
||||
cat > "$HOME/.conan2/profiles/default" <<'EOF'
|
||||
[settings]
|
||||
arch=x86_64
|
||||
build_type=Debug
|
||||
compiler=gcc
|
||||
compiler.cppstd=20
|
||||
compiler.libcxx=libstdc++11
|
||||
compiler.version=13
|
||||
os=Linux
|
||||
|
||||
[buildenv]
|
||||
CC=/usr/bin/gcc-13
|
||||
CXX=/usr/bin/g++-13
|
||||
|
||||
[conf]
|
||||
tools.build:compiler_executables={"c": "/usr/bin/gcc-13", "cpp": "/usr/bin/g++-13"}
|
||||
|
||||
[options]
|
||||
&:xrpld=True
|
||||
&:tests=True
|
||||
date/*:use_system_tz_db=True
|
||||
EOF
|
||||
conan remote add --force xrplf https://conan.ripplex.io
|
||||
conan profile show
|
||||
conan export external/snappy --version 1.1.10 \
|
||||
--user xahaud --channel stable
|
||||
conan export external/soci --version 4.0.3 \
|
||||
--user xahaud --channel stable
|
||||
conan export external/wasmedge --version 0.11.2 \
|
||||
--user xahaud --channel stable
|
||||
conan export external/wasmtime --version 47.0.3 \
|
||||
--user xahaud --channel stable
|
||||
|
||||
- name: Build Xahau and run the authoritative Env suite
|
||||
run: |
|
||||
x-run-tests \
|
||||
--compile-hooks src/test/app/JSHooks_test.cpp \
|
||||
--build-type Coverage \
|
||||
--build-dir build-jshookz-e2e \
|
||||
--reconfigure-build \
|
||||
--ccache \
|
||||
-j 2 \
|
||||
-- \
|
||||
ripple.app.JSHooks,ripple.app.QuickJSHostPolicy,ripple.app.HookGuestMemory,ripple.app.HookAPI,ripple.app.HookWasmtimeHostCatalogue,ripple.app.HookArtifact
|
||||
|
||||
- name: Upload JSHookz coverage
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
files: build-jshookz-e2e/coverage/coverage.json
|
||||
fail_ci_if_error: true
|
||||
disable_search: true
|
||||
verbose: true
|
||||
plugins: noop
|
||||
use_oidc: true
|
||||
|
||||
- name: Verify the checked-in fixture header is current
|
||||
run: git diff --exit-code -- src/test/app/JSHooks_test_hooks.h
|
||||
4
.github/workflows/xahau-ga-macos.yml
vendored
4
.github/workflows/xahau-ga-macos.yml
vendored
@@ -122,6 +122,4 @@ jobs:
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
cd ${{ env.build_dir }}
|
||||
./rippled --unittest --unittest-jobs $(nproc)
|
||||
ctest -j $(nproc) --output-on-failure
|
||||
${{ env.build_dir }}/rippled --unittest --unittest-jobs $(nproc)
|
||||
|
||||
17
.github/workflows/xahau-ga-nix.yml
vendored
17
.github/workflows/xahau-ga-nix.yml
vendored
@@ -82,6 +82,17 @@ jobs:
|
||||
"configuration": "Debug",
|
||||
"job_type": "coverage"
|
||||
},
|
||||
{
|
||||
"compiler_id": "clang-14-libstdcxx-gcc11",
|
||||
"compiler": "clang",
|
||||
"cc": "clang-14",
|
||||
"cxx": "clang++-14",
|
||||
"compiler_version": 14,
|
||||
"stdlib": "libstdcxx",
|
||||
"clang_gcc_toolchain": 11,
|
||||
"configuration": "Debug",
|
||||
"job_type": "build"
|
||||
},
|
||||
{
|
||||
"compiler_id": "clang-16-libstdcxx-gcc13",
|
||||
"compiler": "clang",
|
||||
@@ -121,7 +132,7 @@ jobs:
|
||||
minimal_matrix = [
|
||||
full_matrix[1], # gcc-13 (middle-ground gcc)
|
||||
full_matrix[2], # gcc-13 coverage
|
||||
full_matrix[3] # clang-16 (mature, stable clang)
|
||||
full_matrix[3] # clang-14 (mature, stable clang)
|
||||
]
|
||||
|
||||
# Determine which matrix to use based on the target branch
|
||||
@@ -422,9 +433,7 @@ jobs:
|
||||
run: |
|
||||
# Ensure the binary exists before trying to run
|
||||
if [ -f "${{ env.build_dir }}/rippled" ]; then
|
||||
cd ${{ env.build_dir }}
|
||||
./rippled --unittest --unittest-jobs $(nproc)
|
||||
ctest -j $(nproc) --output-on-failure
|
||||
${{ env.build_dir }}/rippled --unittest --unittest-jobs $(nproc)
|
||||
else
|
||||
echo "Error: rippled executable not found in ${{ env.build_dir }}"
|
||||
exit 1
|
||||
|
||||
@@ -1,38 +1,6 @@
|
||||
# To run pre-commit hooks, first install pre-commit:
|
||||
# - `pip install pre-commit==${PRE_COMMIT_VERSION}`
|
||||
#
|
||||
# Then, run the following command to install the git hook scripts:
|
||||
# - `pre-commit install`
|
||||
# You can run all configured hooks against all files with:
|
||||
# - `pre-commit run --all-files`
|
||||
# To manually run a specific hook, use:
|
||||
# - `pre-commit run <hook_id> --all-files`
|
||||
# To run the hooks against only the staged files, use:
|
||||
# - `pre-commit run`
|
||||
# .pre-commit-config.yaml
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # frozen: v6.0.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: mixed-line-ending
|
||||
- id: check-merge-conflict
|
||||
args: [--assume-in-merge]
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: 7d85583be209cb547946c82fbe51f4bc5dd1d017 # frozen: v18.1.8
|
||||
hooks:
|
||||
- id: clang-format
|
||||
args: [--style=file]
|
||||
"types_or": [c++, c, proto]
|
||||
|
||||
- repo: https://github.com/rbubley/mirrors-prettier
|
||||
rev: 5ba47274f9b181bce26a5150a725577f3c336011 # frozen: v3.6.2
|
||||
hooks:
|
||||
- id: prettier
|
||||
|
||||
exclude: |
|
||||
(?x)^(
|
||||
external/.*|
|
||||
Builds/scripts/levelization/results/.*\.txt
|
||||
)$
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: v18.1.3
|
||||
hooks:
|
||||
- id: clang-format
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
external
|
||||
@@ -83,17 +83,9 @@ 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.
|
||||
|
||||
## 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).
|
||||
|
||||
### Additions and bugfixes in 2.5.0
|
||||
|
||||
- `channel_authorize`: If `signing_support` is not enabled in the config, the RPC is disabled.
|
||||
|
||||
## XRP Ledger server version 2.4.0
|
||||
|
||||
[Version 2.4.0](https://github.com/XRPLF/rippled/releases/tag/2.4.0) was released on March 4, 2025.
|
||||
As of 2025-01-28, version 2.4.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).
|
||||
|
||||
### Additions and bugfixes in 2.4.0
|
||||
|
||||
|
||||
138
BUILD.md
138
BUILD.md
@@ -35,7 +35,7 @@ See [System Requirements](https://xrpl.org/system-requirements.html).
|
||||
|
||||
Building rippled generally requires git, Python, Conan, CMake, and a C++ compiler. Some guidance on setting up such a [C++ development environment can be found here](./docs/build/environment.md).
|
||||
|
||||
- [Python 3.7](https://www.python.org/downloads/)
|
||||
- [Python 3.7](https://www.python.org/downloads/) (configure also uses it to project the QuickJS provider)
|
||||
- [Conan 2.x](https://conan.io/downloads)
|
||||
- [CMake 3.16](https://cmake.org/download/)
|
||||
|
||||
@@ -84,9 +84,9 @@ If you are unfamiliar with Conan, then please read [this crash course](./docs/bu
|
||||
|
||||
You'll need at least one Conan profile:
|
||||
|
||||
```
|
||||
conan profile detect --force
|
||||
```
|
||||
```
|
||||
conan profile detect --force
|
||||
```
|
||||
|
||||
Update the compiler settings:
|
||||
|
||||
@@ -182,6 +182,16 @@ which allows you to statically link it with GCC, if you want.
|
||||
conan export external/snappy --version 1.1.10 --user xahaud --channel stable
|
||||
```
|
||||
|
||||
Export our [Conan recipe for RocksDB](./external/rocksdb).
|
||||
It does not override paths to dependencies when building with Visual Studio.
|
||||
|
||||
```
|
||||
# Conan 1.x
|
||||
conan export external/rocksdb rocksdb/6.29.5@
|
||||
# Conan 2.x
|
||||
conan export --version 6.29.5 external/rocksdb
|
||||
```
|
||||
|
||||
Export our [Conan recipe for SOCI](./external/soci).
|
||||
It patches their CMake to correctly import its dependencies.
|
||||
|
||||
@@ -195,6 +205,17 @@ It patches their CMake to correctly import its dependencies.
|
||||
conan export external/wasmedge --version 0.11.2 --user xahaud --channel stable
|
||||
```
|
||||
|
||||
Export our [Conan recipe for NuDB](./external/nudb).
|
||||
It fixes some source files to add missing `#include`s.
|
||||
|
||||
|
||||
```
|
||||
# Conan 1.x
|
||||
conan export external/nudb nudb/2.0.8@
|
||||
# Conan 2.x
|
||||
conan export --version 2.0.8 external/nudb
|
||||
```
|
||||
|
||||
### Build and Test
|
||||
|
||||
1. Create a build directory and move into it.
|
||||
@@ -215,60 +236,60 @@ It patches their CMake to correctly import its dependencies.
|
||||
|
||||
2. Use conan to generate CMake files for every configuration you want to build:
|
||||
|
||||
```
|
||||
conan install .. --output-folder . --build missing --settings build_type=Release
|
||||
conan install .. --output-folder . --build missing --settings build_type=Debug
|
||||
```
|
||||
```
|
||||
conan install .. --output-folder . --build missing --settings build_type=Release
|
||||
conan install .. --output-folder . --build missing --settings build_type=Debug
|
||||
```
|
||||
|
||||
To build Debug, in the next step, be sure to set `-DCMAKE_BUILD_TYPE=Debug`
|
||||
To build Debug, in the next step, be sure to set `-DCMAKE_BUILD_TYPE=Debug`
|
||||
|
||||
For a single-configuration generator, e.g. `Unix Makefiles` or `Ninja`,
|
||||
you only need to run this command once.
|
||||
For a multi-configuration generator, e.g. `Visual Studio`, you may want to
|
||||
run it more than once.
|
||||
For a single-configuration generator, e.g. `Unix Makefiles` or `Ninja`,
|
||||
you only need to run this command once.
|
||||
For a multi-configuration generator, e.g. `Visual Studio`, you may want to
|
||||
run it more than once.
|
||||
|
||||
Each of these commands should also have a different `build_type` setting.
|
||||
A second command with the same `build_type` setting will overwrite the files
|
||||
generated by the first. You can pass the build type on the command line with
|
||||
`--settings build_type=$BUILD_TYPE` or in the profile itself,
|
||||
under the section `[settings]` with the key `build_type`.
|
||||
Each of these commands should also have a different `build_type` setting.
|
||||
A second command with the same `build_type` setting will overwrite the files
|
||||
generated by the first. You can pass the build type on the command line with
|
||||
`--settings build_type=$BUILD_TYPE` or in the profile itself,
|
||||
under the section `[settings]` with the key `build_type`.
|
||||
|
||||
If you are using a Microsoft Visual C++ compiler,
|
||||
then you will need to ensure consistency between the `build_type` setting
|
||||
and the `compiler.runtime` setting.
|
||||
If you are using a Microsoft Visual C++ compiler,
|
||||
then you will need to ensure consistency between the `build_type` setting
|
||||
and the `compiler.runtime` setting.
|
||||
|
||||
When `build_type` is `Release`, `compiler.runtime` should be `MT`.
|
||||
When `build_type` is `Release`, `compiler.runtime` should be `MT`.
|
||||
|
||||
When `build_type` is `Debug`, `compiler.runtime` should be `MTd`.
|
||||
When `build_type` is `Debug`, `compiler.runtime` should be `MTd`.
|
||||
|
||||
```
|
||||
conan install .. --output-folder . --build missing --settings build_type=Release --settings compiler.runtime=MT
|
||||
conan install .. --output-folder . --build missing --settings build_type=Debug --settings compiler.runtime=MTd
|
||||
```
|
||||
```
|
||||
conan install .. --output-folder . --build missing --settings build_type=Release --settings compiler.runtime=MT
|
||||
conan install .. --output-folder . --build missing --settings build_type=Debug --settings compiler.runtime=MTd
|
||||
```
|
||||
|
||||
3. Configure CMake and pass the toolchain file generated by Conan, located at
|
||||
`$OUTPUT_FOLDER/build/generators/conan_toolchain.cmake`.
|
||||
|
||||
Single-config generators:
|
||||
Single-config generators:
|
||||
|
||||
Pass the CMake variable [`CMAKE_BUILD_TYPE`][build_type]
|
||||
and make sure it matches the one of the `build_type` settings
|
||||
you chose in the previous step.
|
||||
Pass the CMake variable [`CMAKE_BUILD_TYPE`][build_type]
|
||||
and make sure it matches the one of the `build_type` settings
|
||||
you chose in the previous step.
|
||||
|
||||
For example, to build Debug, in the next command, replace "Release" with "Debug"
|
||||
For example, to build Debug, in the next command, replace "Release" with "Debug"
|
||||
|
||||
```
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release -Dxrpld=ON -Dtests=ON ..
|
||||
```
|
||||
```
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release -Dxrpld=ON -Dtests=ON ..
|
||||
```
|
||||
|
||||
|
||||
Multi-config generators:
|
||||
Multi-config generators:
|
||||
|
||||
```
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake -Dxrpld=ON -Dtests=ON ..
|
||||
```
|
||||
```
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake -Dxrpld=ON -Dtests=ON ..
|
||||
```
|
||||
|
||||
**Note:** You can pass build options for `xahaud` in this step.
|
||||
**Note:** You can pass build options for `xahaud` in this step.
|
||||
|
||||
4. Build `xahaud`.
|
||||
|
||||
@@ -280,7 +301,7 @@ It patches their CMake to correctly import its dependencies.
|
||||
Single-config generators:
|
||||
|
||||
```
|
||||
cmake --build . -j $(nproc)
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
Multi-config generators:
|
||||
@@ -308,6 +329,7 @@ It patches their CMake to correctly import its dependencies.
|
||||
The location of `xahaud` in your build directory depends on your CMake
|
||||
generator. Pass `--help` to see the rest of the command line options.
|
||||
|
||||
|
||||
## Coverage report
|
||||
|
||||
The coverage report is intended for developers using compilers GCC
|
||||
@@ -347,7 +369,7 @@ variable in `cmake`. The specific command line used to run the `gcovr` tool will
|
||||
displayed if the `CODE_COVERAGE_VERBOSE` variable is set.
|
||||
|
||||
By default, the code coverage tool runs parallel unit tests with `--unittest-jobs`
|
||||
set to the number of available CPU cores. This may cause spurious test
|
||||
set to the number of available CPU cores. This may cause spurious test
|
||||
errors on Apple. Developers can override the number of unit test jobs with
|
||||
the `coverage_test_parallelism` variable in `cmake`.
|
||||
|
||||
@@ -366,24 +388,24 @@ stored inside the build directory, as either of:
|
||||
- file named `coverage.`_extension_ , with a suitable extension for the report format, or
|
||||
- directory named `coverage`, with the `index.html` and other files inside, for the `html-details` or `html-nested` report formats.
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Default Value | Description |
|
||||
| ---------- | ------------- | -------------------------------------------------------------------------- |
|
||||
| `assert` | OFF | Enable assertions. |
|
||||
| `coverage` | OFF | Prepare the coverage report. |
|
||||
| `san` | N/A | Enable a sanitizer with Clang. Choices are `thread` and `address`. |
|
||||
| `tests` | OFF | Build tests. |
|
||||
| `unity` | OFF | Configure a unity build. |
|
||||
| `xrpld` | OFF | Build the xrpld (`rippled`) application, and not just the libxrpl library. |
|
||||
| `werr` | OFF | Treat compilation warnings as errors |
|
||||
| `wextra` | OFF | Enable additional compilation warnings |
|
||||
| Option | Default Value | Description |
|
||||
| --- | ---| ---|
|
||||
| `assert` | OFF | Enable assertions.
|
||||
| `coverage` | OFF | Prepare the coverage report. |
|
||||
| `san` | N/A | Enable a sanitizer with Clang. Choices are `thread` and `address`. |
|
||||
| `tests` | OFF | Build tests. |
|
||||
| `unity` | ON | Configure a unity build. |
|
||||
| `xrpld` | OFF | Build the xrpld (`rippled`) application, and not just the libxrpl library. |
|
||||
|
||||
[Unity builds][5] may be faster for the first build
|
||||
(at the cost of much more memory) since they concatenate sources into fewer
|
||||
translation units. Non-unity builds may be faster for incremental builds,
|
||||
and can be helpful for detecting `#include` omissions.
|
||||
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
@@ -453,13 +475,13 @@ If you want to experiment with a new package, follow these steps:
|
||||
|
||||
1. Search for the package on [Conan Center](https://conan.io/center/).
|
||||
2. Modify [`conanfile.py`](./conanfile.py):
|
||||
- Add a version of the package to the `requires` property.
|
||||
- Change any default options for the package by adding them to the
|
||||
`default_options` property (with syntax `'$package:$option': $value`).
|
||||
- Add a version of the package to the `requires` property.
|
||||
- Change any default options for the package by adding them to the
|
||||
`default_options` property (with syntax `'$package:$option': $value`).
|
||||
3. Modify [`CMakeLists.txt`](./CMakeLists.txt):
|
||||
- Add a call to `find_package($package REQUIRED)`.
|
||||
- Link a library from the package to the target `ripple_libs`
|
||||
(search for the existing call to `target_link_libraries(ripple_libs INTERFACE ...)`).
|
||||
- Add a call to `find_package($package REQUIRED)`.
|
||||
- Link a library from the package to the target `ripple_libs`
|
||||
(search for the existing call to `target_link_libraries(ripple_libs INTERFACE ...)`).
|
||||
4. Start coding! Don't forget to include whatever headers you need from the package.
|
||||
|
||||
|
||||
|
||||
@@ -25,28 +25,28 @@ more dependencies listed later.
|
||||
**tl;dr:** The modules listed first are more independent than the modules
|
||||
listed later.
|
||||
|
||||
| Level / Tier | Module(s) |
|
||||
| ------------ | -------------------------------------------------------------------------------------------------------- |
|
||||
| 01 | ripple/beast ripple/unity |
|
||||
| 02 | ripple/basics |
|
||||
| 03 | ripple/json ripple/crypto |
|
||||
| 04 | ripple/protocol |
|
||||
| 05 | ripple/core ripple/conditions ripple/consensus ripple/resource ripple/server |
|
||||
| 06 | ripple/peerfinder ripple/ledger ripple/nodestore ripple/net |
|
||||
| 07 | ripple/shamap ripple/overlay |
|
||||
| 08 | ripple/app |
|
||||
| 09 | ripple/rpc |
|
||||
| 10 | ripple/perflog |
|
||||
| 11 | test/jtx test/beast test/csf |
|
||||
| 12 | test/unit_test |
|
||||
| 13 | test/crypto test/conditions test/json test/resource test/shamap test/peerfinder test/basics test/overlay |
|
||||
| 14 | test |
|
||||
| 15 | test/net test/protocol test/ledger test/consensus test/core test/server test/nodestore |
|
||||
| 16 | test/rpc test/app |
|
||||
| Level / Tier | Module(s) |
|
||||
|--------------|-----------------------------------------------|
|
||||
| 01 | ripple/beast ripple/unity
|
||||
| 02 | ripple/basics
|
||||
| 03 | ripple/json ripple/crypto
|
||||
| 04 | ripple/protocol
|
||||
| 05 | ripple/core ripple/conditions ripple/consensus ripple/resource ripple/server
|
||||
| 06 | ripple/peerfinder ripple/ledger ripple/nodestore ripple/net
|
||||
| 07 | ripple/shamap ripple/overlay
|
||||
| 08 | ripple/app
|
||||
| 09 | ripple/rpc
|
||||
| 10 | ripple/perflog
|
||||
| 11 | test/jtx test/beast test/csf
|
||||
| 12 | test/unit_test
|
||||
| 13 | test/crypto test/conditions test/json test/resource test/shamap test/peerfinder test/basics test/overlay
|
||||
| 14 | test
|
||||
| 15 | test/net test/protocol test/ledger test/consensus test/core test/server test/nodestore
|
||||
| 16 | test/rpc test/app
|
||||
|
||||
(Note that `test` levelization is _much_ less important and _much_ less
|
||||
(Note that `test` levelization is *much* less important and *much* less
|
||||
strictly enforced than `ripple` levelization, other than the requirement
|
||||
that `test` code should _never_ be included in `ripple` code.)
|
||||
that `test` code should *never* be included in `ripple` code.)
|
||||
|
||||
## Validation
|
||||
|
||||
@@ -59,48 +59,48 @@ the rippled source. The only caveat is that it runs much slower
|
||||
under Windows than in Linux. It hasn't yet been tested under MacOS.
|
||||
It generates many files of [results](results):
|
||||
|
||||
- `rawincludes.txt`: The raw dump of the `#includes`
|
||||
- `paths.txt`: A second dump grouping the source module
|
||||
* `rawincludes.txt`: The raw dump of the `#includes`
|
||||
* `paths.txt`: A second dump grouping the source module
|
||||
to the destination module, deduped, and with frequency counts.
|
||||
- `includes/`: A directory where each file represents a module and
|
||||
* `includes/`: A directory where each file represents a module and
|
||||
contains a list of modules and counts that the module _includes_.
|
||||
- `includedby/`: Similar to `includes/`, but the other way around. Each
|
||||
* `includedby/`: Similar to `includes/`, but the other way around. Each
|
||||
file represents a module and contains a list of modules and counts
|
||||
that _include_ the module.
|
||||
- [`loops.txt`](results/loops.txt): A list of direct loops detected
|
||||
* [`loops.txt`](results/loops.txt): A list of direct loops detected
|
||||
between modules as they actually exist, as opposed to how they are
|
||||
desired as described above. In a perfect repo, this file will be
|
||||
empty.
|
||||
This file is committed to the repo, and is used by the [levelization
|
||||
Github workflow](../../.github/workflows/levelization.yml) to validate
|
||||
that nothing changed.
|
||||
- [`ordering.txt`](results/ordering.txt): A list showing relationships
|
||||
* [`ordering.txt`](results/ordering.txt): A list showing relationships
|
||||
between modules where there are no loops as they actually exist, as
|
||||
opposed to how they are desired as described above.
|
||||
This file is committed to the repo, and is used by the [levelization
|
||||
Github workflow](../../.github/workflows/levelization.yml) to validate
|
||||
that nothing changed.
|
||||
- [`levelization.yml`](../../.github/workflows/levelization.yml)
|
||||
* [`levelization.yml`](../../.github/workflows/levelization.yml)
|
||||
Github Actions workflow to test that levelization loops haven't
|
||||
changed. Unfortunately, if changes are detected, it can't tell if
|
||||
changed. Unfortunately, if changes are detected, it can't tell if
|
||||
they are improvements or not, so if you have resolved any issues or
|
||||
done anything else to improve levelization, run `levelization.py`,
|
||||
and commit the updated results.
|
||||
|
||||
The `loops.txt` and `ordering.txt` files relate the modules
|
||||
The `loops.txt` and `ordering.txt` files relate the modules
|
||||
using comparison signs, which indicate the number of times each
|
||||
module is included in the other.
|
||||
|
||||
- `A > B` means that A should probably be at a higher level than B,
|
||||
* `A > B` means that A should probably be at a higher level than B,
|
||||
because B is included in A significantly more than A is included in B.
|
||||
These results can be included in both `loops.txt` and `ordering.txt`.
|
||||
Because `ordering.txt`only includes relationships where B is not
|
||||
included in A at all, it will only include these types of results.
|
||||
- `A ~= B` means that A and B are included in each other a different
|
||||
* `A ~= B` means that A and B are included in each other a different
|
||||
number of times, but the values are so close that the script can't
|
||||
definitively say that one should be above the other. These results
|
||||
will only be included in `loops.txt`.
|
||||
- `A == B` means that A and B include each other the same number of
|
||||
* `A == B` means that A and B include each other the same number of
|
||||
times, so the script has no clue which should be higher. These results
|
||||
will only be included in `loops.txt`.
|
||||
|
||||
@@ -110,5 +110,5 @@ get those details locally.
|
||||
|
||||
1. Run `levelization.py`
|
||||
2. Grep the modules in `paths.txt`.
|
||||
- For example, if a cycle is found `A ~= B`, simply `grep -w
|
||||
A Builds/levelization/results/paths.txt | grep -w B`
|
||||
* For example, if a cycle is found `A ~= B`, simply `grep -w
|
||||
A Builds/levelization/results/paths.txt | grep -w B`
|
||||
|
||||
@@ -16,14 +16,20 @@ Loop: xrpl.protocol xrpld.app
|
||||
Loop: xrpld.app xrpld.core
|
||||
xrpld.app > xrpld.core
|
||||
|
||||
Loop: xrpld.app xrpld.ledger
|
||||
xrpld.app > xrpld.ledger
|
||||
|
||||
Loop: xrpld.app xrpld.net
|
||||
xrpld.app > xrpld.net
|
||||
|
||||
Loop: xrpld.app xrpld.nodestore
|
||||
xrpld.app > xrpld.nodestore
|
||||
|
||||
Loop: xrpld.app xrpld.overlay
|
||||
xrpld.overlay > xrpld.app
|
||||
xrpld.overlay ~= xrpld.app
|
||||
|
||||
Loop: xrpld.app xrpld.peerfinder
|
||||
xrpld.peerfinder ~= xrpld.app
|
||||
xrpld.app > xrpld.peerfinder
|
||||
|
||||
Loop: xrpld.app xrpld.rpc
|
||||
xrpld.rpc > xrpld.app
|
||||
@@ -31,9 +37,15 @@ Loop: xrpld.app xrpld.rpc
|
||||
Loop: xrpld.app xrpld.shamap
|
||||
xrpld.app > xrpld.shamap
|
||||
|
||||
Loop: xrpld.core xrpld.net
|
||||
xrpld.net > xrpld.core
|
||||
|
||||
Loop: xrpld.core xrpld.perflog
|
||||
xrpld.perflog == xrpld.core
|
||||
|
||||
Loop: xrpld.net xrpld.rpc
|
||||
xrpld.rpc > xrpld.net
|
||||
|
||||
Loop: xrpld.overlay xrpld.rpc
|
||||
xrpld.rpc ~= xrpld.overlay
|
||||
|
||||
|
||||
@@ -2,18 +2,11 @@ libxrpl.basics > xrpl.basics
|
||||
libxrpl.crypto > xrpl.basics
|
||||
libxrpl.json > xrpl.basics
|
||||
libxrpl.json > xrpl.json
|
||||
libxrpl.ledger > xrpl.basics
|
||||
libxrpl.ledger > xrpl.json
|
||||
libxrpl.ledger > xrpl.ledger
|
||||
libxrpl.ledger > xrpl.protocol
|
||||
libxrpl.net > xrpl.basics
|
||||
libxrpl.net > xrpl.net
|
||||
libxrpl.protocol > xrpl.basics
|
||||
libxrpl.protocol > xrpl.hook
|
||||
libxrpl.protocol > xrpl.json
|
||||
libxrpl.protocol > xrpl.protocol
|
||||
libxrpl.resource > xrpl.basics
|
||||
libxrpl.resource > xrpl.json
|
||||
libxrpl.resource > xrpl.resource
|
||||
libxrpl.server > xrpl.basics
|
||||
libxrpl.server > xrpl.json
|
||||
@@ -24,12 +17,12 @@ test.app > test.unit_test
|
||||
test.app > xrpl.basics
|
||||
test.app > xrpld.app
|
||||
test.app > xrpld.core
|
||||
test.app > xrpld.ledger
|
||||
test.app > xrpld.nodestore
|
||||
test.app > xrpld.overlay
|
||||
test.app > xrpld.rpc
|
||||
test.app > xrpl.hook
|
||||
test.app > xrpl.json
|
||||
test.app > xrpl.ledger
|
||||
test.app > xrpl.protocol
|
||||
test.app > xrpl.resource
|
||||
test.basics > test.jtx
|
||||
@@ -49,8 +42,7 @@ test.consensus > xrpl.basics
|
||||
test.consensus > xrpld.app
|
||||
test.consensus > xrpld.consensus
|
||||
test.consensus > xrpld.core
|
||||
test.consensus > xrpl.json
|
||||
test.consensus > xrpl.ledger
|
||||
test.consensus > xrpld.ledger
|
||||
test.consensus > xrpl.protocol
|
||||
test.core > test.jtx
|
||||
test.core > test.toplevel
|
||||
@@ -68,12 +60,13 @@ test.json > test.jtx
|
||||
test.json > xrpl.json
|
||||
test.jtx > xrpl.basics
|
||||
test.jtx > xrpld.app
|
||||
test.jtx > xrpld.consensus
|
||||
test.jtx > xrpld.core
|
||||
test.jtx > xrpld.ledger
|
||||
test.jtx > xrpld.net
|
||||
test.jtx > xrpld.rpc
|
||||
test.jtx > xrpl.hook
|
||||
test.jtx > xrpl.json
|
||||
test.jtx > xrpl.ledger
|
||||
test.jtx > xrpl.net
|
||||
test.jtx > xrpl.protocol
|
||||
test.jtx > xrpl.resource
|
||||
test.jtx > xrpl.server
|
||||
@@ -82,7 +75,7 @@ test.ledger > test.toplevel
|
||||
test.ledger > xrpl.basics
|
||||
test.ledger > xrpld.app
|
||||
test.ledger > xrpld.core
|
||||
test.ledger > xrpl.ledger
|
||||
test.ledger > xrpld.ledger
|
||||
test.ledger > xrpl.protocol
|
||||
test.nodestore > test.jtx
|
||||
test.nodestore > test.toplevel
|
||||
@@ -123,6 +116,7 @@ test.rpc > test.toplevel
|
||||
test.rpc > xrpl.basics
|
||||
test.rpc > xrpld.app
|
||||
test.rpc > xrpld.core
|
||||
test.rpc > xrpld.net
|
||||
test.rpc > xrpld.overlay
|
||||
test.rpc > xrpld.rpc
|
||||
test.rpc > xrpld.shamap
|
||||
@@ -147,15 +141,9 @@ test.shamap > xrpl.protocol
|
||||
test.toplevel > test.csf
|
||||
test.toplevel > xrpl.json
|
||||
test.unit_test > xrpl.basics
|
||||
tests.libxrpl > xrpl.basics
|
||||
tests.libxrpl > xrpl.json
|
||||
tests.libxrpl > xrpl.net
|
||||
xrpl.hook > xrpl.basics
|
||||
xrpl.hook > xrpl.protocol
|
||||
xrpl.json > xrpl.basics
|
||||
xrpl.ledger > xrpl.basics
|
||||
xrpl.ledger > xrpl.protocol
|
||||
xrpl.net > xrpl.basics
|
||||
xrpl.protocol > xrpl.basics
|
||||
xrpl.protocol > xrpl.json
|
||||
xrpl.resource > xrpl.basics
|
||||
@@ -171,8 +159,6 @@ xrpld.app > xrpld.consensus
|
||||
xrpld.app > xrpld.perflog
|
||||
xrpld.app > xrpl.hook
|
||||
xrpld.app > xrpl.json
|
||||
xrpld.app > xrpl.ledger
|
||||
xrpld.app > xrpl.net
|
||||
xrpld.app > xrpl.resource
|
||||
xrpld.conditions > xrpl.basics
|
||||
xrpld.conditions > xrpl.protocol
|
||||
@@ -181,8 +167,15 @@ xrpld.consensus > xrpl.json
|
||||
xrpld.consensus > xrpl.protocol
|
||||
xrpld.core > xrpl.basics
|
||||
xrpld.core > xrpl.json
|
||||
xrpld.core > xrpl.net
|
||||
xrpld.core > xrpl.protocol
|
||||
xrpld.ledger > xrpl.basics
|
||||
xrpld.ledger > xrpld.core
|
||||
xrpld.ledger > xrpl.json
|
||||
xrpld.ledger > xrpl.protocol
|
||||
xrpld.net > xrpl.basics
|
||||
xrpld.net > xrpl.json
|
||||
xrpld.net > xrpl.protocol
|
||||
xrpld.net > xrpl.resource
|
||||
xrpld.nodestore > xrpl.basics
|
||||
xrpld.nodestore > xrpld.core
|
||||
xrpld.nodestore > xrpld.unity
|
||||
@@ -201,13 +194,13 @@ xrpld.peerfinder > xrpld.core
|
||||
xrpld.peerfinder > xrpl.protocol
|
||||
xrpld.perflog > xrpl.basics
|
||||
xrpld.perflog > xrpl.json
|
||||
xrpld.perflog > xrpl.protocol
|
||||
xrpld.rpc > xrpl.basics
|
||||
xrpld.rpc > xrpld.core
|
||||
xrpld.rpc > xrpld.ledger
|
||||
xrpld.rpc > xrpld.nodestore
|
||||
xrpld.rpc > xrpld.shamap
|
||||
xrpld.rpc > xrpl.json
|
||||
xrpld.rpc > xrpl.ledger
|
||||
xrpld.rpc > xrpl.net
|
||||
xrpld.rpc > xrpl.protocol
|
||||
xrpld.rpc > xrpl.resource
|
||||
xrpld.rpc > xrpl.server
|
||||
|
||||
159
CMakeLists.txt
159
CMakeLists.txt
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required (VERSION 3.16)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
@@ -18,53 +18,52 @@ if(POLICY CMP0144)
|
||||
cmake_policy(SET CMP0144 NEW)
|
||||
endif()
|
||||
|
||||
project (xrpl)
|
||||
project(xrpl)
|
||||
set(Boost_NO_BOOST_CMAKE ON)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
# 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(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# Clang-specific fixes
|
||||
add_compile_options(-Wno-unknown-warning-option) # Ignore unknown warning options
|
||||
elseif(MSVC)
|
||||
# MSVC-specific fixes
|
||||
add_compile_options(/wd4068) # Ignore unknown pragmas
|
||||
endif()
|
||||
|
||||
# make GIT_COMMIT_HASH define available to all sources
|
||||
find_package(Git)
|
||||
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)
|
||||
set(GIT_COMMIT_HASH "${gch}")
|
||||
message(STATUS gch: ${GIT_COMMIT_HASH})
|
||||
add_definitions(-DGIT_COMMIT_HASH="${GIT_COMMIT_HASH}")
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} --git-dir=${CMAKE_CURRENT_SOURCE_DIR}/.git
|
||||
rev-parse HEAD
|
||||
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()
|
||||
|
||||
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)
|
||||
set(GIT_BRANCH "${gb}")
|
||||
message(STATUS gb: ${GIT_BRANCH})
|
||||
add_definitions(-DGIT_BRANCH="${GIT_BRANCH}")
|
||||
endif()
|
||||
endif() #git
|
||||
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)
|
||||
set(GIT_BRANCH "${gb}")
|
||||
message(STATUS gb: ${GIT_BRANCH})
|
||||
add_definitions(-DGIT_BRANCH="${GIT_BRANCH}")
|
||||
endif()
|
||||
endif() # git
|
||||
|
||||
# make SOURCE_ROOT_PATH define available for logging
|
||||
set(SOURCE_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/src/")
|
||||
add_definitions(-DSOURCE_ROOT_PATH="${SOURCE_ROOT_PATH}")
|
||||
|
||||
# BEAST_ENHANCED_LOGGING - adds file:line numbers and formatting to logs
|
||||
# Automatically enabled for Debug builds via generator expression
|
||||
# Can be explicitly controlled with -DBEAST_ENHANCED_LOGGING=ON/OFF
|
||||
option(BEAST_ENHANCED_LOGGING "Include file and line numbers in log messages (auto: Debug=ON, Release=OFF)" OFF)
|
||||
# Automatically enabled for Debug builds via generator expression Can be
|
||||
# explicitly controlled with -DBEAST_ENHANCED_LOGGING=ON/OFF
|
||||
option(
|
||||
BEAST_ENHANCED_LOGGING
|
||||
"Include file and line numbers in log messages (auto: Debug=ON, Release=OFF)"
|
||||
OFF)
|
||||
message(STATUS "BEAST_ENHANCED_LOGGING option: ${BEAST_ENHANCED_LOGGING}")
|
||||
|
||||
if(thread_safety_analysis)
|
||||
add_compile_options(-Wthread-safety -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS -DRIPPLE_ENABLE_THREAD_SAFETY_ANNOTATIONS)
|
||||
add_compile_options(
|
||||
-Wthread-safety -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
|
||||
-DRIPPLE_ENABLE_THREAD_SAFETY_ANNOTATIONS)
|
||||
add_compile_options("-stdlib=libc++")
|
||||
add_link_options("-stdlib=libc++")
|
||||
endif()
|
||||
@@ -74,55 +73,58 @@ option(USE_CONAN "Use Conan package manager for dependencies" OFF)
|
||||
if(CMAKE_TOOLCHAIN_FILE)
|
||||
# Check if the toolchain file path contains "conan_toolchain"
|
||||
if(CMAKE_TOOLCHAIN_FILE MATCHES "conan_toolchain")
|
||||
set(USE_CONAN ON CACHE BOOL "Using Conan detected from toolchain file" FORCE)
|
||||
set(USE_CONAN
|
||||
ON
|
||||
CACHE BOOL "Using Conan detected from toolchain file" FORCE)
|
||||
message(STATUS "Conan toolchain detected: ${CMAKE_TOOLCHAIN_FILE}")
|
||||
message(STATUS "Building with Conan dependencies")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
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")
|
||||
endif ()
|
||||
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"
|
||||
)
|
||||
endif()
|
||||
|
||||
include(RippledSanity)
|
||||
include(RippledVersion)
|
||||
include(RippledSettings)
|
||||
|
||||
# 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?")
|
||||
# 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 ()
|
||||
endif ()
|
||||
return()
|
||||
endif()
|
||||
include(RippledCompiler)
|
||||
include(RippledInterface)
|
||||
|
||||
include(deps/Boost)
|
||||
find_package(OpenSSL 1.1.1 REQUIRED)
|
||||
set_target_properties(OpenSSL::SSL PROPERTIES
|
||||
INTERFACE_COMPILE_DEFINITIONS OPENSSL_NO_SSL2
|
||||
)
|
||||
set_target_properties(OpenSSL::SSL PROPERTIES INTERFACE_COMPILE_DEFINITIONS
|
||||
OPENSSL_NO_SSL2)
|
||||
set(SECP256K1_INSTALL TRUE)
|
||||
set(SECP256K1_BUILD_BENCHMARK FALSE)
|
||||
set(SECP256K1_BUILD_TESTS FALSE)
|
||||
set(SECP256K1_BUILD_EXHAUSTIVE_TESTS FALSE)
|
||||
set(SECP256K1_BUILD_CTIME_TESTS FALSE)
|
||||
set(SECP256K1_BUILD_EXAMPLES FALSE)
|
||||
add_subdirectory(external/secp256k1)
|
||||
add_library(secp256k1::secp256k1 ALIAS secp256k1)
|
||||
add_subdirectory(external/ed25519-donna)
|
||||
add_subdirectory(external/antithesis-sdk)
|
||||
find_package(gRPC REQUIRED)
|
||||
find_package(lz4 REQUIRED)
|
||||
# Target names with :: are not allowed in a generator expression.
|
||||
# We need to pull the include directories and imported location properties
|
||||
# from separate targets.
|
||||
# Target names with :: are not allowed in a generator expression. We need to
|
||||
# pull the include directories and imported location properties from separate
|
||||
# targets.
|
||||
find_package(LibArchive REQUIRED)
|
||||
find_package(SOCI REQUIRED)
|
||||
find_package(SQLite3 REQUIRED)
|
||||
@@ -130,9 +132,9 @@ find_package(SQLite3 REQUIRED)
|
||||
option(rocksdb "Enable RocksDB" ON)
|
||||
if(rocksdb)
|
||||
find_package(RocksDB REQUIRED)
|
||||
set_target_properties(RocksDB::rocksdb PROPERTIES
|
||||
INTERFACE_COMPILE_DEFINITIONS RIPPLE_ROCKSDB_AVAILABLE=1
|
||||
)
|
||||
set_target_properties(
|
||||
RocksDB::rocksdb PROPERTIES INTERFACE_COMPILE_DEFINITIONS
|
||||
RIPPLE_ROCKSDB_AVAILABLE=1)
|
||||
target_link_libraries(ripple_libs INTERFACE RocksDB::rocksdb)
|
||||
endif()
|
||||
|
||||
@@ -141,8 +143,12 @@ find_package(date REQUIRED)
|
||||
find_package(xxHash REQUIRED)
|
||||
find_package(magic_enum REQUIRED)
|
||||
|
||||
include(deps/WasmEdge)
|
||||
if(TARGET nudb::core)
|
||||
include(deps/WasmEdge)
|
||||
if(xrpld)
|
||||
include(deps/Wasmtime)
|
||||
include(QuickJSProvider)
|
||||
endif()
|
||||
if(TARGET nudb::core)
|
||||
set(nudb nudb::core)
|
||||
elseif(TARGET NuDB::nudb)
|
||||
set(nudb NuDB::nudb)
|
||||
@@ -151,16 +157,16 @@ else()
|
||||
endif()
|
||||
target_link_libraries(ripple_libs INTERFACE ${nudb})
|
||||
|
||||
target_link_libraries(ripple_libs INTERFACE
|
||||
ed25519::ed25519
|
||||
LibArchive::LibArchive
|
||||
lz4::lz4
|
||||
OpenSSL::Crypto
|
||||
OpenSSL::SSL
|
||||
secp256k1::secp256k1
|
||||
soci::soci
|
||||
SQLite::SQLite3
|
||||
)
|
||||
target_link_libraries(
|
||||
ripple_libs
|
||||
INTERFACE ed25519::ed25519
|
||||
LibArchive::LibArchive
|
||||
lz4::lz4
|
||||
OpenSSL::Crypto
|
||||
OpenSSL::SSL
|
||||
secp256k1::secp256k1
|
||||
soci::soci
|
||||
SQLite::SQLite3)
|
||||
|
||||
if(coverage)
|
||||
include(RippledCov)
|
||||
@@ -171,8 +177,3 @@ include(RippledCore)
|
||||
include(RippledInstall)
|
||||
include(RippledDocs)
|
||||
include(RippledValidatorKeys)
|
||||
|
||||
if(tests)
|
||||
include(CTest)
|
||||
add_subdirectory(src/tests/libxrpl)
|
||||
endif()
|
||||
|
||||
@@ -7,6 +7,7 @@ We assume you are familiar with the general practice of [making
|
||||
contributions on GitHub][1]. This file includes only special
|
||||
instructions specific to this project.
|
||||
|
||||
|
||||
## Before you start
|
||||
|
||||
In general, contributions should be developed in your personal
|
||||
@@ -27,6 +28,7 @@ your verifying key. Please set up [signature verification][signing].
|
||||
[signing]:
|
||||
https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification
|
||||
|
||||
|
||||
## Major contributions
|
||||
|
||||
If your contribution is a major feature or breaking change, then you
|
||||
@@ -43,6 +45,7 @@ responsibility of the XLS author to update the draft to match the final
|
||||
implementation when its corresponding pull request is merged, unless the
|
||||
author delegates that responsibility to others.
|
||||
|
||||
|
||||
## Before making a pull request
|
||||
|
||||
Changes that alter transaction processing must be guarded by an
|
||||
@@ -72,17 +75,16 @@ Changes should be usually squashed down into a single commit.
|
||||
Some larger or more complicated change sets make more sense,
|
||||
and are easier to review if organized into multiple logical commits.
|
||||
Either way, all commits should fit the following criteria:
|
||||
|
||||
- Changes should be presented in a single commit or a logical
|
||||
* Changes should be presented in a single commit or a logical
|
||||
sequence of commits.
|
||||
Specifically, chronological commits that simply
|
||||
reflect the history of how the author implemented
|
||||
the change, "warts and all", are not useful to
|
||||
reviewers.
|
||||
- Every commit should have a [good message](#good-commit-messages).
|
||||
* Every commit should have a [good message](#good-commit-messages).
|
||||
to explain a specific aspects of the change.
|
||||
- Every commit should be signed.
|
||||
- Every commit should be well-formed (builds successfully,
|
||||
* Every commit should be signed.
|
||||
* Every commit should be well-formed (builds successfully,
|
||||
unit tests passing), as this helps to resolve merge
|
||||
conflicts, and makes it easier to use `git bisect`
|
||||
to find bugs.
|
||||
@@ -94,14 +96,13 @@ Refer to
|
||||
for general rules on writing a good commit message.
|
||||
|
||||
tl;dr
|
||||
|
||||
> 1. Separate subject from body with a blank line.
|
||||
> 2. Limit the subject line to 50 characters.
|
||||
> - [...]shoot for 50 characters, but consider 72 the hard limit.
|
||||
> * [...]shoot for 50 characters, but consider 72 the hard limit.
|
||||
> 3. Capitalize the subject line.
|
||||
> 4. Do not end the subject line with a period.
|
||||
> 5. Use the imperative mood in the subject line.
|
||||
> - A properly formed Git commit subject line should always be able
|
||||
> * A properly formed Git commit subject line should always be able
|
||||
> to complete the following sentence: "If applied, this commit will
|
||||
> _your subject line here_".
|
||||
> 6. Wrap the body at 72 characters.
|
||||
@@ -109,17 +110,16 @@ tl;dr
|
||||
|
||||
In addition to those guidelines, please add one of the following
|
||||
prefixes to the subject line if appropriate.
|
||||
|
||||
- `fix:` - The primary purpose is to fix an existing bug.
|
||||
- `perf:` - The primary purpose is performance improvements.
|
||||
- `refactor:` - The changes refactor code without affecting
|
||||
* `fix:` - The primary purpose is to fix an existing bug.
|
||||
* `perf:` - The primary purpose is performance improvements.
|
||||
* `refactor:` - The changes refactor code without affecting
|
||||
functionality.
|
||||
- `test:` - The changes _only_ affect unit tests.
|
||||
- `docs:` - The changes _only_ affect documentation. This can
|
||||
* `test:` - The changes _only_ affect unit tests.
|
||||
* `docs:` - The changes _only_ affect documentation. This can
|
||||
include code comments in addition to `.md` files like this one.
|
||||
- `build:` - The changes _only_ affect the build process,
|
||||
* `build:` - The changes _only_ affect the build process,
|
||||
including CMake and/or Conan settings.
|
||||
- `chore:` - Other tasks that don't affect the binary, but don't fit
|
||||
* `chore:` - Other tasks that don't affect the binary, but don't fit
|
||||
any of the other cases. e.g. formatting, git settings, updating
|
||||
Github Actions jobs.
|
||||
|
||||
@@ -169,11 +169,11 @@ meets a few criteria:
|
||||
2. All CI checks must be complete and passed. (One-off failures may
|
||||
be acceptable if they are related to a known issue.)
|
||||
3. The PR must have a [good commit message](#good-commit-messages).
|
||||
- If the PR started with a good commit message, and it doesn't
|
||||
* If the PR started with a good commit message, and it doesn't
|
||||
need to be updated, the author can indicate that in a comment.
|
||||
- Any contributor, preferably the author, can leave a comment
|
||||
* Any contributor, preferably the author, can leave a comment
|
||||
suggesting a commit message.
|
||||
- If the author squashes and rebases the code in preparation for
|
||||
* If the author squashes and rebases the code in preparation for
|
||||
merge, they should also ensure the commit message(s) are updated
|
||||
as well.
|
||||
4. The PR branch must be up to date with the base branch (usually
|
||||
@@ -320,6 +320,7 @@ This is a non-exhaustive list of recommended style guidelines. These are
|
||||
not always strictly enforced and serve as a way to keep the codebase
|
||||
coherent rather than a set of _thou shalt not_ commandments.
|
||||
|
||||
|
||||
## Formatting
|
||||
|
||||
All code must conform to `clang-format` version 10,
|
||||
@@ -348,7 +349,6 @@ To download the patch file:
|
||||
5. Commit and push.
|
||||
|
||||
You can install a pre-commit hook to automatically run `clang-format` before every commit:
|
||||
|
||||
```
|
||||
pip3 install pre-commit
|
||||
pre-commit install
|
||||
@@ -379,51 +379,49 @@ locations, where the reporting of contract violations on the Antithesis
|
||||
platform is either not possible or not useful.
|
||||
|
||||
For this reason:
|
||||
|
||||
- The locations where `assert` or `assert(false)` contracts should continue to be used:
|
||||
- `constexpr` functions
|
||||
- unit tests i.e. files under `src/test`
|
||||
- unit tests-related modules (files under `beast/test` and `beast/unit_test`)
|
||||
- Outside of the listed locations, do not use `assert`; use `XRPL_ASSERT` instead,
|
||||
* The locations where `assert` or `assert(false)` contracts should continue to be used:
|
||||
* `constexpr` functions
|
||||
* unit tests i.e. files under `src/test`
|
||||
* unit tests-related modules (files under `beast/test` and `beast/unit_test`)
|
||||
* Outside of the listed locations, do not use `assert`; use `XRPL_ASSERT` instead,
|
||||
giving it unique name, with the short description of the contract.
|
||||
- Outside of the listed locations, do not use `assert(false)`; use
|
||||
* Outside of the listed locations, do not use `assert(false)`; use
|
||||
`UNREACHABLE` instead, giving it unique name, with the description of the
|
||||
condition being violated
|
||||
- The contract name should start with a full name (including scope) of the
|
||||
function, optionally a named lambda, followed by a colon `:` and a brief
|
||||
* The contract name should start with a full name (including scope) of the
|
||||
function, optionally a named lambda, followed by a colon ` : ` and a brief
|
||||
(typically at most five words) description. `UNREACHABLE` contracts
|
||||
can use slightly longer descriptions. If there are multiple overloads of the
|
||||
function, use common sense to balance both brevity and unambiguity of the
|
||||
function name. NOTE: the purpose of name is to provide stable means of
|
||||
unique identification of every contract; for this reason try to avoid elements
|
||||
which can change in some obvious refactors or when reinforcing the condition.
|
||||
- Contract description typically (except for `UNREACHABLE`) should describe the
|
||||
* Contract description typically (except for `UNREACHABLE`) should describe the
|
||||
_expected_ condition, as in "I assert that _expected_ is true".
|
||||
- Contract description for `UNREACHABLE` should describe the _unexpected_
|
||||
* Contract description for `UNREACHABLE` should describe the _unexpected_
|
||||
situation which caused the line to have been reached.
|
||||
- Example good name for an
|
||||
* Example good name for an
|
||||
`UNREACHABLE` macro `"Json::operator==(Value, Value) : invalid type"`; example
|
||||
good name for an `XRPL_ASSERT` macro `"Json::Value::asCString : valid type"`.
|
||||
- Example **bad** name
|
||||
* Example **bad** name
|
||||
`"RFC1751::insert(char* s, int x, int start, int length) : length is greater than or equal zero"`
|
||||
(missing namespace, unnecessary full function signature, description too verbose).
|
||||
Good name: `"ripple::RFC1751::insert : minimum length"`.
|
||||
- In **few** well-justified cases a non-standard name can be used, in which case a
|
||||
* In **few** well-justified cases a non-standard name can be used, in which case a
|
||||
comment should be placed to explain the rationale (example in `contract.cpp`)
|
||||
- Do **not** rename a contract without a good reason (e.g. the name no longer
|
||||
* Do **not** rename a contract without a good reason (e.g. the name no longer
|
||||
reflects the location or the condition being checked)
|
||||
- Do not use `std::unreachable`
|
||||
- Do not put contracts where they can be violated by an external condition
|
||||
* Do not use `std::unreachable`
|
||||
* Do not put contracts where they can be violated by an external condition
|
||||
(e.g. timing, data payload before mandatory validation etc.) as this creates
|
||||
bogus bug reports (and causes crashes of Debug builds)
|
||||
|
||||
## Unit Tests
|
||||
|
||||
To execute all unit tests:
|
||||
|
||||
`rippled --unittest --unittest-jobs=<number of cores>`
|
||||
```rippled --unittest --unittest-jobs=<number of cores>```
|
||||
|
||||
(Note: Using multiple cores on a Mac M1 can cause spurious test failures. The
|
||||
(Note: Using multiple cores on a Mac M1 can cause spurious test failures. The
|
||||
cause is still under investigation. If you observe this problem, try specifying fewer jobs.)
|
||||
|
||||
To run a specific set of test suites:
|
||||
@@ -431,11 +429,10 @@ To run a specific set of test suites:
|
||||
```
|
||||
rippled --unittest TestSuiteName
|
||||
```
|
||||
|
||||
Note: In this example, all tests with prefix `TestSuiteName` will be run, so if
|
||||
`TestSuiteName1` and `TestSuiteName2` both exist, then both tests will run.
|
||||
Alternatively, if the unit test name finds an exact match, it will stop
|
||||
doing partial matches, i.e. if a unit test with a title of `TestSuiteName`
|
||||
`TestSuiteName1` and `TestSuiteName2` both exist, then both tests will run.
|
||||
Alternatively, if the unit test name finds an exact match, it will stop
|
||||
doing partial matches, i.e. if a unit test with a title of `TestSuiteName`
|
||||
exists, then no other unit test will be executed, apart from `TestSuiteName`.
|
||||
|
||||
## Avoid
|
||||
@@ -451,6 +448,7 @@ exists, then no other unit test will be executed, apart from `TestSuiteName`.
|
||||
explanatory comments.
|
||||
8. Importing new libraries unless there is a very good reason to do so.
|
||||
|
||||
|
||||
## Seek to
|
||||
|
||||
9. Extend functionality of existing code rather than creating new code.
|
||||
@@ -465,12 +463,14 @@ exists, then no other unit test will be executed, apart from `TestSuiteName`.
|
||||
14. Provide as many comments as you feel that a competent programmer
|
||||
would need to understand what your code does.
|
||||
|
||||
|
||||
# Maintainers
|
||||
|
||||
Maintainers are ecosystem participants with elevated access to the repository.
|
||||
They are able to push new code, make decisions on when a release should be
|
||||
made, etc.
|
||||
|
||||
|
||||
## Adding and removing
|
||||
|
||||
New maintainers can be proposed by two existing maintainers, subject to a vote
|
||||
@@ -485,6 +485,7 @@ A minimum of 60% agreement and 50% participation are required.
|
||||
The XRP Ledger Foundation will have the ability, for cause, to remove an
|
||||
existing maintainer without a vote.
|
||||
|
||||
|
||||
## Current Maintainers
|
||||
|
||||
* [Richard Holland](https://github.com/RichardAH) (XRPL Labs + INFTF)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
ISC License
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2011, Arthur Britto, David Schwartz, Jed McCaleb, Vinnie Falco, Bob Way, Eric Lombrozo, Nikolaos D. Bougalis, Howard Hinnant.
|
||||
Copyright (c) 2012-2020, the XRP Ledger developers.
|
||||
@@ -15,3 +15,4 @@ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
@@ -5,11 +5,9 @@
|
||||
[Xahau](https://xahau.network/) is a decentralized cryptographic ledger that builds upon the robust foundation of the XRP Ledger. It inherits the XRP Ledger's Byzantine Fault Tolerant consensus algorithm and enhances it with additional features and functionalities. Developers and users familiar with the XRP Ledger will find that most documentation and tutorials available on [xrpl.org](https://xrpl.org) are relevant and applicable to Xahau, including those related to running validators and managing validator keys. For Xahau specific documentation you can visit our [documentation](https://xahau.network/)
|
||||
|
||||
## XAH
|
||||
|
||||
XAH is the public, counterparty-free asset native to Xahau and functions primarily as network gas. Transactions submitted to the Xahau network must supply an appropriate amount of XAH, to be burnt by the network as a fee, in order to be successfully included in a validated ledger. In addition, XAH also acts as a bridge currency within the Xahau DEX. XAH is traded on the open-market and is available for anyone to access. Xahau was created in 2023 with a supply of 600 million units of XAH.
|
||||
|
||||
## xahaud
|
||||
|
||||
The server software that powers Xahau is called `xahaud` and is available in this repository under the permissive [ISC open-source license](LICENSE.md). The `xahaud` server software is written primarily in C++ and runs on a variety of platforms. The `xahaud` server software can run in several modes depending on its configuration.
|
||||
|
||||
### Build from Source
|
||||
|
||||
4716
RELEASENOTES.md
Normal file
4716
RELEASENOTES.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@
|
||||
|
||||
For more details on operating the Xahau server securely, please visit https://docs.xahau.network/infrastructure/building-xahau.
|
||||
|
||||
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
218
bin/physical.sh
Executable file
218
bin/physical.sh
Executable file
@@ -0,0 +1,218 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -o errexit
|
||||
|
||||
marker_base=f62f74da10c5936c64bd16cd509a8b68f1464e41
|
||||
marker_commit=${1:-${marker_base}}
|
||||
|
||||
if [ $(git merge-base ${marker_commit} ${marker_base}) != ${marker_base} ]; then
|
||||
echo "first marker commit not an ancestor: ${marker_commit}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $(git merge-base ${marker_commit} HEAD) != $(git rev-parse --verify ${marker_commit}) ]; then
|
||||
echo "given marker commit not an ancestor: ${marker_commit}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -e Builds/CMake ]; then
|
||||
echo move CMake
|
||||
git mv Builds/CMake cmake
|
||||
git add --update .
|
||||
git commit -m 'Move CMake directory' --author 'Pretty Printer <cpp@ripple.com>'
|
||||
fi
|
||||
|
||||
if [ -e src/ripple ]; then
|
||||
|
||||
echo move protocol buffers
|
||||
mkdir -p include/xrpl
|
||||
if [ -e src/ripple/proto ]; then
|
||||
git mv src/ripple/proto include/xrpl
|
||||
fi
|
||||
|
||||
extract_list() {
|
||||
git show ${marker_commit}:Builds/CMake/RippledCore.cmake | \
|
||||
awk "/END ${1}/ { p = 0 } p && /src\/ripple/; /BEGIN ${1}/ { p = 1 }" | \
|
||||
sed -e 's#src/ripple/##' -e 's#[^a-z]\+$##'
|
||||
}
|
||||
|
||||
move_files() {
|
||||
oldroot="$1"; shift
|
||||
newroot="$1"; shift
|
||||
detail="$1"; shift
|
||||
files=("$@")
|
||||
for file in ${files[@]}; do
|
||||
if [ ! -e ${oldroot}/${file} ]; then
|
||||
continue
|
||||
fi
|
||||
dir=$(dirname ${file})
|
||||
if [ $(basename ${dir}) == 'details' ]; then
|
||||
dir=$(dirname ${dir})
|
||||
fi
|
||||
if [ $(basename ${dir}) == 'impl' ]; then
|
||||
dir="$(dirname ${dir})/${detail}"
|
||||
fi
|
||||
mkdir -p ${newroot}/${dir}
|
||||
git mv ${oldroot}/${file} ${newroot}/${dir}
|
||||
done
|
||||
}
|
||||
|
||||
echo move libxrpl headers
|
||||
files=$(extract_list 'LIBXRPL HEADERS')
|
||||
files+=(
|
||||
basics/SlabAllocator.h
|
||||
|
||||
beast/asio/io_latency_probe.h
|
||||
beast/container/aged_container.h
|
||||
beast/container/aged_container_utility.h
|
||||
beast/container/aged_map.h
|
||||
beast/container/aged_multimap.h
|
||||
beast/container/aged_multiset.h
|
||||
beast/container/aged_set.h
|
||||
beast/container/aged_unordered_map.h
|
||||
beast/container/aged_unordered_multimap.h
|
||||
beast/container/aged_unordered_multiset.h
|
||||
beast/container/aged_unordered_set.h
|
||||
beast/container/detail/aged_associative_container.h
|
||||
beast/container/detail/aged_container_iterator.h
|
||||
beast/container/detail/aged_ordered_container.h
|
||||
beast/container/detail/aged_unordered_container.h
|
||||
beast/container/detail/empty_base_optimization.h
|
||||
beast/core/LockFreeStack.h
|
||||
beast/insight/Collector.h
|
||||
beast/insight/Counter.h
|
||||
beast/insight/CounterImpl.h
|
||||
beast/insight/Event.h
|
||||
beast/insight/EventImpl.h
|
||||
beast/insight/Gauge.h
|
||||
beast/insight/GaugeImpl.h
|
||||
beast/insight/Group.h
|
||||
beast/insight/Groups.h
|
||||
beast/insight/Hook.h
|
||||
beast/insight/HookImpl.h
|
||||
beast/insight/Insight.h
|
||||
beast/insight/Meter.h
|
||||
beast/insight/MeterImpl.h
|
||||
beast/insight/NullCollector.h
|
||||
beast/insight/StatsDCollector.h
|
||||
beast/test/fail_counter.h
|
||||
beast/test/fail_stream.h
|
||||
beast/test/pipe_stream.h
|
||||
beast/test/sig_wait.h
|
||||
beast/test/string_iostream.h
|
||||
beast/test/string_istream.h
|
||||
beast/test/string_ostream.h
|
||||
beast/test/test_allocator.h
|
||||
beast/test/yield_to.h
|
||||
beast/utility/hash_pair.h
|
||||
beast/utility/maybe_const.h
|
||||
beast/utility/temp_dir.h
|
||||
|
||||
# included by only json/impl/json_assert.h
|
||||
json/json_errors.h
|
||||
|
||||
protocol/PayChan.h
|
||||
protocol/RippleLedgerHash.h
|
||||
protocol/messages.h
|
||||
protocol/st.h
|
||||
)
|
||||
files+=(
|
||||
basics/README.md
|
||||
crypto/README.md
|
||||
json/README.md
|
||||
protocol/README.md
|
||||
resource/README.md
|
||||
)
|
||||
move_files src/ripple include/xrpl detail ${files[@]}
|
||||
|
||||
echo move libxrpl sources
|
||||
files=$(extract_list 'LIBXRPL SOURCES')
|
||||
move_files src/ripple src/libxrpl "" ${files[@]}
|
||||
|
||||
echo check leftovers
|
||||
dirs=$(cd include/xrpl; ls -d */)
|
||||
dirs=$(cd src/ripple; ls -d ${dirs} 2>/dev/null || true)
|
||||
files="$(cd src/ripple; find ${dirs} -type f)"
|
||||
if [ -n "${files}" ]; then
|
||||
echo "leftover files:"
|
||||
echo ${files}
|
||||
exit
|
||||
fi
|
||||
|
||||
echo remove empty directories
|
||||
empty_dirs="$(cd src/ripple; find ${dirs} -depth -type d)"
|
||||
for dir in ${empty_dirs[@]}; do
|
||||
if [ -e ${dir} ]; then
|
||||
rmdir ${dir}
|
||||
fi
|
||||
done
|
||||
|
||||
echo move xrpld sources
|
||||
files=$(
|
||||
extract_list 'XRPLD SOURCES'
|
||||
cd src/ripple
|
||||
find * -regex '.*\.\(h\|ipp\|md\|pu\|uml\|png\)'
|
||||
)
|
||||
move_files src/ripple src/xrpld detail ${files[@]}
|
||||
|
||||
files="$(cd src/ripple; find . -type f)"
|
||||
if [ -n "${files}" ]; then
|
||||
echo "leftover files:"
|
||||
echo ${files}
|
||||
exit
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
rm -rf src/ripple
|
||||
|
||||
echo rename .hpp to .h
|
||||
find include src -name '*.hpp' -exec bash -c 'f="{}"; git mv "${f}" "${f%hpp}h"' \;
|
||||
|
||||
echo move PerfLog.h
|
||||
if [ -e include/xrpl/basics/PerfLog.h ]; then
|
||||
git mv include/xrpl/basics/PerfLog.h src/xrpld/perflog
|
||||
fi
|
||||
|
||||
# Make sure all protobuf includes have the correct prefix.
|
||||
protobuf_replace='s:^#include\s*["<].*org/xrpl\([^">]\+\)[">]:#include <xrpl/proto/org/xrpl\1>:'
|
||||
# Make sure first-party includes use angle brackets and .h extension.
|
||||
ripple_replace='s:include\s*["<]ripple/\(.*\)\.h\(pp\)\?[">]:include <ripple/\1.h>:'
|
||||
beast_replace='s:include\s*<beast/:include <xrpl/beast/:'
|
||||
# Rename impl directories to detail.
|
||||
impl_rename='s:\(<xrpl.*\)/impl\(/details\)\?/:\1/detail/:'
|
||||
|
||||
echo rewrite includes in libxrpl
|
||||
find include/xrpl src/libxrpl -type f -exec sed -i \
|
||||
-e "${protobuf_replace}" \
|
||||
-e "${ripple_replace}" \
|
||||
-e "${beast_replace}" \
|
||||
-e 's:^#include <ripple/:#include <xrpl/:' \
|
||||
-e "${impl_rename}" \
|
||||
{} +
|
||||
|
||||
echo rewrite includes in xrpld
|
||||
# # https://www.baeldung.com/linux/join-multiple-lines
|
||||
libxrpl_dirs="$(cd include/xrpl; ls -d1 */ | sed 's:/$::')"
|
||||
# libxrpl_dirs='a\nb\nc\n'
|
||||
readarray -t libxrpl_dirs <<< "${libxrpl_dirs}"
|
||||
# libxrpl_dirs=(a b c)
|
||||
libxrpl_dirs=$(printf -v txt '%s\\|' "${libxrpl_dirs[@]}"; echo "${txt%\\|}")
|
||||
# libxrpl_dirs='a\|b\|c'
|
||||
find src/xrpld src/test -type f -exec sed -i \
|
||||
-e "${protobuf_replace}" \
|
||||
-e "${ripple_replace}" \
|
||||
-e "${beast_replace}" \
|
||||
-e "s:^#include <ripple/basics/PerfLog.h>:#include <xrpld/perflog/PerfLog.h>:" \
|
||||
-e "s:^#include <ripple/\(${libxrpl_dirs}\)/:#include <xrpl/\1/:" \
|
||||
-e 's:^#include <ripple/:#include <xrpld/:' \
|
||||
-e "${impl_rename}" \
|
||||
{} +
|
||||
|
||||
git commit -m 'Rearrange sources' --author 'Pretty Printer <cpp@ripple.com>'
|
||||
find include src -type f \( -name '*.cpp' -o -name '*.h' -o -name '*.ipp' \) -exec clang-format-10 -i {} +
|
||||
git add --update .
|
||||
git commit -m 'Rewrite includes' --author 'Pretty Printer <cpp@ripple.com>'
|
||||
./Builds/levelization/levelization.sh
|
||||
git add --update .
|
||||
git commit -m 'Recompute loops' --author 'Pretty Printer <cpp@ripple.com>'
|
||||
148
bin/update-jshookz-snapshot
Executable file
148
bin/update-jshookz-snapshot
Executable file
@@ -0,0 +1,148 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Build and import one committed jshookz provider snapshot into Xahau."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
SNAPSHOT_FILES = (
|
||||
"jshookz_provider.manifest.cmake",
|
||||
"jshookz_provider.manifest.json",
|
||||
"jshookz_provider.native-abi.json",
|
||||
"jshookz_provider.wasm",
|
||||
)
|
||||
API_SNAPSHOT_FILES = {
|
||||
"python/jshookz/src/jshookz/types/api-artifacts.json": "api-artifacts.json",
|
||||
"python/jshookz/src/jshookz/types/hooks-api.d.ts": "hooks-api.d.ts",
|
||||
"python/jshookz/src/jshookz/types/xahau-quickjs-v1.d.ts":
|
||||
"xahau-quickjs-v1.d.ts",
|
||||
"python/jshookz/src/jshookz/types/xahau-quickjs-v1.surface.json":
|
||||
"xahau-quickjs-v1.surface.json",
|
||||
}
|
||||
|
||||
|
||||
def run(*args: str, cwd: Path, capture: bool = False) -> str:
|
||||
completed = subprocess.run(
|
||||
args,
|
||||
cwd=cwd,
|
||||
check=True,
|
||||
text=True,
|
||||
stdout=subprocess.PIPE if capture else None,
|
||||
)
|
||||
return completed.stdout.strip() if capture else ""
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(
|
||||
description=(
|
||||
"Build a committed jshookz checkout and copy its sealed "
|
||||
"provider lock into Xahau. CI tracks jshookz main; the lock "
|
||||
"is what must match."
|
||||
)
|
||||
)
|
||||
parser.add_argument("jshookz_checkout", type=Path)
|
||||
parser.add_argument(
|
||||
"--no-build",
|
||||
action="store_true",
|
||||
help="import an already-built build/xahau-provider bundle",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
xahau_root = Path(__file__).resolve().parents[1]
|
||||
jshookz_root = args.jshookz_checkout.expanduser().resolve()
|
||||
cli = next(
|
||||
(
|
||||
candidate
|
||||
for candidate in (
|
||||
jshookz_root / "python/jshookz/.venv/bin/jshookz",
|
||||
jshookz_root / "packages/jshookz/.venv/bin/jshookz",
|
||||
)
|
||||
if candidate.is_file()
|
||||
),
|
||||
None,
|
||||
)
|
||||
if cli is None:
|
||||
parser.error(
|
||||
"missing jshookz CLI under python/jshookz/.venv or "
|
||||
"packages/jshookz/.venv"
|
||||
)
|
||||
bundle = jshookz_root / "build/xahau-provider"
|
||||
destination = xahau_root / "external/quickjs-provider"
|
||||
|
||||
dirty = run(
|
||||
"git",
|
||||
"status",
|
||||
"--porcelain",
|
||||
"--untracked-files=no",
|
||||
cwd=jshookz_root,
|
||||
capture=True,
|
||||
)
|
||||
if dirty:
|
||||
parser.error(
|
||||
"jshookz checkout has uncommitted tracked changes; commit them "
|
||||
"before creating a pinned snapshot"
|
||||
)
|
||||
|
||||
commit = run("git", "rev-parse", "HEAD", cwd=jshookz_root, capture=True)
|
||||
if not args.no_build:
|
||||
run(str(cli), "build", "provider", cwd=jshookz_root)
|
||||
|
||||
missing = [name for name in SNAPSHOT_FILES if not (bundle / name).is_file()]
|
||||
missing.extend(
|
||||
source for source in API_SNAPSHOT_FILES if not (jshookz_root / source).is_file()
|
||||
)
|
||||
if missing:
|
||||
parser.error(f"incomplete provider bundle: {', '.join(missing)}")
|
||||
|
||||
for name in SNAPSHOT_FILES:
|
||||
shutil.copy2(bundle / name, destination / name)
|
||||
for source, name in API_SNAPSHOT_FILES.items():
|
||||
shutil.copy2(jshookz_root / source, destination / name)
|
||||
|
||||
manifest = json.loads((bundle / "jshookz_provider.manifest.json").read_text())
|
||||
wasi_sdk = os.environ.get("HOOKZ_WASI_SDK")
|
||||
if not wasi_sdk:
|
||||
try:
|
||||
wasi_sdk = str(
|
||||
Path(
|
||||
run(
|
||||
"mise",
|
||||
"where",
|
||||
"wasi-sdk",
|
||||
cwd=jshookz_root,
|
||||
capture=True,
|
||||
)
|
||||
)
|
||||
/ "wasi-sdk"
|
||||
)
|
||||
except (FileNotFoundError, subprocess.CalledProcessError):
|
||||
wasi_sdk = "/path/to/wasi-sdk"
|
||||
|
||||
print(f"jshookz commit: {commit}")
|
||||
print(f"provider sha256: {manifest['provider']['sha256']}")
|
||||
print(f"bytecode ABI: {manifest['bytecode_abi_id']}")
|
||||
print(f"runtime profile: {manifest['runtime_profile_id']}")
|
||||
print("snapshot imported; regenerate fixtures and run the focused suite with:")
|
||||
print(
|
||||
" env "
|
||||
f"JSHOOKZ_HOOK_COMPILER={shlex.quote(f'{cli} compile-hook')} "
|
||||
f"HOOKZ_WASI_SDK={shlex.quote(wasi_sdk)} "
|
||||
f"XAHAU_QJS_PROVIDER_WASM={shlex.quote(str(bundle / 'jshookz_provider.wasm'))} "
|
||||
"XAHAU_REQUIRE_QJS_PROVIDER_TESTS=1 "
|
||||
"x-run-tests --compile-hooks src/test/app/JSHooks_test.cpp "
|
||||
"--build-dir build --ccache -- "
|
||||
"ripple.app.JSHooks,ripple.app.QuickJSHostPolicy,"
|
||||
"ripple.app.HookGuestMemory,ripple.app.HookAPI"
|
||||
)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -111,9 +111,9 @@ fi
|
||||
|
||||
cd ..;
|
||||
|
||||
mv src/libxrpl/net/RegisterSSLCerts.cpp.old src/libxrpl/net/RegisterSSLCerts.cpp;
|
||||
mv src/xrpld/net/detail/RegisterSSLCerts.cpp.old src/xrpld/net/detail/RegisterSSLCerts.cpp;
|
||||
mv cmake/deps/WasmEdge.old cmake/deps/WasmEdge.cmake;
|
||||
rm include/xrpl/net/certs;
|
||||
rm src/certs/certbundle.h;
|
||||
git checkout src/libxrpl/protocol/BuildInfo.cpp;
|
||||
|
||||
echo "END INSIDE CONTAINER - CORE"
|
||||
|
||||
14
build-full.sh
Executable file → Normal file
14
build-full.sh
Executable file → Normal file
@@ -17,10 +17,10 @@ umask 0000
|
||||
####
|
||||
|
||||
cd /io
|
||||
mkdir -p include/xrpl/net/certs
|
||||
curl --silent -k https://raw.githubusercontent.com/RichardAH/rippled-release-builder/main/ca-bundle/certbundle.h -o include/xrpl/net/certs/certbundle.h
|
||||
if [ "$(grep certbundle.h src/libxrpl/net/RegisterSSLCerts.cpp | wc -l)" -eq "0" ]; then
|
||||
cp src/libxrpl/net/RegisterSSLCerts.cpp src/libxrpl/net/RegisterSSLCerts.cpp.old
|
||||
mkdir -p src/certs
|
||||
curl --silent -k https://raw.githubusercontent.com/RichardAH/rippled-release-builder/main/ca-bundle/certbundle.h -o src/certs/certbundle.h
|
||||
if [ "$(grep certbundle.h src/xrpld/net/detail/RegisterSSLCerts.cpp | wc -l)" -eq "0" ]; then
|
||||
cp src/xrpld/net/detail/RegisterSSLCerts.cpp src/xrpld/net/detail/RegisterSSLCerts.cpp.old
|
||||
perl -i -pe "s/^{/{
|
||||
#ifdef EMBEDDED_CA_BUNDLE
|
||||
BIO *cbio = BIO_new_mem_buf(ca_bundle.data(), ca_bundle.size());
|
||||
@@ -60,11 +60,11 @@ if [ "$(grep certbundle.h src/libxrpl/net/RegisterSSLCerts.cpp | wc -l)" -eq "0"
|
||||
BIO_free(cbio);
|
||||
}
|
||||
}
|
||||
#endif/g" src/libxrpl/net/RegisterSSLCerts.cpp &&
|
||||
sed -i "s/#include <xrpl\/net\/RegisterSSLCerts.h>/\0\n#include <xrpl\/net\/certs\/certbundle.h>/g" src/libxrpl/net/RegisterSSLCerts.cpp
|
||||
#endif/g" src/xrpld/net/detail/RegisterSSLCerts.cpp &&
|
||||
sed -i "s/#include <xrpld\/net\/RegisterSSLCerts.h>/\0\n#include <certs\/certbundle.h>/g" src/xrpld/net/detail/RegisterSSLCerts.cpp
|
||||
fi
|
||||
# Environment setup moved to Dockerfile in release-builder.sh
|
||||
source /opt/rh/gcc-toolset-${GCC_TOOLSET_VERSION}/enable
|
||||
source /opt/rh/gcc-toolset-11/enable
|
||||
export PATH=/usr/local/bin:$PATH
|
||||
export CC='/usr/lib64/ccache/gcc' &&
|
||||
export CXX='/usr/lib64/ccache/g++' &&
|
||||
|
||||
@@ -394,8 +394,8 @@
|
||||
# true - enables compression
|
||||
# false - disables compression [default].
|
||||
#
|
||||
# The rippled server can save bandwidth by compressing its peer-to-peer communications,
|
||||
# at a cost of greater CPU usage. If you enable link compression,
|
||||
# The rippled server can save bandwidth by compressing its peer-to-peer communications,
|
||||
# at a cost of greater CPU usage. If you enable link compression,
|
||||
# the server automatically compresses communications with peer servers
|
||||
# that also have link compression enabled.
|
||||
# https://xrpl.org/enable-link-compression.html
|
||||
@@ -1070,7 +1070,7 @@
|
||||
# that xahaud is still in sync with the network,
|
||||
# and that the validated ledger is less than
|
||||
# 'age_threshold_seconds' old. If not, then continue
|
||||
# sleeping for this number of seconds and
|
||||
# sleeping for this number of seconds and
|
||||
# checking until healthy.
|
||||
# Default is 5.
|
||||
#
|
||||
@@ -1172,7 +1172,7 @@
|
||||
# page_size Valid values: integer (MUST be power of 2 between 512 and 65536)
|
||||
# The default is 4096 bytes. This setting determines
|
||||
# the size of a page in the transaction.db file.
|
||||
# See https://www.sqlite.org/pragma.html#pragma_page_size
|
||||
# See https://www.sqlite.org/pragma.html#pragma_page_size
|
||||
# for more details about the available options.
|
||||
#
|
||||
# journal_size_limit Valid values: integer
|
||||
|
||||
@@ -1,3 +1,21 @@
|
||||
macro(group_sources_in source_dir curdir)
|
||||
file(GLOB children RELATIVE ${source_dir}/${curdir}
|
||||
${source_dir}/${curdir}/*)
|
||||
foreach (child ${children})
|
||||
if (IS_DIRECTORY ${source_dir}/${curdir}/${child})
|
||||
group_sources_in(${source_dir} ${curdir}/${child})
|
||||
else()
|
||||
string(REPLACE "/" "\\" groupname ${curdir})
|
||||
source_group(${groupname} FILES
|
||||
${source_dir}/${curdir}/${child})
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
macro(group_sources curdir)
|
||||
group_sources_in(${PROJECT_SOURCE_DIR} ${curdir})
|
||||
endmacro()
|
||||
|
||||
macro (exclude_from_default target_)
|
||||
set_target_properties (${target_} PROPERTIES EXCLUDE_FROM_ALL ON)
|
||||
set_target_properties (${target_} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD ON)
|
||||
|
||||
@@ -98,17 +98,6 @@
|
||||
# 2024-04-03, Bronek Kozicki
|
||||
# - add support for output formats: jacoco, clover, lcov
|
||||
#
|
||||
# 2025-05-12, Jingchen Wu
|
||||
# - add -fprofile-update=atomic to ensure atomic profile generation
|
||||
#
|
||||
# 2025-08-28, Bronek Kozicki
|
||||
# - fix "At least one COMMAND must be given" CMake warning from policy CMP0175
|
||||
#
|
||||
# 2025-09-03, Jingchen Wu
|
||||
# - remove the unused function append_coverage_compiler_flags and append_coverage_compiler_flags_to_target
|
||||
# - add a new function add_code_coverage_to_target
|
||||
# - remove some unused code
|
||||
#
|
||||
# USAGE:
|
||||
#
|
||||
# 1. Copy this file into your cmake modules path.
|
||||
@@ -117,8 +106,10 @@
|
||||
# using a CMake option() to enable it just optionally):
|
||||
# include(CodeCoverage)
|
||||
#
|
||||
# 3. Append necessary compiler flags and linker flags for all supported source files:
|
||||
# add_code_coverage_to_target(<target> <PRIVATE|PUBLIC|INTERFACE>)
|
||||
# 3. Append necessary compiler flags for all supported source files:
|
||||
# append_coverage_compiler_flags()
|
||||
# Or for specific target:
|
||||
# append_coverage_compiler_flags_to_target(YOUR_TARGET_NAME)
|
||||
#
|
||||
# 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og
|
||||
#
|
||||
@@ -207,69 +198,55 @@ endforeach()
|
||||
|
||||
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)")
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(CheckCCompilerFlag)
|
||||
include(CheckLinkerFlag)
|
||||
|
||||
set(COVERAGE_CXX_COMPILER_FLAGS ${COVERAGE_COMPILER_FLAGS})
|
||||
set(COVERAGE_C_COMPILER_FLAGS ${COVERAGE_COMPILER_FLAGS})
|
||||
set(COVERAGE_CXX_LINKER_FLAGS ${COVERAGE_COMPILER_FLAGS})
|
||||
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)
|
||||
set(COVERAGE_CXX_COMPILER_FLAGS "${COVERAGE_CXX_COMPILER_FLAGS} -fprofile-abs-path")
|
||||
set(COVERAGE_CXX_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
|
||||
endif()
|
||||
include(CheckCCompilerFlag)
|
||||
check_c_compiler_flag(-fprofile-abs-path HAVE_c_fprofile_abs_path)
|
||||
if(HAVE_c_fprofile_abs_path)
|
||||
set(COVERAGE_C_COMPILER_FLAGS "${COVERAGE_C_COMPILER_FLAGS} -fprofile-abs-path")
|
||||
set(COVERAGE_C_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
|
||||
endif()
|
||||
|
||||
check_linker_flag(CXX -fprofile-abs-path 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()
|
||||
|
||||
check_linker_flag(C -fprofile-abs-path 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()
|
||||
|
||||
check_cxx_compiler_flag(-fprofile-update=atomic HAVE_cxx_fprofile_update)
|
||||
if(HAVE_cxx_fprofile_update)
|
||||
set(COVERAGE_CXX_COMPILER_FLAGS "${COVERAGE_CXX_COMPILER_FLAGS} -fprofile-update=atomic")
|
||||
endif()
|
||||
|
||||
check_c_compiler_flag(-fprofile-update=atomic HAVE_c_fprofile_update)
|
||||
if(HAVE_c_fprofile_update)
|
||||
set(COVERAGE_C_COMPILER_FLAGS "${COVERAGE_C_COMPILER_FLAGS} -fprofile-update=atomic")
|
||||
endif()
|
||||
|
||||
check_linker_flag(CXX -fprofile-update=atomic HAVE_cxx_linker_fprofile_update)
|
||||
if(HAVE_cxx_linker_fprofile_update)
|
||||
set(COVERAGE_CXX_LINKER_FLAGS "${COVERAGE_CXX_LINKER_FLAGS} -fprofile-update=atomic")
|
||||
endif()
|
||||
|
||||
check_linker_flag(C -fprofile-update=atomic 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()
|
||||
|
||||
set(CMAKE_Fortran_FLAGS_COVERAGE
|
||||
${COVERAGE_COMPILER_FLAGS}
|
||||
CACHE STRING "Flags used by the Fortran compiler during coverage builds."
|
||||
FORCE )
|
||||
set(CMAKE_CXX_FLAGS_COVERAGE
|
||||
${COVERAGE_COMPILER_FLAGS}
|
||||
CACHE STRING "Flags used by the C++ compiler during coverage builds."
|
||||
FORCE )
|
||||
set(CMAKE_C_FLAGS_COVERAGE
|
||||
${COVERAGE_COMPILER_FLAGS}
|
||||
CACHE STRING "Flags used by the C compiler during coverage builds."
|
||||
FORCE )
|
||||
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
""
|
||||
CACHE STRING "Flags used for linking binaries during coverage builds."
|
||||
FORCE )
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
|
||||
""
|
||||
CACHE STRING "Flags used by the shared libraries linker during coverage builds."
|
||||
FORCE )
|
||||
mark_as_advanced(
|
||||
CMAKE_Fortran_FLAGS_COVERAGE
|
||||
CMAKE_CXX_FLAGS_COVERAGE
|
||||
CMAKE_C_FLAGS_COVERAGE
|
||||
CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
|
||||
|
||||
get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY 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)
|
||||
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
|
||||
link_libraries(gcov)
|
||||
endif()
|
||||
|
||||
# Defines a target for running and collection code coverage information
|
||||
# Builds dependencies, runs the given executable and outputs reports.
|
||||
# NOTE! The executable should always have a ZERO as exit code otherwise
|
||||
@@ -455,24 +432,23 @@ function(setup_target_for_coverage_gcovr)
|
||||
|
||||
# Show info where to find the report
|
||||
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||
COMMAND echo
|
||||
COMMAND ;
|
||||
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)
|
||||
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}")
|
||||
function(append_coverage_compiler_flags)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||
message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
|
||||
endfunction() # append_coverage_compiler_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_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
|
||||
# Setup coverage for specific library
|
||||
function(append_coverage_compiler_flags_to_target name)
|
||||
separate_arguments(_flag_list NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}")
|
||||
target_compile_options(${name} PRIVATE ${_flag_list})
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
|
||||
target_link_libraries(${name} PRIVATE gcov)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
928
cmake/GenerateQuickJSProviderBundle.py
Normal file
928
cmake/GenerateQuickJSProviderBundle.py
Normal file
@@ -0,0 +1,928 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Project the sealed QuickJS bundle into one C++ translation unit."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
CHUNK = 64
|
||||
CMAKE_SET = re.compile(r'^set\(XAHAU_QUICKJS_([A-Z0-9_]+) "([^"]*)"\)\s*$')
|
||||
WASM_VALTYPE = {"i32", "i64"}
|
||||
WASM_BYTE = {"i32": "0x7f", "i64": "0x7e"}
|
||||
WASM_STACK_BYTES = 131072
|
||||
WASM_PAGE_BYTES = 65536
|
||||
PROVIDER_MEMORY_MINIMUM_PAGES = 7
|
||||
PROVIDER_MEMORY_MAXIMUM_PAGES = 512
|
||||
PROVIDER_MEMORY_MAX_BYTES = PROVIDER_MEMORY_MAXIMUM_PAGES * WASM_PAGE_BYTES
|
||||
SEALED_MANIFEST_SHA256 = (
|
||||
"1673b27d21063957cece9095cceb7e2dbfa53b6f49a5b7f824a486d7d90b2391"
|
||||
)
|
||||
SEALED_PROVIDER_SHA256 = (
|
||||
"f60ab333acb547e50d7d087960839bd11833cb133d496af98e0b72a1bb3b84df"
|
||||
)
|
||||
SEALED_PROVIDER_SIZE = 1116638
|
||||
SEALED_NATIVE_ABI_SHA256 = (
|
||||
"328ec938dcad875f3bdf25b8d779dd77f3571589818ca9271cb98c64c7018f99"
|
||||
)
|
||||
SEALED_BYTECODE_ABI_ID = (
|
||||
"75ea54f357d397c4b33899e495bb385dad975a43b1c4a7a2cead30474327d33e"
|
||||
)
|
||||
SEALED_RUNTIME_PROFILE_ID = (
|
||||
"29acf12e170436e5ccadfbc118d02a60909f86a88262106652b2f71994b0ea25"
|
||||
)
|
||||
SEALED_WASMTIME_VERSION = "47.0.3"
|
||||
SEALED_HOOK_API_VERSION = 1
|
||||
SEALED_HOST_ADAPTER_POLICY = "xahau-raw-hook-host-v1"
|
||||
SEALED_BROAD_DECLARATION_SHA256 = (
|
||||
"649079b831bc68eff0f440644649a505addafb08a3f5174e4031c8de6aedffa0"
|
||||
)
|
||||
SEALED_EXACT_V1_DECLARATION_SHA256 = (
|
||||
"20881232f0602e35de0fcbb8b5a3c1511606392749a0f79daebb386204f4f4da"
|
||||
)
|
||||
SEALED_SURFACE_SHA256 = (
|
||||
"96a9218bf38abbf1bc9f2839408700d03572e0b065d625263f70477bc32597ac"
|
||||
)
|
||||
SEALED_API_ARTIFACT_MANIFEST_SHA256 = (
|
||||
"95babf622bf5edff76fdcbd9746bad8f1f8b275a3d4bacdc320ff4deae543eba"
|
||||
)
|
||||
API_ARTIFACT_SCHEMA = "jshookz.api-artifacts.v1"
|
||||
SEALED_API_ARTIFACTS = {
|
||||
"python/jshookz/src/jshookz/types/hooks-api.d.ts": (
|
||||
"broad_declaration",
|
||||
"hooks-api.d.ts",
|
||||
SEALED_BROAD_DECLARATION_SHA256,
|
||||
),
|
||||
"python/jshookz/src/jshookz/types/xahau-quickjs-v1.d.ts": (
|
||||
"exact_v1_declaration",
|
||||
"xahau-quickjs-v1.d.ts",
|
||||
SEALED_EXACT_V1_DECLARATION_SHA256,
|
||||
),
|
||||
"python/jshookz/src/jshookz/types/xahau-quickjs-v1.surface.json": (
|
||||
"selected_surface",
|
||||
"xahau-quickjs-v1.surface.json",
|
||||
SEALED_SURFACE_SHA256,
|
||||
),
|
||||
}
|
||||
SEALED_LIMITS = {
|
||||
"host_work_base_per_call": 1,
|
||||
"host_work_budget": 1000000,
|
||||
"host_work_meter": "base-plus-addressed-byte-v1",
|
||||
"host_work_per_addressed_byte": 1,
|
||||
"quickjs_heap_bytes": 16777216,
|
||||
"quickjs_stack_bytes": 65536,
|
||||
"serialized_object_max_bytes": 1048576,
|
||||
"serialized_object_max_fields": 32768,
|
||||
"serialized_object_max_scopes": 32769,
|
||||
"serialized_object_max_depth": 10,
|
||||
"wasmtime_fuel_per_initialization": 5000000,
|
||||
"wasmtime_fuel_per_invocation": 50000000,
|
||||
}
|
||||
SEALED_HOST_WORK_ADDRESSED_LENGTH_INDICES = {
|
||||
"accept": [1],
|
||||
"emit": [1, 3],
|
||||
"hook_account": [1],
|
||||
"ledger_last_hash": [1],
|
||||
"prepare": [1, 3],
|
||||
"rollback": [1],
|
||||
"state": [1, 3],
|
||||
"state_set": [1, 3],
|
||||
"trace": [1, 3],
|
||||
}
|
||||
SEALED_ENGINE_CONFIGURATION = {
|
||||
"consume_fuel": True,
|
||||
"cranelift_nan_canonicalization": True,
|
||||
"wasi": False,
|
||||
"wasm_memory64": False,
|
||||
"wasm_multi_memory": False,
|
||||
"wasm_relaxed_simd": False,
|
||||
"wasm_tail_call": False,
|
||||
"wasm_threads": False,
|
||||
}
|
||||
IMPORT_KEYS = frozenset({"module", "name", "params", "results"})
|
||||
FUNCTION_EXPORT_KEYS = frozenset({"kind", "name", "params", "results"})
|
||||
MEMORY_EXPORT_KEYS = frozenset(
|
||||
{"kind", "name", "minimum_pages", "maximum_pages", "memory64", "shared"}
|
||||
)
|
||||
SURFACE_KEYS = frozenset(
|
||||
{"declaration", "declaration_sha256", "manifest", "schema", "sha256"}
|
||||
)
|
||||
NESTED_SURFACE_KEYS = frozenset({"declaration", "manifest", "schema"})
|
||||
|
||||
|
||||
def _import_row(name: str, params: list[str], results: list[str]) -> dict[str, Any]:
|
||||
return {"module": "env", "name": name, "params": params, "results": results}
|
||||
|
||||
|
||||
def _function_export(name: str, params: list[str], results: list[str]) -> dict[str, Any]:
|
||||
return {"kind": "function", "name": name, "params": params, "results": results}
|
||||
|
||||
|
||||
SEALED_IMPORTS = [
|
||||
_import_row("accept", ["i32", "i32", "i64"], ["i64"]),
|
||||
_import_row("emit", ["i32", "i32", "i32", "i32"], ["i64"]),
|
||||
_import_row("etxn_reserve", ["i32"], ["i64"]),
|
||||
_import_row("hook_account", ["i32", "i32"], ["i64"]),
|
||||
_import_row("ledger_last_hash", ["i32", "i32"], ["i64"]),
|
||||
_import_row("ledger_last_time", [], ["i64"]),
|
||||
_import_row("ledger_seq", [], ["i64"]),
|
||||
_import_row("otxn_type", [], ["i64"]),
|
||||
_import_row("prepare", ["i32", "i32", "i32", "i32"], ["i64"]),
|
||||
_import_row("rollback", ["i32", "i32", "i64"], ["i64"]),
|
||||
_import_row("state", ["i32", "i32", "i32", "i32"], ["i64"]),
|
||||
_import_row("state_set", ["i32", "i32", "i32", "i32"], ["i64"]),
|
||||
_import_row("trace", ["i32", "i32", "i32", "i32", "i32"], ["i64"]),
|
||||
]
|
||||
SEALED_EXPORTS = [
|
||||
_function_export("_initialize", [], []),
|
||||
_function_export("free", ["i32"], []),
|
||||
_function_export("malloc", ["i32"], ["i32"]),
|
||||
{
|
||||
"kind": "memory",
|
||||
"maximum_pages": 512,
|
||||
"memory64": False,
|
||||
"minimum_pages": 7,
|
||||
"name": "memory",
|
||||
"shared": False,
|
||||
},
|
||||
_function_export("qjs_cbak", ["i32", "i32", "i32"], ["i32"]),
|
||||
_function_export("qjs_compile", ["i32", "i32"], ["i32"]),
|
||||
_function_export("qjs_compile_module", ["i32", "i32"], ["i32"]),
|
||||
_function_export("qjs_destroy", [], []),
|
||||
_function_export("qjs_enable_coverage", ["i32"], []),
|
||||
_function_export("qjs_eval", ["i32", "i32"], ["i32"]),
|
||||
_function_export("qjs_eval_bytecode", ["i32", "i32"], ["i32"]),
|
||||
_function_export("qjs_eval_module", ["i32", "i32"], ["i32"]),
|
||||
_function_export("qjs_get_bytecode_len", [], ["i32"]),
|
||||
_function_export("qjs_get_bytecode_ptr", [], ["i32"]),
|
||||
_function_export("qjs_get_result_len", [], ["i32"]),
|
||||
_function_export("qjs_get_result_ptr", [], ["i32"]),
|
||||
_function_export("qjs_hook", ["i32", "i32", "i32"], ["i32"]),
|
||||
_function_export("qjs_init", [], []),
|
||||
_function_export("qjs_set_max_stack_size", ["i32"], []),
|
||||
_function_export("qjs_set_memory_limit", ["i32"], []),
|
||||
_function_export("qjs_set_seed", ["i32"], []),
|
||||
_function_export("qjs_validate_hook_module", ["i32", "i32"], ["i32"]),
|
||||
]
|
||||
|
||||
|
||||
class LockError(ValueError):
|
||||
"""A sealed QuickJS lock identity failed a fail-closed check."""
|
||||
|
||||
|
||||
def quote(value: str) -> str:
|
||||
if not isinstance(value, str) or any(c in value for c in "\n\r"):
|
||||
raise LockError(f"invalid QuickJS policy string: {value!r}")
|
||||
return json.dumps(value)
|
||||
|
||||
|
||||
def parse_cmake(path: Path) -> dict[str, str]:
|
||||
values: dict[str, str] = {}
|
||||
for line in path.read_text().splitlines():
|
||||
match = CMAKE_SET.match(line)
|
||||
if match:
|
||||
values[match.group(1)] = match.group(2)
|
||||
return values
|
||||
|
||||
|
||||
def hex_bytes(value: str) -> str:
|
||||
if len(value) != 64 or any(c not in "0123456789abcdefABCDEF" for c in value):
|
||||
raise LockError(f"QuickJS identity must be 32 hexadecimal bytes: {value!r}")
|
||||
return ", ".join(f"0x{value[i:i + 2]}" for i in range(0, 64, 2))
|
||||
|
||||
|
||||
def require(cmake: dict[str, str], key: str) -> str:
|
||||
if key not in cmake:
|
||||
raise LockError(f"QuickJS cmake projection missing {key}")
|
||||
return cmake[key]
|
||||
|
||||
|
||||
def require_int(cmake: dict[str, str], key: str) -> int:
|
||||
return int(require(cmake, key))
|
||||
|
||||
|
||||
def require_hex(value: object, label: str) -> str:
|
||||
text = str(value).lower()
|
||||
if len(text) != 64 or any(c not in "0123456789abcdef" for c in text):
|
||||
raise LockError(f"{label} is not a SHA-256 hex digest: {value!r}")
|
||||
return text
|
||||
|
||||
|
||||
def require_sealed(actual: object, expected: object, label: str) -> None:
|
||||
if actual != expected:
|
||||
raise LockError(
|
||||
f"{label} disagrees with the sealed F0 table: "
|
||||
f"{actual!r} != {expected!r}"
|
||||
)
|
||||
|
||||
|
||||
def validate_api_artifacts(bundle: Path) -> dict[str, str]:
|
||||
manifest_path = bundle / "api-artifacts.json"
|
||||
manifest = json.loads(manifest_path.read_text())
|
||||
if not isinstance(manifest, dict) or set(manifest) != {"artifacts", "schema"}:
|
||||
raise LockError("API artifact manifest has extra or missing keys")
|
||||
if manifest.get("schema") != API_ARTIFACT_SCHEMA:
|
||||
raise LockError("API artifact manifest schema disagrees with the sealed F0 table")
|
||||
artifacts = manifest.get("artifacts")
|
||||
if not isinstance(artifacts, dict) or set(artifacts) != set(SEALED_API_ARTIFACTS):
|
||||
raise LockError("API artifact manifest file set disagrees with the sealed F0 table")
|
||||
|
||||
identities: dict[str, str] = {}
|
||||
for source_path, artifact in SEALED_API_ARTIFACTS.items():
|
||||
identity_name, local_name, sealed_digest = artifact
|
||||
actual_digest = hashlib.sha256((bundle / local_name).read_bytes()).hexdigest()
|
||||
declared_digest = require_hex(
|
||||
artifacts.get(source_path), f"API artifact {source_path} SHA-256"
|
||||
)
|
||||
if actual_digest != declared_digest:
|
||||
raise LockError(
|
||||
f"API artifact {source_path} disagrees with its manifest digest"
|
||||
)
|
||||
require_sealed(actual_digest, sealed_digest, f"API artifact {source_path}")
|
||||
identities[identity_name] = actual_digest
|
||||
|
||||
actual_manifest = hashlib.sha256(manifest_path.read_bytes()).hexdigest()
|
||||
require_sealed(
|
||||
actual_manifest,
|
||||
SEALED_API_ARTIFACT_MANIFEST_SHA256,
|
||||
"API artifact manifest SHA-256",
|
||||
)
|
||||
identities["api_artifact_manifest"] = actual_manifest
|
||||
return identities
|
||||
|
||||
|
||||
def cpp_bool(value: object) -> str:
|
||||
if value is True:
|
||||
return "true"
|
||||
if value is False:
|
||||
return "false"
|
||||
raise LockError(f"expected JSON boolean, got {value!r}")
|
||||
|
||||
|
||||
def join_types(values: object, label: str) -> str:
|
||||
if not isinstance(values, list) or not all(isinstance(item, str) for item in values):
|
||||
raise LockError(f"{label} is not a list of wasm value types: {values!r}")
|
||||
for item in values:
|
||||
if item not in WASM_VALTYPE:
|
||||
raise LockError(f"{label} has unsupported wasm value type {item!r}")
|
||||
return ",".join(values)
|
||||
|
||||
|
||||
def wasm_signature(params: object, results: object, label: str) -> list[str]:
|
||||
join_types(params, f"{label} params")
|
||||
join_types(results, f"{label} results")
|
||||
assert isinstance(params, list) and isinstance(results, list)
|
||||
return [WASM_BYTE[item] for item in results] + [WASM_BYTE[item] for item in params]
|
||||
|
||||
|
||||
def embed_body(data: bytes | None) -> str:
|
||||
if data is None:
|
||||
return (
|
||||
"std::span<std::uint8_t const>\n"
|
||||
"embeddedQuickJSProvider()\n"
|
||||
"{\n"
|
||||
" return {};\n"
|
||||
"}\n"
|
||||
)
|
||||
lines = []
|
||||
for offset in range(0, len(data), CHUNK):
|
||||
chunk = data[offset : offset + CHUNK]
|
||||
lines.append(' "' + "".join(f"\\x{b:02x}" for b in chunk) + '"')
|
||||
return (
|
||||
"namespace {\n"
|
||||
"\n"
|
||||
"constexpr char const sealedProvider[] =\n"
|
||||
+ "\n".join(lines)
|
||||
+ ";\n"
|
||||
"\n"
|
||||
"static_assert(\n"
|
||||
f" sizeof(sealedProvider) - 1 == {len(data)},\n"
|
||||
' "embedded provider size disagrees with its manifest");\n'
|
||||
"\n"
|
||||
"} // namespace\n"
|
||||
"\n"
|
||||
"std::span<std::uint8_t const>\n"
|
||||
"embeddedQuickJSProvider()\n"
|
||||
"{\n"
|
||||
" return {\n"
|
||||
" reinterpret_cast<std::uint8_t const*>(sealedProvider),\n"
|
||||
" sizeof(sealedProvider) - 1};\n"
|
||||
"}\n"
|
||||
)
|
||||
|
||||
|
||||
def format_export_row(item: dict[str, Any]) -> str:
|
||||
kind = item["kind"]
|
||||
name = item["name"]
|
||||
if kind == "memory":
|
||||
fields = (
|
||||
quote(kind),
|
||||
quote(name),
|
||||
quote(""),
|
||||
quote(""),
|
||||
f"{int(item['minimum_pages'])}U",
|
||||
f"{int(item['maximum_pages'])}U",
|
||||
cpp_bool(item["memory64"]),
|
||||
cpp_bool(item["shared"]),
|
||||
)
|
||||
elif kind == "function":
|
||||
fields = (
|
||||
quote(kind),
|
||||
quote(name),
|
||||
quote(join_types(item["params"], f"export {name} params")),
|
||||
quote(join_types(item["results"], f"export {name} results")),
|
||||
"0U",
|
||||
"0U",
|
||||
"false",
|
||||
"false",
|
||||
)
|
||||
else:
|
||||
raise LockError(f"unsupported provider export kind: {kind!r}")
|
||||
return "{" + ", ".join(fields) + "}"
|
||||
|
||||
|
||||
def require_typed_exports(exports: object, label: str) -> list[dict[str, Any]]:
|
||||
if not isinstance(exports, list) or not all(isinstance(item, dict) for item in exports):
|
||||
raise LockError(f"{label} must be a list of typed export rows")
|
||||
names: list[str] = []
|
||||
memory_rows: list[dict[str, Any]] = []
|
||||
for item in exports:
|
||||
kind = item.get("kind")
|
||||
name = item.get("name")
|
||||
if not isinstance(kind, str) or not isinstance(name, str) or not name:
|
||||
raise LockError(f"{label} row is missing kind/name: {item!r}")
|
||||
if kind == "function":
|
||||
if set(item) != FUNCTION_EXPORT_KEYS:
|
||||
raise LockError(f"{label} function {name} has extra or missing keys")
|
||||
join_types(item.get("params"), f"{label} {name} params")
|
||||
join_types(item.get("results"), f"{label} {name} results")
|
||||
elif kind == "memory":
|
||||
if set(item) != MEMORY_EXPORT_KEYS:
|
||||
raise LockError(f"{label} memory row has extra or missing keys")
|
||||
for key in ("minimum_pages", "maximum_pages"):
|
||||
if not isinstance(item.get(key), int):
|
||||
raise LockError(f"{label} memory row missing integer {key}")
|
||||
if item.get("memory64") is not False or item.get("shared") is not False:
|
||||
raise LockError(
|
||||
f"{label} memory row is not memory64=false / shared=false"
|
||||
)
|
||||
memory_rows.append(item)
|
||||
else:
|
||||
raise LockError(f"{label} has unsupported export kind {kind!r}")
|
||||
names.append(name)
|
||||
if len(names) != len(set(names)):
|
||||
raise LockError(f"{label} contains duplicate export names")
|
||||
if names != sorted(names):
|
||||
raise LockError(f"{label} must be normalized by export name")
|
||||
if len(memory_rows) != 1 or memory_rows[0].get("name") != "memory":
|
||||
raise LockError(f"{label} must export exactly one memory named memory")
|
||||
return exports
|
||||
|
||||
|
||||
def require_typed_imports(imports: object, label: str) -> list[dict[str, Any]]:
|
||||
if not isinstance(imports, list) or not all(isinstance(item, dict) for item in imports):
|
||||
raise LockError(f"{label} must be a list of typed import rows")
|
||||
names: list[str] = []
|
||||
for item in imports:
|
||||
module = item.get("module")
|
||||
name = item.get("name")
|
||||
if not isinstance(module, str) or not isinstance(name, str) or not name:
|
||||
raise LockError(f"{label} row is missing module/name: {item!r}")
|
||||
if set(item) != IMPORT_KEYS:
|
||||
raise LockError(f"{label} {name} has extra or missing keys")
|
||||
wasm_signature(item.get("params"), item.get("results"), f"{label} {name}")
|
||||
names.append(name)
|
||||
if len(names) != len(set(names)):
|
||||
raise LockError(f"{label} contains duplicate import names")
|
||||
return imports
|
||||
|
||||
|
||||
def require_build(build: object, label: str) -> dict[str, Any]:
|
||||
if not isinstance(build, dict):
|
||||
raise LockError(f"{label} is missing build metadata")
|
||||
stack = build.get("wasm_stack_bytes")
|
||||
memory = build.get("wasm_memory_max_bytes")
|
||||
if stack != WASM_STACK_BYTES:
|
||||
raise LockError(
|
||||
f"{label} wasm_stack_bytes is {stack!r}, expected {WASM_STACK_BYTES}"
|
||||
)
|
||||
if memory != PROVIDER_MEMORY_MAX_BYTES:
|
||||
raise LockError(
|
||||
f"{label} wasm_memory_max_bytes is {memory!r}, "
|
||||
f"expected {PROVIDER_MEMORY_MAX_BYTES}"
|
||||
)
|
||||
return build
|
||||
|
||||
|
||||
def cross_compare_int(cmake: dict[str, str], key: str, actual: object, label: str) -> int:
|
||||
expected = require_int(cmake, key)
|
||||
if actual != expected:
|
||||
raise LockError(
|
||||
f"{label} disagrees between JSON ({actual!r}) and CMake {key} ({expected!r})"
|
||||
)
|
||||
return expected
|
||||
|
||||
|
||||
def cross_compare_str(cmake: dict[str, str], key: str, actual: object, label: str) -> str:
|
||||
expected = require(cmake, key)
|
||||
if str(actual) != expected:
|
||||
raise LockError(
|
||||
f"{label} disagrees between JSON ({actual!r}) and CMake {key} ({expected!r})"
|
||||
)
|
||||
return expected
|
||||
|
||||
|
||||
def validate_lock(
|
||||
profile: dict[str, Any],
|
||||
native: dict[str, Any],
|
||||
cmake: dict[str, str],
|
||||
wasmtime_version: str,
|
||||
api_identities: dict[str, str],
|
||||
) -> tuple[list[dict[str, Any]], list[dict[str, Any]], dict[str, Any], str, str, int]:
|
||||
schema = require(cmake, "MANIFEST_SCHEMA")
|
||||
if schema != "xahau.quickjs.runtime-profile-lock.v1" or profile.get("schema") != schema:
|
||||
raise LockError(f"unsupported QuickJS provider manifest schema: {schema}")
|
||||
|
||||
expected_sha = require_hex(require(cmake, "PROVIDER_SHA256"), "CMake provider SHA-256")
|
||||
json_sha = require_hex(profile.get("provider", {}).get("sha256"), "JSON provider SHA-256")
|
||||
if json_sha != expected_sha:
|
||||
raise LockError("provider sha256 disagrees between JSON lock and cmake")
|
||||
require_sealed(expected_sha, SEALED_PROVIDER_SHA256, "provider SHA-256")
|
||||
expected_size = require_int(cmake, "PROVIDER_SIZE")
|
||||
json_size = profile.get("provider", {}).get("size")
|
||||
if json_size != expected_size:
|
||||
raise LockError("provider size disagrees between JSON lock and cmake")
|
||||
require_sealed(expected_size, SEALED_PROVIDER_SIZE, "provider size")
|
||||
|
||||
bytecode = require_hex(require(cmake, "BYTECODE_ABI_ID"), "CMake bytecode ABI")
|
||||
if require_hex(profile.get("bytecode_abi_id"), "JSON bytecode ABI") != bytecode:
|
||||
raise LockError("bytecode ABI disagrees between JSON lock and cmake")
|
||||
require_sealed(bytecode, SEALED_BYTECODE_ABI_ID, "bytecode ABI")
|
||||
runtime_profile = require_hex(
|
||||
require(cmake, "RUNTIME_PROFILE_ID"), "CMake runtime-profile ID"
|
||||
)
|
||||
if require_hex(profile.get("runtime_profile_id"), "JSON runtime-profile ID") != runtime_profile:
|
||||
raise LockError("runtime-profile ID disagrees between JSON lock and cmake")
|
||||
require_sealed(
|
||||
runtime_profile, SEALED_RUNTIME_PROFILE_ID, "runtime-profile ID"
|
||||
)
|
||||
|
||||
pinned_wasmtime = require(cmake, "WASMTIME_VERSION")
|
||||
engine = profile.get("source", {}).get("engine", {})
|
||||
engine_version = engine.get("version")
|
||||
if wasmtime_version != pinned_wasmtime or engine_version != pinned_wasmtime:
|
||||
raise LockError(
|
||||
f"QuickJS provider requires Wasmtime {pinned_wasmtime}, "
|
||||
f"but CMake resolved {wasmtime_version} and JSON has {engine_version!r}"
|
||||
)
|
||||
require_sealed(pinned_wasmtime, SEALED_WASMTIME_VERSION, "Wasmtime version")
|
||||
require_sealed(
|
||||
engine.get("configuration"),
|
||||
SEALED_ENGINE_CONFIGURATION,
|
||||
"Wasmtime engine configuration",
|
||||
)
|
||||
|
||||
limits = profile.get("source", {}).get("limits")
|
||||
if not isinstance(limits, dict):
|
||||
raise LockError("JSON runtime-profile source is missing limits")
|
||||
cross_compare_int(
|
||||
cmake, "SERIALIZED_OBJECT_MAX_BYTES", limits.get("serialized_object_max_bytes"),
|
||||
"serialized_object_max_bytes",
|
||||
)
|
||||
cross_compare_int(
|
||||
cmake, "SERIALIZED_OBJECT_MAX_FIELDS", limits.get("serialized_object_max_fields"),
|
||||
"serialized_object_max_fields",
|
||||
)
|
||||
cross_compare_int(
|
||||
cmake, "SERIALIZED_OBJECT_MAX_SCOPES", limits.get("serialized_object_max_scopes"),
|
||||
"serialized_object_max_scopes",
|
||||
)
|
||||
cross_compare_int(
|
||||
cmake, "SERIALIZED_OBJECT_MAX_DEPTH", limits.get("serialized_object_max_depth"),
|
||||
"serialized_object_max_depth",
|
||||
)
|
||||
for key, expected in SEALED_LIMITS.items():
|
||||
require_sealed(limits.get(key), expected, key)
|
||||
require_sealed(
|
||||
limits.get("host_work_addressed_length_indices"),
|
||||
SEALED_HOST_WORK_ADDRESSED_LENGTH_INDICES,
|
||||
"host_work_addressed_length_indices",
|
||||
)
|
||||
cross_compare_int(cmake, "HEAP_BYTES", limits.get("quickjs_heap_bytes"), "quickjs_heap_bytes")
|
||||
cross_compare_int(cmake, "STACK_BYTES", limits.get("quickjs_stack_bytes"), "quickjs_stack_bytes")
|
||||
cross_compare_int(
|
||||
cmake, "INITIALIZATION_FUEL", limits.get("wasmtime_fuel_per_initialization"),
|
||||
"initialization fuel",
|
||||
)
|
||||
cross_compare_int(
|
||||
cmake, "INVOCATION_FUEL", limits.get("wasmtime_fuel_per_invocation"),
|
||||
"invocation fuel",
|
||||
)
|
||||
cross_compare_int(cmake, "HOST_WORK_BUDGET", limits.get("host_work_budget"), "host_work_budget")
|
||||
cross_compare_int(
|
||||
cmake, "HOST_WORK_BASE_PER_CALL", limits.get("host_work_base_per_call"),
|
||||
"host_work_base_per_call",
|
||||
)
|
||||
cross_compare_int(
|
||||
cmake, "HOST_WORK_PER_ADDRESSED_BYTE", limits.get("host_work_per_addressed_byte"),
|
||||
"host_work_per_addressed_byte",
|
||||
)
|
||||
cross_compare_str(cmake, "HOST_WORK_METER", limits.get("host_work_meter"), "host_work_meter")
|
||||
host_adapter_policy = cross_compare_str(
|
||||
cmake, "HOST_ADAPTER_POLICY",
|
||||
profile.get("source", {}).get("execution", {}).get("host_adapter_policy"),
|
||||
"host_adapter_policy",
|
||||
)
|
||||
require_sealed(
|
||||
host_adapter_policy, SEALED_HOST_ADAPTER_POLICY, "host_adapter_policy"
|
||||
)
|
||||
hook_api_version = cross_compare_int(
|
||||
cmake, "HOOK_API_VERSION",
|
||||
profile.get("source", {}).get("artifact", {}).get("hook_api_version"),
|
||||
"hook_api_version",
|
||||
)
|
||||
require_sealed(hook_api_version, SEALED_HOOK_API_VERSION, "hook_api_version")
|
||||
|
||||
provider = profile.get("provider")
|
||||
source_provider = profile.get("source", {}).get("provider")
|
||||
if not isinstance(provider, dict) or not isinstance(source_provider, dict):
|
||||
raise LockError("JSON lock is missing provider or source.provider")
|
||||
require_build(provider.get("build"), "provider.build")
|
||||
require_build(source_provider.get("build"), "source.provider.build")
|
||||
require_sealed(
|
||||
source_provider.get("forbidden_import_modules"),
|
||||
["wasi_snapshot_preview1"],
|
||||
"forbidden provider import modules",
|
||||
)
|
||||
|
||||
expected_import_count = require_int(cmake, "PROVIDER_IMPORT_COUNT")
|
||||
provider_imports = require_typed_imports(provider.get("imports"), "provider.imports")
|
||||
source_imports = require_typed_imports(
|
||||
source_provider.get("imports"), "source.provider.imports"
|
||||
)
|
||||
native_imports = native.get("selected")
|
||||
if not isinstance(native_imports, list):
|
||||
raise LockError("native ABI snapshot is missing selected imports")
|
||||
if provider_imports != source_imports:
|
||||
raise LockError("provider import signatures disagree between JSON copies")
|
||||
if provider_imports != SEALED_IMPORTS:
|
||||
raise LockError(
|
||||
"provider import signatures disagree with the sealed F0 table"
|
||||
)
|
||||
if (
|
||||
len(provider_imports) != expected_import_count
|
||||
or len(native_imports) != expected_import_count
|
||||
):
|
||||
raise LockError("QuickJS provider/native ABI import counts differ")
|
||||
provider_names = [item["name"] for item in provider_imports]
|
||||
native_names = [item["name"] for item in native_imports]
|
||||
if len(set(provider_names)) != expected_import_count or set(provider_names) != set(
|
||||
native_names
|
||||
):
|
||||
raise LockError("QuickJS provider/native ABI import sets differ")
|
||||
native_by_name = {item["name"]: item for item in native_imports}
|
||||
for item in provider_imports:
|
||||
native_item = native_by_name[item["name"]]
|
||||
expected_sig = wasm_signature(
|
||||
item["params"], item["results"], f"import {item['name']}"
|
||||
)
|
||||
if native_item.get("wasm_signature") != expected_sig:
|
||||
raise LockError(
|
||||
f"import {item['name']} wasm signature disagrees between JSON and native ABI"
|
||||
)
|
||||
|
||||
expected_export_count = require_int(cmake, "PROVIDER_EXPORT_COUNT")
|
||||
provider_exports = require_typed_exports(provider.get("exports"), "provider.exports")
|
||||
allowed_exports = require_typed_exports(
|
||||
source_provider.get("allowed_exports"), "source.provider.allowed_exports"
|
||||
)
|
||||
if len(provider_exports) != expected_export_count:
|
||||
raise LockError("QuickJS provider export count disagrees with its CMake lock")
|
||||
if provider_exports != allowed_exports:
|
||||
raise LockError("provider export signatures disagree between JSON copies")
|
||||
memory = next(item for item in provider_exports if item["kind"] == "memory")
|
||||
if (
|
||||
int(memory["minimum_pages"]) != PROVIDER_MEMORY_MINIMUM_PAGES
|
||||
or int(memory["maximum_pages"]) != PROVIDER_MEMORY_MAXIMUM_PAGES
|
||||
or memory["memory64"] is not False
|
||||
or memory["shared"] is not False
|
||||
):
|
||||
raise LockError(
|
||||
"QuickJS provider memory shape is not min 7 / max 512 / "
|
||||
"memory64=false / shared=false"
|
||||
)
|
||||
if provider_exports != SEALED_EXPORTS:
|
||||
raise LockError(
|
||||
"provider export signatures disagree with the sealed F0 table"
|
||||
)
|
||||
|
||||
surface = profile.get("javascript_surface")
|
||||
nested_surface = profile.get("source", {}).get("javascript_surface")
|
||||
if not isinstance(surface, dict) or not isinstance(nested_surface, dict):
|
||||
raise LockError("JSON lock is missing javascript_surface")
|
||||
if set(surface) != SURFACE_KEYS or set(nested_surface) != NESTED_SURFACE_KEYS:
|
||||
raise LockError("javascript_surface has extra or missing keys")
|
||||
declaration_sha = require_hex(
|
||||
surface.get("declaration_sha256"), "javascript surface declaration SHA-256"
|
||||
)
|
||||
surface_sha = require_hex(surface.get("sha256"), "javascript surface SHA-256")
|
||||
require_sealed(
|
||||
declaration_sha,
|
||||
api_identities["exact_v1_declaration"],
|
||||
"exact-v1 declaration SHA-256",
|
||||
)
|
||||
require_sealed(
|
||||
surface_sha, api_identities["selected_surface"], "selected surface SHA-256"
|
||||
)
|
||||
for key in ("declaration", "manifest", "schema"):
|
||||
if surface.get(key) != nested_surface.get(key):
|
||||
raise LockError(f"javascript_surface.{key} disagrees between JSON copies")
|
||||
|
||||
return (
|
||||
provider_imports,
|
||||
provider_exports,
|
||||
native_imports,
|
||||
declaration_sha,
|
||||
surface_sha,
|
||||
expected_size,
|
||||
)
|
||||
|
||||
|
||||
def render_source(
|
||||
*,
|
||||
provenance: str,
|
||||
cmake: dict[str, str],
|
||||
native: dict[str, Any],
|
||||
provider_imports: list[dict[str, Any]],
|
||||
provider_exports: list[dict[str, Any]],
|
||||
native_imports: list[dict[str, Any]],
|
||||
declaration_sha: str,
|
||||
surface_sha: str,
|
||||
broad_declaration_sha: str,
|
||||
api_artifact_manifest_sha: str,
|
||||
manifest_sha: str,
|
||||
expected_sha: str,
|
||||
expected_size: int,
|
||||
wasm_bytes: bytes | None,
|
||||
actual_native: str,
|
||||
) -> str:
|
||||
provider_names = [item["name"] for item in provider_imports]
|
||||
provider_rows = ",\n ".join(
|
||||
"{"
|
||||
+ ", ".join(
|
||||
(
|
||||
quote(item["module"]),
|
||||
quote(item["name"]),
|
||||
quote(join_types(item["params"], f"import {item['name']} params")),
|
||||
quote(join_types(item["results"], f"import {item['name']} results")),
|
||||
)
|
||||
)
|
||||
+ "}"
|
||||
for item in provider_imports
|
||||
)
|
||||
native_rows = ",\n ".join(
|
||||
"{"
|
||||
+ ", ".join(
|
||||
(
|
||||
quote(item["name"]),
|
||||
quote(item["return_type"]),
|
||||
quote(",".join(item["param_types"])),
|
||||
quote(item["amendment"] or ""),
|
||||
)
|
||||
)
|
||||
+ "}"
|
||||
for item in native_imports
|
||||
)
|
||||
export_rows = ",\n ".join(format_export_row(item) for item in provider_exports)
|
||||
source = native["source"]
|
||||
memory = next(item for item in provider_exports if item["kind"] == "memory")
|
||||
return f"""// Generated by cmake/GenerateQuickJSProviderBundle.py; do not edit.
|
||||
// Source: {provenance}
|
||||
#include <xrpld/app/hook/QuickJSHookRuntime.h>
|
||||
#include <xrpld/app/hook/detail/QuickJSProviderProfile.h>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <span>
|
||||
#include <string_view>
|
||||
|
||||
namespace hook::artifact::generated {{
|
||||
|
||||
std::array<std::uint8_t, 32> const providerSHA256 = {{
|
||||
{hex_bytes(expected_sha)}}};
|
||||
std::array<std::uint8_t, 32> const bytecodeABI = {{
|
||||
{hex_bytes(require(cmake, "BYTECODE_ABI_ID"))}}};
|
||||
std::array<std::uint8_t, 32> const runtimeProfile = {{
|
||||
{hex_bytes(require(cmake, "RUNTIME_PROFILE_ID"))}}};
|
||||
std::string_view const providerManifestSHA256 = {quote(manifest_sha)};
|
||||
std::size_t const providerSize = {expected_size};
|
||||
std::uint16_t const hookApiVersion = {require(cmake, "HOOK_API_VERSION")};
|
||||
std::uint64_t const initializationFuel = {require(cmake, "INITIALIZATION_FUEL")}ULL;
|
||||
std::uint64_t const invocationFuel = {require(cmake, "INVOCATION_FUEL")}ULL;
|
||||
std::string_view const hostWorkMeter = {quote(require(cmake, "HOST_WORK_METER"))};
|
||||
std::uint64_t const hostWorkBudget = {require(cmake, "HOST_WORK_BUDGET")}ULL;
|
||||
std::uint64_t const hostWorkBasePerCall = {require(cmake, "HOST_WORK_BASE_PER_CALL")}ULL;
|
||||
std::uint64_t const hostWorkPerAddressedByte =
|
||||
{require(cmake, "HOST_WORK_PER_ADDRESSED_BYTE")}ULL;
|
||||
std::string_view const hostAdapterPolicy = {quote(require(cmake, "HOST_ADAPTER_POLICY"))};
|
||||
std::uint32_t const heapBytes = {require(cmake, "HEAP_BYTES")}U;
|
||||
std::uint32_t const stackBytes = {require(cmake, "STACK_BYTES")}U;
|
||||
std::uint32_t const wasmStackBytes = {WASM_STACK_BYTES}U;
|
||||
std::uint32_t const serializedObjectMaxBytes =
|
||||
{require(cmake, "SERIALIZED_OBJECT_MAX_BYTES")}U;
|
||||
std::uint32_t const serializedObjectMaxFields =
|
||||
{require(cmake, "SERIALIZED_OBJECT_MAX_FIELDS")}U;
|
||||
std::uint32_t const serializedObjectMaxScopes =
|
||||
{require(cmake, "SERIALIZED_OBJECT_MAX_SCOPES")}U;
|
||||
std::uint32_t const serializedObjectMaxDepth =
|
||||
{require(cmake, "SERIALIZED_OBJECT_MAX_DEPTH")}U;
|
||||
std::uint32_t const providerMemoryMinimumPages = {int(memory["minimum_pages"])}U;
|
||||
std::uint32_t const providerMemoryMaximumPages = {int(memory["maximum_pages"])}U;
|
||||
bool const providerMemory64 = false;
|
||||
bool const providerMemoryShared = false;
|
||||
std::string_view const javascriptBroadDeclarationSHA256 =
|
||||
{quote(broad_declaration_sha)};
|
||||
std::string_view const javascriptExactV1DeclarationSHA256 =
|
||||
{quote(declaration_sha)};
|
||||
std::string_view const javascriptSurfaceSHA256 = {quote(surface_sha)};
|
||||
std::string_view const javascriptAPIArtifactManifestSHA256 =
|
||||
{quote(api_artifact_manifest_sha)};
|
||||
|
||||
namespace {{
|
||||
|
||||
std::string_view const providerImportNames[] = {{
|
||||
{", ".join(quote(name) for name in provider_names)}}};
|
||||
std::string_view const providerExportNames[] = {{
|
||||
{", ".join(quote(item["name"]) for item in provider_exports)}}};
|
||||
ProviderImportSignature const providerImportSignatureData[] = {{
|
||||
{provider_rows}}};
|
||||
ProviderExportSignature const providerExportSignatureData[] = {{
|
||||
{export_rows}}};
|
||||
NativeImportSignature const nativeImportSignatureData[] = {{
|
||||
{native_rows}}};
|
||||
|
||||
}} // namespace
|
||||
|
||||
std::span<std::string_view const> const providerImports{{providerImportNames}};
|
||||
std::span<std::string_view const> const providerExports{{providerExportNames}};
|
||||
std::span<ProviderImportSignature const> const providerImportSignatures{{
|
||||
providerImportSignatureData}};
|
||||
std::span<ProviderExportSignature const> const providerExportSignatures{{
|
||||
providerExportSignatureData}};
|
||||
std::span<NativeImportSignature const> const nativeImportSignatures{{
|
||||
nativeImportSignatureData}};
|
||||
std::string_view const nativeABISourceRepository = {quote(source["repository"])};
|
||||
std::string_view const nativeABISourceCommit = {quote(source["commit"])};
|
||||
std::string_view const nativeABISourcePath = {quote(source["path"])};
|
||||
std::string_view const nativeABISHA256 = {quote(actual_native)};
|
||||
std::size_t const nativeABICatalogueCount = {source["macro_function_count"]};
|
||||
|
||||
}} // namespace hook::artifact::generated
|
||||
|
||||
namespace hook {{
|
||||
|
||||
{embed_body(wasm_bytes)}
|
||||
}} // namespace hook
|
||||
"""
|
||||
|
||||
|
||||
def project_bundle(bundle: Path, wasmtime_version: str, output: Path) -> int:
|
||||
profile_path = bundle / "jshookz_provider.manifest.json"
|
||||
cmake_path = bundle / "jshookz_provider.manifest.cmake"
|
||||
native_path = bundle / "jshookz_provider.native-abi.json"
|
||||
api_manifest_path = bundle / "api-artifacts.json"
|
||||
api_paths = tuple(
|
||||
bundle / local_name
|
||||
for _, local_name, _ in SEALED_API_ARTIFACTS.values()
|
||||
)
|
||||
for path in (profile_path, cmake_path, native_path, api_manifest_path, *api_paths):
|
||||
if not path.is_file():
|
||||
print(f"missing sealed QuickJS bundle file: {path}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
cmake = parse_cmake(cmake_path)
|
||||
actual_manifest = hashlib.sha256(profile_path.read_bytes()).hexdigest()
|
||||
if actual_manifest != require(cmake, "MANIFEST_SHA256"):
|
||||
print(
|
||||
"QuickJS provider JSON manifest does not match its CMake projection",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 1
|
||||
|
||||
actual_native = hashlib.sha256(native_path.read_bytes()).hexdigest()
|
||||
if actual_native != require(cmake, "NATIVE_ABI_SHA256"):
|
||||
print(
|
||||
"QuickJS native ABI snapshot does not match its sealed digest",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 1
|
||||
|
||||
try:
|
||||
profile = json.loads(profile_path.read_text())
|
||||
native = json.loads(native_path.read_text())
|
||||
api_identities = validate_api_artifacts(bundle)
|
||||
(
|
||||
provider_imports,
|
||||
provider_exports,
|
||||
native_imports,
|
||||
declaration_sha,
|
||||
surface_sha,
|
||||
expected_size,
|
||||
) = validate_lock(
|
||||
profile, native, cmake, wasmtime_version, api_identities
|
||||
)
|
||||
require_sealed(
|
||||
actual_manifest, SEALED_MANIFEST_SHA256, "provider manifest SHA-256"
|
||||
)
|
||||
require_sealed(
|
||||
actual_native, SEALED_NATIVE_ABI_SHA256, "native ABI SHA-256"
|
||||
)
|
||||
except LockError as error:
|
||||
print(str(error), file=sys.stderr)
|
||||
return 1
|
||||
|
||||
wasm_name = require(cmake, "PROVIDER_FILE")
|
||||
wasm_path = bundle / wasm_name
|
||||
expected_sha = require(cmake, "PROVIDER_SHA256").lower()
|
||||
fingerprint = hashlib.sha256()
|
||||
for path in (
|
||||
profile_path,
|
||||
cmake_path,
|
||||
native_path,
|
||||
api_manifest_path,
|
||||
*api_paths,
|
||||
Path(__file__),
|
||||
):
|
||||
fingerprint.update(path.read_bytes())
|
||||
fingerprint.update(wasmtime_version.encode())
|
||||
wasm_bytes: bytes | None = None
|
||||
if wasm_path.is_file():
|
||||
wasm_bytes = wasm_path.read_bytes()
|
||||
digest = hashlib.sha256(wasm_bytes).hexdigest()
|
||||
if digest != expected_sha or len(wasm_bytes) != expected_size:
|
||||
print(
|
||||
"QuickJS provider WASM does not match its generated manifest",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 1
|
||||
fingerprint.update(b"wasm")
|
||||
fingerprint.update(bytes.fromhex(digest))
|
||||
provenance = f"{wasm_path} sha256={digest} size={len(wasm_bytes)}"
|
||||
else:
|
||||
fingerprint.update(b"absent")
|
||||
provenance = "no provider binary was present in the bundle directory"
|
||||
|
||||
stamp_path = output.with_name(output.name + ".stamp")
|
||||
stamp = fingerprint.hexdigest()
|
||||
if output.is_file() and stamp_path.is_file() and stamp_path.read_text() == stamp:
|
||||
return 0
|
||||
|
||||
if wasm_bytes is None:
|
||||
print(
|
||||
f"No QuickJS provider WASM at {wasm_path}; nothing is embedded "
|
||||
"and the daemon will refuse to start",
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
text = render_source(
|
||||
provenance=provenance,
|
||||
cmake=cmake,
|
||||
native=native,
|
||||
provider_imports=provider_imports,
|
||||
provider_exports=provider_exports,
|
||||
native_imports=native_imports,
|
||||
declaration_sha=declaration_sha,
|
||||
surface_sha=surface_sha,
|
||||
broad_declaration_sha=api_identities["broad_declaration"],
|
||||
api_artifact_manifest_sha=api_identities["api_artifact_manifest"],
|
||||
manifest_sha=actual_manifest,
|
||||
expected_sha=expected_sha,
|
||||
expected_size=expected_size,
|
||||
wasm_bytes=wasm_bytes,
|
||||
actual_native=actual_native,
|
||||
)
|
||||
output.parent.mkdir(parents=True, exist_ok=True)
|
||||
output.write_text(text)
|
||||
stamp_path.write_text(stamp)
|
||||
return 0
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--bundle-dir", type=Path, required=True)
|
||||
parser.add_argument("--wasmtime-version", required=True)
|
||||
parser.add_argument("--output", type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
try:
|
||||
return project_bundle(args.bundle_dir, args.wasmtime_version, args.output)
|
||||
except LockError as error:
|
||||
print(str(error), file=sys.stderr)
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
90
cmake/QuickJSProvider.cmake
Normal file
90
cmake/QuickJSProvider.cmake
Normal file
@@ -0,0 +1,90 @@
|
||||
set(XAHAU_QUICKJS_PROVIDER_BUNDLE_DIR
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/external/quickjs-provider"
|
||||
CACHE PATH
|
||||
"Directory containing the sealed QuickJS provider WASM and generated manifests")
|
||||
get_filename_component(XAHAU_QUICKJS_PROVIDER_BUNDLE_DIR
|
||||
"${XAHAU_QUICKJS_PROVIDER_BUNDLE_DIR}"
|
||||
ABSOLUTE
|
||||
BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
set(XAHAU_QUICKJS_PROVIDER_MANIFEST
|
||||
"${XAHAU_QUICKJS_PROVIDER_BUNDLE_DIR}/jshookz_provider.manifest.cmake")
|
||||
set(XAHAU_QUICKJS_PROVIDER_PROFILE_LOCK
|
||||
"${XAHAU_QUICKJS_PROVIDER_BUNDLE_DIR}/jshookz_provider.manifest.json")
|
||||
set(XAHAU_QUICKJS_NATIVE_ABI
|
||||
"${XAHAU_QUICKJS_PROVIDER_BUNDLE_DIR}/jshookz_provider.native-abi.json")
|
||||
set(XAHAU_QUICKJS_API_ARTIFACT_MANIFEST
|
||||
"${XAHAU_QUICKJS_PROVIDER_BUNDLE_DIR}/api-artifacts.json")
|
||||
set(XAHAU_QUICKJS_BROAD_DECLARATION
|
||||
"${XAHAU_QUICKJS_PROVIDER_BUNDLE_DIR}/hooks-api.d.ts")
|
||||
set(XAHAU_QUICKJS_EXACT_V1_DECLARATION
|
||||
"${XAHAU_QUICKJS_PROVIDER_BUNDLE_DIR}/xahau-quickjs-v1.d.ts")
|
||||
set(XAHAU_QUICKJS_SELECTED_SURFACE
|
||||
"${XAHAU_QUICKJS_PROVIDER_BUNDLE_DIR}/xahau-quickjs-v1.surface.json")
|
||||
|
||||
foreach(_bundle_file
|
||||
"${XAHAU_QUICKJS_PROVIDER_MANIFEST}"
|
||||
"${XAHAU_QUICKJS_PROVIDER_PROFILE_LOCK}"
|
||||
"${XAHAU_QUICKJS_NATIVE_ABI}"
|
||||
"${XAHAU_QUICKJS_API_ARTIFACT_MANIFEST}"
|
||||
"${XAHAU_QUICKJS_BROAD_DECLARATION}"
|
||||
"${XAHAU_QUICKJS_EXACT_V1_DECLARATION}"
|
||||
"${XAHAU_QUICKJS_SELECTED_SURFACE}")
|
||||
if(NOT EXISTS "${_bundle_file}")
|
||||
message(FATAL_ERROR
|
||||
"Missing sealed QuickJS provider bundle file: ${_bundle_file}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT DEFINED wasmtime_VERSION_STRING OR wasmtime_VERSION_STRING STREQUAL "")
|
||||
message(FATAL_ERROR
|
||||
"QuickJS provider requires an exact Wasmtime version, but the resolved "
|
||||
"package did not publish one")
|
||||
endif()
|
||||
|
||||
find_program(XAHAU_QUICKJS_PYTHON NAMES python3 python)
|
||||
if(NOT XAHAU_QUICKJS_PYTHON)
|
||||
message(FATAL_ERROR
|
||||
"Python is required to project the sealed QuickJS provider bundle")
|
||||
endif()
|
||||
|
||||
set(XAHAU_QUICKJS_GENERATED_INCLUDE_DIR
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/generated")
|
||||
set(XAHAU_QUICKJS_PROVIDER_VALUES_SOURCE
|
||||
"${XAHAU_QUICKJS_GENERATED_INCLUDE_DIR}/xrpld/app/hook/detail/QuickJSProviderValues.cpp")
|
||||
set(XAHAU_QUICKJS_BUNDLE_SCRIPT
|
||||
"${CMAKE_CURRENT_LIST_DIR}/GenerateQuickJSProviderBundle.py")
|
||||
|
||||
# The gitignored wasm is not a CMake depend (ninja cannot name a missing
|
||||
# file). Refresh on every rippled build; the script no-ops when inputs
|
||||
# including wasm existence/digest are unchanged.
|
||||
add_custom_target(xahau_quickjs_refresh_provider
|
||||
COMMAND
|
||||
"${XAHAU_QUICKJS_PYTHON}"
|
||||
"${XAHAU_QUICKJS_BUNDLE_SCRIPT}"
|
||||
--bundle-dir "${XAHAU_QUICKJS_PROVIDER_BUNDLE_DIR}"
|
||||
--wasmtime-version "${wasmtime_VERSION_STRING}"
|
||||
--output "${XAHAU_QUICKJS_PROVIDER_VALUES_SOURCE}"
|
||||
BYPRODUCTS "${XAHAU_QUICKJS_PROVIDER_VALUES_SOURCE}"
|
||||
DEPENDS
|
||||
"${XAHAU_QUICKJS_PROVIDER_PROFILE_LOCK}"
|
||||
"${XAHAU_QUICKJS_PROVIDER_MANIFEST}"
|
||||
"${XAHAU_QUICKJS_NATIVE_ABI}"
|
||||
"${XAHAU_QUICKJS_API_ARTIFACT_MANIFEST}"
|
||||
"${XAHAU_QUICKJS_BROAD_DECLARATION}"
|
||||
"${XAHAU_QUICKJS_EXACT_V1_DECLARATION}"
|
||||
"${XAHAU_QUICKJS_SELECTED_SURFACE}"
|
||||
"${XAHAU_QUICKJS_BUNDLE_SCRIPT}"
|
||||
COMMENT "Projecting sealed QuickJS provider values"
|
||||
VERBATIM)
|
||||
|
||||
message(STATUS
|
||||
"QuickJS provider values: ${XAHAU_QUICKJS_PROVIDER_VALUES_SOURCE}")
|
||||
|
||||
add_custom_target(xahau_quickjs_lock_mutations
|
||||
COMMAND
|
||||
"${XAHAU_QUICKJS_PYTHON}"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/test_generate_quickjs_provider_bundle.py"
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
COMMENT "Proving sealed QuickJS lock mutation reds"
|
||||
VERBATIM)
|
||||
@@ -12,7 +12,7 @@ if (static OR MSVC)
|
||||
else ()
|
||||
set (Boost_USE_STATIC_RUNTIME OFF)
|
||||
endif ()
|
||||
find_dependency (Boost
|
||||
find_dependency (Boost 1.70
|
||||
COMPONENTS
|
||||
chrono
|
||||
container
|
||||
@@ -52,3 +52,5 @@ if (TARGET ZLIB::ZLIB)
|
||||
set_target_properties(OpenSSL::Crypto PROPERTIES
|
||||
INTERFACE_LINK_LIBRARIES ZLIB::ZLIB)
|
||||
endif ()
|
||||
|
||||
include ("${CMAKE_CURRENT_LIST_DIR}/RippleTargets.cmake")
|
||||
|
||||
@@ -93,16 +93,27 @@ if (MSVC)
|
||||
-errorreport:none
|
||||
-machine:X64)
|
||||
else ()
|
||||
# HACK : because these need to come first, before any warning demotion
|
||||
string (APPEND CMAKE_CXX_FLAGS " -Wall -Wdeprecated")
|
||||
if (wextra)
|
||||
string (APPEND CMAKE_CXX_FLAGS " -Wextra -Wno-unused-parameter")
|
||||
endif ()
|
||||
# not MSVC
|
||||
target_compile_options (common
|
||||
INTERFACE
|
||||
-Wall
|
||||
-Wdeprecated
|
||||
$<$<BOOL:${is_clang}>:-Wno-deprecated-declarations>
|
||||
$<$<BOOL:${wextra}>:-Wextra -Wno-unused-parameter>
|
||||
$<$<BOOL:${werr}>:-Werror>
|
||||
-fstack-protector
|
||||
$<$<COMPILE_LANGUAGE:CXX>:
|
||||
-frtti
|
||||
-Wnon-virtual-dtor
|
||||
>
|
||||
-Wno-sign-compare
|
||||
-Wno-unused-but-set-variable
|
||||
-Wno-char-subscripts
|
||||
-Wno-format
|
||||
-Wno-unused-local-typedefs
|
||||
$<$<BOOL:${is_gcc}>:
|
||||
-Wno-unused-but-set-variable
|
||||
-Wno-deprecated
|
||||
>
|
||||
$<$<NOT:$<CONFIG:Debug>>:-fno-strict-aliasing>
|
||||
# tweak gcc optimization for debug
|
||||
$<$<AND:$<BOOL:${is_gcc}>,$<CONFIG:Debug>>:-O0>
|
||||
|
||||
@@ -85,7 +85,10 @@ include(target_link_modules)
|
||||
|
||||
# Level 01
|
||||
add_module(xrpl beast)
|
||||
target_link_libraries(xrpl.libxrpl.beast PUBLIC xrpl.imports.main)
|
||||
target_link_libraries(xrpl.libxrpl.beast PUBLIC
|
||||
xrpl.imports.main
|
||||
xrpl.libpb
|
||||
)
|
||||
|
||||
# Level 02
|
||||
add_module(xrpl basics)
|
||||
@@ -113,24 +116,9 @@ target_link_libraries(xrpl.libxrpl.protocol PUBLIC
|
||||
add_module(xrpl resource)
|
||||
target_link_libraries(xrpl.libxrpl.resource PUBLIC xrpl.libxrpl.protocol)
|
||||
|
||||
# Level 06
|
||||
add_module(xrpl net)
|
||||
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 ledger)
|
||||
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)
|
||||
@@ -161,8 +149,6 @@ target_link_modules(xrpl PUBLIC
|
||||
protocol
|
||||
resource
|
||||
server
|
||||
net
|
||||
ledger
|
||||
)
|
||||
|
||||
# All headers in libxrpl are in modules.
|
||||
@@ -178,9 +164,6 @@ if(xrpld)
|
||||
add_executable(rippled)
|
||||
if(tests)
|
||||
target_compile_definitions(rippled PUBLIC ENABLE_TESTS)
|
||||
target_compile_definitions(rippled PRIVATE
|
||||
UNIT_TEST_REFERENCE_FEE=${UNIT_TEST_REFERENCE_FEE}
|
||||
)
|
||||
endif()
|
||||
target_include_directories(rippled
|
||||
PRIVATE
|
||||
@@ -191,18 +174,106 @@ if(xrpld)
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/xrpld/*.cpp"
|
||||
)
|
||||
target_sources(rippled PRIVATE ${sources})
|
||||
add_dependencies(rippled xahau_quickjs_refresh_provider)
|
||||
target_sources(rippled PRIVATE "${XAHAU_QUICKJS_PROVIDER_VALUES_SOURCE}")
|
||||
|
||||
if(tests)
|
||||
file(GLOB_RECURSE sources CONFIGURE_DEPENDS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/test/*.cpp"
|
||||
)
|
||||
if(HOOKS_TEST_ONLY OR DEFINED ENV{HOOKS_TEST_ONLY})
|
||||
list(FILTER sources EXCLUDE REGEX "_test\\.cpp$")
|
||||
message(STATUS "HOOKS_TEST_ONLY: excluded *_test.cpp from src/test/")
|
||||
endif()
|
||||
target_sources(rippled PRIVATE ${sources})
|
||||
|
||||
# External Env tests live next to the producer. Point at a directory of
|
||||
# *_test.cpp files (typically jshookz/env-tests). hookz build-test-hooks
|
||||
# must be on PATH. Coverage is not wired here.
|
||||
if(NOT HOOKS_TEST_DIR AND DEFINED ENV{HOOKS_TEST_DIR})
|
||||
set(HOOKS_TEST_DIR $ENV{HOOKS_TEST_DIR})
|
||||
endif()
|
||||
if(NOT HOOKS_SOURCE_DIR AND DEFINED ENV{HOOKS_SOURCE_DIR})
|
||||
set(HOOKS_SOURCE_DIR $ENV{HOOKS_SOURCE_DIR})
|
||||
endif()
|
||||
if(HOOKS_TEST_DIR AND EXISTS "${HOOKS_TEST_DIR}")
|
||||
file(GLOB EXTERNAL_HOOK_TESTS CONFIGURE_DEPENDS
|
||||
"${HOOKS_TEST_DIR}/*_test.cpp"
|
||||
)
|
||||
if(EXTERNAL_HOOK_TESTS)
|
||||
set(_hooks_extra_args "")
|
||||
set(_hooks_source_deps "")
|
||||
if(HOOKS_SOURCE_DIR)
|
||||
foreach(_dir ${HOOKS_SOURCE_DIR})
|
||||
list(APPEND _hooks_extra_args "--hooks-c-dir" "${_dir}")
|
||||
string(REGEX REPLACE "^[^=]+=" "" _hook_dir "${_dir}")
|
||||
if(EXISTS "${_hook_dir}")
|
||||
file(GLOB_RECURSE _hook_dir_deps CONFIGURE_DEPENDS
|
||||
"${_hook_dir}/*.c"
|
||||
"${_hook_dir}/*.h"
|
||||
"${_hook_dir}/*.ts"
|
||||
"${_hook_dir}/*.js"
|
||||
)
|
||||
if(HOOKS_TEST_DIR)
|
||||
list(FILTER _hook_dir_deps EXCLUDE REGEX "^${HOOKS_TEST_DIR}/")
|
||||
endif()
|
||||
list(APPEND _hooks_source_deps ${_hook_dir_deps})
|
||||
endif()
|
||||
endforeach()
|
||||
list(REMOVE_DUPLICATES _hooks_source_deps)
|
||||
endif()
|
||||
set(_hooks_always_run OFF)
|
||||
if(HOOKS_FORCE_RECOMPILE OR DEFINED ENV{HOOKS_FORCE_RECOMPILE})
|
||||
list(APPEND _hooks_extra_args "--force-write" "--no-cache")
|
||||
set(_hooks_always_run ON)
|
||||
message(STATUS "Hook force recompile enabled (cache bypassed)")
|
||||
endif()
|
||||
foreach(_test_file ${EXTERNAL_HOOK_TESTS})
|
||||
get_filename_component(_stem ${_test_file} NAME_WE)
|
||||
set(_hooks_header "${HOOKS_TEST_DIR}/${_stem}_hooks.h")
|
||||
if(_hooks_always_run)
|
||||
add_custom_target(compile_hooks_${_stem} ALL
|
||||
COMMAND hookz build-test-hooks "${_test_file}" ${_hooks_extra_args}
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
COMMENT "Compiling hooks for ${_stem} (forced)"
|
||||
VERBATIM
|
||||
)
|
||||
list(APPEND EXTERNAL_HOOK_TARGETS compile_hooks_${_stem})
|
||||
else()
|
||||
add_custom_command(
|
||||
OUTPUT "${_hooks_header}"
|
||||
COMMAND hookz build-test-hooks "${_test_file}" ${_hooks_extra_args}
|
||||
DEPENDS "${_test_file}" ${_hooks_source_deps}
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
COMMENT "Compiling hooks for ${_stem}"
|
||||
VERBATIM
|
||||
)
|
||||
list(APPEND EXTERNAL_HOOK_HEADERS "${_hooks_header}")
|
||||
endif()
|
||||
endforeach()
|
||||
if(_hooks_always_run)
|
||||
foreach(_tgt ${EXTERNAL_HOOK_TARGETS})
|
||||
add_dependencies(rippled ${_tgt})
|
||||
endforeach()
|
||||
else()
|
||||
add_custom_target(compile_external_hooks DEPENDS ${EXTERNAL_HOOK_HEADERS})
|
||||
add_dependencies(rippled compile_external_hooks)
|
||||
endif()
|
||||
target_sources(rippled PRIVATE ${EXTERNAL_HOOK_TESTS})
|
||||
set_property(
|
||||
SOURCE ${EXTERNAL_HOOK_TESTS}
|
||||
APPEND PROPERTY INCLUDE_DIRECTORIES "${HOOKS_TEST_DIR}"
|
||||
)
|
||||
message(STATUS "Including external hook tests from: ${HOOKS_TEST_DIR}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_link_libraries(rippled
|
||||
Ripple::boost
|
||||
Ripple::opts
|
||||
Ripple::libs
|
||||
wasmtime::wasmtime
|
||||
xrpl.libxrpl
|
||||
# Workaround for a Conan 1.x bug that prevents static linking of libstdc++
|
||||
# when a dependency (snappy) modifies system_libs. See the comment in
|
||||
|
||||
@@ -33,8 +33,6 @@ setup_target_for_coverage_gcovr(
|
||||
FORMAT ${coverage_format}
|
||||
EXECUTABLE rippled
|
||||
EXECUTABLE_ARGS --unittest$<$<BOOL:${coverage_test}>:=${coverage_test}> --unittest-jobs ${coverage_test_parallelism} --quiet --unittest-log
|
||||
EXCLUDE "src/test" "src/tests" "include/xrpl/beast/test" "include/xrpl/beast/unit_test" "${CMAKE_BINARY_DIR}/pb-xrpl.libpb"
|
||||
EXCLUDE "src/test" "include/xrpl/beast/test" "include/xrpl/beast/unit_test" "${CMAKE_BINARY_DIR}/pb-xrpl.libpb"
|
||||
DEPENDENCIES rippled
|
||||
)
|
||||
|
||||
add_code_coverage_to_target(opts INTERFACE)
|
||||
|
||||
@@ -19,9 +19,7 @@ install (
|
||||
xrpl.libxrpl.json
|
||||
xrpl.libxrpl.protocol
|
||||
xrpl.libxrpl.resource
|
||||
xrpl.libxrpl.ledger
|
||||
xrpl.libxrpl.server
|
||||
xrpl.libxrpl.net
|
||||
xrpl.libxrpl
|
||||
antithesis-sdk-cpp
|
||||
EXPORT RippleExports
|
||||
|
||||
@@ -28,11 +28,15 @@ target_compile_options (opts
|
||||
$<$<AND:$<BOOL:${is_gcc}>,$<COMPILE_LANGUAGE:CXX>>:-Wsuggest-override>
|
||||
$<$<BOOL:${is_gcc}>:-Wno-maybe-uninitialized>
|
||||
$<$<BOOL:${perf}>:-fno-omit-frame-pointer>
|
||||
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${coverage}>>:-g --coverage -fprofile-abs-path>
|
||||
$<$<AND:$<BOOL:${is_clang}>,$<BOOL:${coverage}>>:-g --coverage>
|
||||
$<$<BOOL:${profile}>:-pg>
|
||||
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>)
|
||||
|
||||
target_link_libraries (opts
|
||||
INTERFACE
|
||||
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${coverage}>>:-g --coverage -fprofile-abs-path>
|
||||
$<$<AND:$<BOOL:${is_clang}>,$<BOOL:${coverage}>>:-g --coverage>
|
||||
$<$<BOOL:${profile}>:-pg>
|
||||
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>)
|
||||
|
||||
|
||||
@@ -1,8 +1,23 @@
|
||||
#[===================================================================[
|
||||
sanity checks
|
||||
convenience variables and sanity checks
|
||||
#]===================================================================]
|
||||
|
||||
get_property(is_multiconfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
include(ProcessorCount)
|
||||
|
||||
if (NOT ep_procs)
|
||||
ProcessorCount(ep_procs)
|
||||
if (ep_procs GREATER 1)
|
||||
# never use more than half of cores for EP builds
|
||||
math (EXPR ep_procs "${ep_procs} / 2")
|
||||
message (STATUS "Using ${ep_procs} cores for ExternalProject builds.")
|
||||
endif ()
|
||||
endif ()
|
||||
get_property (is_multiconfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
if (is_multiconfig STREQUAL "NOTFOUND")
|
||||
if (${CMAKE_GENERATOR} STREQUAL "Xcode" OR ${CMAKE_GENERATOR} MATCHES "^Visual Studio")
|
||||
set (is_multiconfig TRUE)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
set (CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE)
|
||||
if (NOT is_multiconfig)
|
||||
@@ -16,22 +31,42 @@ if (NOT is_multiconfig)
|
||||
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 ("${CMAKE_CXX_COMPILER_ID}" MATCHES ".*Clang") # both Clang and AppleClang
|
||||
set (is_clang TRUE)
|
||||
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")
|
||||
CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.0)
|
||||
message (FATAL_ERROR "This project requires clang 8 or later")
|
||||
endif ()
|
||||
# TODO min AppleClang version check ?
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
set (is_gcc TRUE)
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0)
|
||||
message (FATAL_ERROR "This project requires GCC 12 or later")
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.0)
|
||||
message (FATAL_ERROR "This project requires GCC 8 or later")
|
||||
endif ()
|
||||
endif ()
|
||||
if (CMAKE_GENERATOR STREQUAL "Xcode")
|
||||
set (is_xcode TRUE)
|
||||
endif ()
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
set (is_linux TRUE)
|
||||
else ()
|
||||
set (is_linux FALSE)
|
||||
endif ()
|
||||
|
||||
if ("$ENV{CI}" STREQUAL "true" OR "$ENV{CONTINUOUS_INTEGRATION}" STREQUAL "true")
|
||||
set (is_ci TRUE)
|
||||
else ()
|
||||
set (is_ci FALSE)
|
||||
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 "
|
||||
|
||||
@@ -1,54 +1,28 @@
|
||||
#[===================================================================[
|
||||
declare options and variables
|
||||
declare user options/settings
|
||||
#]===================================================================]
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
set (is_linux TRUE)
|
||||
else()
|
||||
set(is_linux FALSE)
|
||||
endif()
|
||||
include(ProcessorCount)
|
||||
|
||||
if("$ENV{CI}" STREQUAL "true" OR "$ENV{CONTINUOUS_INTEGRATION}" STREQUAL "true")
|
||||
set(is_ci TRUE)
|
||||
else()
|
||||
set(is_ci FALSE)
|
||||
endif()
|
||||
|
||||
get_directory_property(has_parent PARENT_DIRECTORY)
|
||||
if(has_parent)
|
||||
set(is_root_project OFF)
|
||||
else()
|
||||
set(is_root_project ON)
|
||||
endif()
|
||||
ProcessorCount(PROCESSOR_COUNT)
|
||||
|
||||
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()
|
||||
|
||||
option(unity "Creates a build using UNITY support in cmake." OFF)
|
||||
option(unity "Creates a build using UNITY support in cmake. This is the default" ON)
|
||||
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_gcc OR is_clang)
|
||||
include(ProcessorCount)
|
||||
ProcessorCount(PROCESSOR_COUNT)
|
||||
|
||||
option(coverage "Generates coverage info." OFF)
|
||||
option(profile "Add profiling flags" OFF)
|
||||
set(coverage_test_parallelism "${PROCESSOR_COUNT}" CACHE STRING
|
||||
@@ -68,7 +42,6 @@ else()
|
||||
set(coverage OFF CACHE BOOL "gcc/clang only" FORCE)
|
||||
set(wextra OFF CACHE BOOL "gcc/clang only" FORCE)
|
||||
endif()
|
||||
|
||||
if(is_linux)
|
||||
option(BUILD_SHARED_LIBS "build shared ripple libraries" OFF)
|
||||
option(static "link protobuf, openssl, libc++, and boost statically" ON)
|
||||
@@ -85,13 +58,11 @@ else()
|
||||
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()
|
||||
|
||||
option(jemalloc "Enables jemalloc for heap profiling" OFF)
|
||||
option(werr "treat warnings as errors" OFF)
|
||||
option(local_protobuf
|
||||
@@ -125,6 +96,16 @@ if(san)
|
||||
message(FATAL_ERROR "${san} sanitizer does not seem to be supported by your compiler")
|
||||
endif()
|
||||
endif()
|
||||
set(container_label "" CACHE STRING "tag to use for package building containers")
|
||||
option(packages_only
|
||||
"ONLY generate package building targets. This is special use-case and almost \
|
||||
certainly not what you want. Use with caution as you won't be able to build \
|
||||
any compiled targets locally." OFF)
|
||||
option(have_package_container
|
||||
"Sometimes you already have the tagged container you want to use for package \
|
||||
building and you don't want docker to rebuild it. This flag will detach the \
|
||||
dependency of the package build from the container build. It's an advanced \
|
||||
use case and most likely you should not be touching this flag." OFF)
|
||||
|
||||
# the remaining options are obscure and rarely used
|
||||
option(beast_no_unit_test_inline
|
||||
@@ -138,13 +119,15 @@ option(boost_show_deprecated
|
||||
"Allow boost to fail on deprecated usage. Only useful if you're trying\
|
||||
to find deprecated calls."
|
||||
OFF)
|
||||
option(beast_hashers
|
||||
"Use local implementations for sha/ripemd hashes (experimental, not recommended)"
|
||||
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(coverage)
|
||||
message(STATUS "coverage build requested - forcing Debug build")
|
||||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "build type" FORCE)
|
||||
|
||||
@@ -2,6 +2,7 @@ find_package(Boost 1.86 REQUIRED
|
||||
COMPONENTS
|
||||
chrono
|
||||
container
|
||||
context
|
||||
coroutine
|
||||
date_time
|
||||
filesystem
|
||||
@@ -24,7 +25,7 @@ endif()
|
||||
|
||||
target_link_libraries(ripple_boost
|
||||
INTERFACE
|
||||
Boost::headers
|
||||
Boost::boost
|
||||
Boost::chrono
|
||||
Boost::container
|
||||
Boost::coroutine
|
||||
|
||||
1
cmake/deps/Wasmtime.cmake
Normal file
1
cmake/deps/Wasmtime.cmake
Normal file
@@ -0,0 +1 @@
|
||||
find_package(wasmtime REQUIRED)
|
||||
756
cmake/test_generate_quickjs_provider_bundle.py
Normal file
756
cmake/test_generate_quickjs_provider_bundle.py
Normal file
@@ -0,0 +1,756 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Fail-closed generator/checker mutation reds for the sealed QuickJS lock."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
SCRIPT = Path(__file__).with_name("GenerateQuickJSProviderBundle.py")
|
||||
BUNDLE = ROOT / "external" / "quickjs-provider"
|
||||
WASM_VERSION = "47.0.3"
|
||||
CMAKE_SET = re.compile(r'^set\(XAHAU_QUICKJS_([A-Z0-9_]+) "([^"]*)"\)\s*$')
|
||||
|
||||
PIN = {
|
||||
"provider_sha256": "f60ab333acb547e50d7d087960839bd11833cb133d496af98e0b72a1bb3b84df",
|
||||
"provider_size": "1116638",
|
||||
"manifest_sha256": "1673b27d21063957cece9095cceb7e2dbfa53b6f49a5b7f824a486d7d90b2391",
|
||||
"runtime_profile_id": "29acf12e170436e5ccadfbc118d02a60909f86a88262106652b2f71994b0ea25",
|
||||
"broad_declaration_sha256": "649079b831bc68eff0f440644649a505addafb08a3f5174e4031c8de6aedffa0",
|
||||
"exact_v1_declaration_sha256": "20881232f0602e35de0fcbb8b5a3c1511606392749a0f79daebb386204f4f4da",
|
||||
"surface_sha256": "96a9218bf38abbf1bc9f2839408700d03572e0b065d625263f70477bc32597ac",
|
||||
"api_artifact_manifest_sha256": "95babf622bf5edff76fdcbd9746bad8f1f8b275a3d4bacdc320ff4deae543eba",
|
||||
"bytecode_abi": "75ea54f357d397c4b33899e495bb385dad975a43b1c4a7a2cead30474327d33e",
|
||||
"native_abi": "328ec938dcad875f3bdf25b8d779dd77f3571589818ca9271cb98c64c7018f99",
|
||||
"wasm_stack_bytes": "131072",
|
||||
}
|
||||
|
||||
RECEIPT_B = {
|
||||
"provider_sha256": "40f9ac0203afa9296196c627bc94e669ad789322ddc1e4ab58ba0cf6d32a5e21",
|
||||
"provider_size": "1101461",
|
||||
"runtime_profile_id": "60950ca8b6fe4dd2a35559367051998bc04f75e8aa41934dd4caad0de5a1c3ba",
|
||||
"declaration_sha256": "56b4b2974b8a63a550721abd60350e392990762e76666f050b1a7c810e584957",
|
||||
"surface_sha256": "b112346b95da74d04930ba86bd597e56a428e41e11581804ccc49907ae206eb0",
|
||||
}
|
||||
|
||||
TYPED_IMPORT_ROWS = (
|
||||
'{"env", "accept", "i32,i32,i64", "i64"}',
|
||||
'{"env", "emit", "i32,i32,i32,i32", "i64"}',
|
||||
'{"env", "etxn_reserve", "i32", "i64"}',
|
||||
'{"env", "hook_account", "i32,i32", "i64"}',
|
||||
'{"env", "ledger_last_hash", "i32,i32", "i64"}',
|
||||
'{"env", "ledger_last_time", "", "i64"}',
|
||||
'{"env", "ledger_seq", "", "i64"}',
|
||||
'{"env", "otxn_type", "", "i64"}',
|
||||
'{"env", "prepare", "i32,i32,i32,i32", "i64"}',
|
||||
'{"env", "rollback", "i32,i32,i64", "i64"}',
|
||||
'{"env", "state", "i32,i32,i32,i32", "i64"}',
|
||||
'{"env", "state_set", "i32,i32,i32,i32", "i64"}',
|
||||
'{"env", "trace", "i32,i32,i32,i32,i32", "i64"}',
|
||||
)
|
||||
|
||||
TYPED_EXPORT_ROWS = (
|
||||
'{"function", "_initialize", "", "", 0U, 0U, false, false}',
|
||||
'{"function", "free", "i32", "", 0U, 0U, false, false}',
|
||||
'{"function", "malloc", "i32", "i32", 0U, 0U, false, false}',
|
||||
'{"memory", "memory", "", "", 7U, 512U, false, false}',
|
||||
'{"function", "qjs_cbak", "i32,i32,i32", "i32", 0U, 0U, false, false}',
|
||||
'{"function", "qjs_compile", "i32,i32", "i32", 0U, 0U, false, false}',
|
||||
'{"function", "qjs_compile_module", "i32,i32", "i32", 0U, 0U, false, false}',
|
||||
'{"function", "qjs_destroy", "", "", 0U, 0U, false, false}',
|
||||
'{"function", "qjs_enable_coverage", "i32", "", 0U, 0U, false, false}',
|
||||
'{"function", "qjs_eval", "i32,i32", "i32", 0U, 0U, false, false}',
|
||||
'{"function", "qjs_eval_bytecode", "i32,i32", "i32", 0U, 0U, false, false}',
|
||||
'{"function", "qjs_eval_module", "i32,i32", "i32", 0U, 0U, false, false}',
|
||||
'{"function", "qjs_get_bytecode_len", "", "i32", 0U, 0U, false, false}',
|
||||
'{"function", "qjs_get_bytecode_ptr", "", "i32", 0U, 0U, false, false}',
|
||||
'{"function", "qjs_get_result_len", "", "i32", 0U, 0U, false, false}',
|
||||
'{"function", "qjs_get_result_ptr", "", "i32", 0U, 0U, false, false}',
|
||||
'{"function", "qjs_hook", "i32,i32,i32", "i32", 0U, 0U, false, false}',
|
||||
'{"function", "qjs_init", "", "", 0U, 0U, false, false}',
|
||||
'{"function", "qjs_set_max_stack_size", "i32", "", 0U, 0U, false, false}',
|
||||
'{"function", "qjs_set_memory_limit", "i32", "", 0U, 0U, false, false}',
|
||||
'{"function", "qjs_set_seed", "i32", "", 0U, 0U, false, false}',
|
||||
'{"function", "qjs_validate_hook_module", "i32,i32", "i32", 0U, 0U, false, false}',
|
||||
)
|
||||
|
||||
|
||||
def json_path(bundle: Path) -> Path:
|
||||
return bundle / "jshookz_provider.manifest.json"
|
||||
|
||||
|
||||
def cmake_path(bundle: Path) -> Path:
|
||||
return bundle / "jshookz_provider.manifest.cmake"
|
||||
|
||||
|
||||
def native_path(bundle: Path) -> Path:
|
||||
return bundle / "jshookz_provider.native-abi.json"
|
||||
|
||||
|
||||
def wasm_path(bundle: Path) -> Path:
|
||||
return bundle / "jshookz_provider.wasm"
|
||||
|
||||
|
||||
def api_manifest_path(bundle: Path) -> Path:
|
||||
return bundle / "api-artifacts.json"
|
||||
|
||||
|
||||
def broad_declaration_path(bundle: Path) -> Path:
|
||||
return bundle / "hooks-api.d.ts"
|
||||
|
||||
|
||||
def exact_v1_declaration_path(bundle: Path) -> Path:
|
||||
return bundle / "xahau-quickjs-v1.d.ts"
|
||||
|
||||
|
||||
def surface_path(bundle: Path) -> Path:
|
||||
return bundle / "xahau-quickjs-v1.surface.json"
|
||||
|
||||
|
||||
def load_json(bundle: Path) -> dict:
|
||||
return json.loads(json_path(bundle).read_text())
|
||||
|
||||
|
||||
def write_json(bundle: Path, data: dict) -> None:
|
||||
json_path(bundle).write_text(json.dumps(data, indent=2) + "\n")
|
||||
|
||||
|
||||
def set_cmake(bundle: Path, key: str, value: str) -> None:
|
||||
path = cmake_path(bundle)
|
||||
lines = []
|
||||
replaced = False
|
||||
for line in path.read_text().splitlines():
|
||||
match = CMAKE_SET.match(line)
|
||||
if match and match.group(1) == key:
|
||||
lines.append(f'set(XAHAU_QUICKJS_{key} "{value}")')
|
||||
replaced = True
|
||||
else:
|
||||
lines.append(line)
|
||||
if not replaced:
|
||||
raise AssertionError(f"CMake lock is missing {key}")
|
||||
path.write_text("\n".join(lines) + "\n")
|
||||
|
||||
|
||||
def rehash_manifest(bundle: Path) -> None:
|
||||
digest = hashlib.sha256(json_path(bundle).read_bytes()).hexdigest()
|
||||
set_cmake(bundle, "MANIFEST_SHA256", digest)
|
||||
|
||||
|
||||
def rehash_native(bundle: Path) -> None:
|
||||
digest = hashlib.sha256(native_path(bundle).read_bytes()).hexdigest()
|
||||
set_cmake(bundle, "NATIVE_ABI_SHA256", digest)
|
||||
|
||||
|
||||
def load_api_manifest(bundle: Path) -> dict:
|
||||
return json.loads(api_manifest_path(bundle).read_text())
|
||||
|
||||
|
||||
def write_api_manifest(bundle: Path, data: dict) -> None:
|
||||
api_manifest_path(bundle).write_text(json.dumps(data, indent=2) + "\n")
|
||||
|
||||
|
||||
def clone_bundle(root: Path) -> Path:
|
||||
dest = root / "bundle"
|
||||
shutil.copytree(BUNDLE, dest, ignore=shutil.ignore_patterns("README.md"))
|
||||
return dest
|
||||
|
||||
|
||||
def generate(
|
||||
bundle: Path, work: Path, wasmtime_version: str = WASM_VERSION
|
||||
) -> tuple[int, str, str]:
|
||||
output = work / "QuickJSProviderValues.cpp"
|
||||
completed = subprocess.run(
|
||||
[
|
||||
sys.executable,
|
||||
str(SCRIPT),
|
||||
"--bundle-dir",
|
||||
str(bundle),
|
||||
"--wasmtime-version",
|
||||
wasmtime_version,
|
||||
"--output",
|
||||
str(output),
|
||||
],
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
cpp = output.read_text() if output.is_file() else ""
|
||||
return completed.returncode, completed.stderr, cpp
|
||||
|
||||
|
||||
def hex_bytes(value: str) -> str:
|
||||
return ", ".join(f"0x{value[i:i + 2]}" for i in range(0, 64, 2))
|
||||
|
||||
|
||||
def pin_holds(returncode: int, cpp: str) -> bool:
|
||||
if returncode != 0 or not cpp:
|
||||
return False
|
||||
required = [
|
||||
hex_bytes(PIN["provider_sha256"]),
|
||||
f"std::size_t const providerSize = {PIN['provider_size']};",
|
||||
f'"{PIN["manifest_sha256"]}"',
|
||||
hex_bytes(PIN["runtime_profile_id"]),
|
||||
f'"{PIN["broad_declaration_sha256"]}"',
|
||||
f'"{PIN["exact_v1_declaration_sha256"]}"',
|
||||
f'"{PIN["surface_sha256"]}"',
|
||||
f'"{PIN["api_artifact_manifest_sha256"]}"',
|
||||
hex_bytes(PIN["bytecode_abi"]),
|
||||
f'"{PIN["native_abi"]}"',
|
||||
f"std::uint32_t const wasmStackBytes = {PIN['wasm_stack_bytes']}U;",
|
||||
"std::uint32_t const serializedObjectMaxBytes =\n 1048576U;",
|
||||
"std::uint32_t const serializedObjectMaxFields =\n 32768U;",
|
||||
"std::uint32_t const serializedObjectMaxScopes =\n 32769U;",
|
||||
"std::uint32_t const serializedObjectMaxDepth =\n 10U;",
|
||||
"std::uint32_t const providerMemoryMinimumPages = 7U;",
|
||||
"std::uint32_t const providerMemoryMaximumPages = 512U;",
|
||||
"constexpr char const sealedProvider[] =",
|
||||
f"sizeof(sealedProvider) - 1 == {PIN['provider_size']}",
|
||||
]
|
||||
if any(item not in cpp for item in required):
|
||||
return False
|
||||
return all(row in cpp for row in (*TYPED_IMPORT_ROWS, *TYPED_EXPORT_ROWS))
|
||||
|
||||
|
||||
class GenerateQuickJSProviderBundleTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls) -> None:
|
||||
missing = [
|
||||
path.name
|
||||
for path in (
|
||||
json_path(BUNDLE),
|
||||
cmake_path(BUNDLE),
|
||||
native_path(BUNDLE),
|
||||
wasm_path(BUNDLE),
|
||||
api_manifest_path(BUNDLE),
|
||||
broad_declaration_path(BUNDLE),
|
||||
exact_v1_declaration_path(BUNDLE),
|
||||
surface_path(BUNDLE),
|
||||
SCRIPT,
|
||||
)
|
||||
if not path.is_file()
|
||||
]
|
||||
if missing:
|
||||
raise AssertionError(
|
||||
"sealed QuickJS bundle is incomplete: " + ", ".join(missing)
|
||||
)
|
||||
|
||||
def mutate(
|
||||
self, mutator, wasmtime_version: str = WASM_VERSION
|
||||
) -> tuple[int, str, str]:
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
work = Path(tmp)
|
||||
bundle = clone_bundle(work)
|
||||
mutator(bundle)
|
||||
return generate(bundle, work / "out", wasmtime_version)
|
||||
|
||||
def assert_generator_red(
|
||||
self, mutator, fragment: str, wasmtime_version: str = WASM_VERSION
|
||||
) -> None:
|
||||
returncode, stderr, cpp = self.mutate(mutator, wasmtime_version)
|
||||
self.assertNotEqual(returncode, 0, stderr)
|
||||
self.assertIn(fragment, stderr)
|
||||
self.assertFalse(pin_holds(returncode, cpp), stderr)
|
||||
|
||||
def test_unmutated_lock_projects_pin_and_typed_exports(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
work = Path(tmp)
|
||||
returncode, stderr, cpp = generate(clone_bundle(work), work / "out")
|
||||
self.assertEqual(returncode, 0, stderr)
|
||||
self.assertTrue(pin_holds(returncode, cpp), stderr)
|
||||
self.assertEqual(cpp.count("ProviderExportSignature const"), 2)
|
||||
|
||||
def test_provider_bytes_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
path = wasm_path(bundle)
|
||||
data = bytearray(path.read_bytes())
|
||||
data[-1] ^= 0xFF
|
||||
path.write_bytes(data)
|
||||
|
||||
self.assert_generator_red(mutate, "WASM does not match")
|
||||
|
||||
def test_provider_size_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
set_cmake(bundle, "PROVIDER_SIZE", "1116637")
|
||||
|
||||
self.assert_generator_red(mutate, "provider size disagrees")
|
||||
|
||||
def test_coordinated_provider_size_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
value = 1116637
|
||||
data = load_json(bundle)
|
||||
data["provider"]["size"] = value
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
set_cmake(bundle, "PROVIDER_SIZE", str(value))
|
||||
|
||||
self.assert_generator_red(mutate, "provider size disagrees with the sealed F0")
|
||||
|
||||
def test_provider_sha_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
set_cmake(
|
||||
bundle,
|
||||
"PROVIDER_SHA256",
|
||||
"00" + PIN["provider_sha256"][2:],
|
||||
)
|
||||
|
||||
self.assert_generator_red(mutate, "provider sha256 disagrees")
|
||||
|
||||
def test_coordinated_provider_sha_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
value = "00" + PIN["provider_sha256"][2:]
|
||||
data = load_json(bundle)
|
||||
data["provider"]["sha256"] = value
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
set_cmake(bundle, "PROVIDER_SHA256", value)
|
||||
|
||||
self.assert_generator_red(mutate, "provider SHA-256 disagrees with the sealed F0")
|
||||
|
||||
def test_manifest_sha_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
set_cmake(
|
||||
bundle,
|
||||
"MANIFEST_SHA256",
|
||||
"00" + PIN["manifest_sha256"][2:],
|
||||
)
|
||||
|
||||
self.assert_generator_red(mutate, "JSON manifest does not match")
|
||||
|
||||
def test_coordinated_manifest_identity_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_json(bundle)
|
||||
data["diagnostic_note"] = "not F0"
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
|
||||
self.assert_generator_red(mutate, "provider manifest SHA-256")
|
||||
|
||||
def test_runtime_profile_id_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
set_cmake(
|
||||
bundle,
|
||||
"RUNTIME_PROFILE_ID",
|
||||
"00" + PIN["runtime_profile_id"][2:],
|
||||
)
|
||||
|
||||
self.assert_generator_red(mutate, "runtime-profile ID disagrees")
|
||||
|
||||
def test_coordinated_runtime_profile_id_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
value = "00" + PIN["runtime_profile_id"][2:]
|
||||
data = load_json(bundle)
|
||||
data["runtime_profile_id"] = value
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
set_cmake(bundle, "RUNTIME_PROFILE_ID", value)
|
||||
|
||||
self.assert_generator_red(mutate, "runtime-profile ID disagrees with the sealed F0")
|
||||
|
||||
def _coordinated_api_artifact_mutation(
|
||||
self, source_path: str, local_path, fragment: str
|
||||
) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
path = local_path(bundle)
|
||||
path.write_bytes(path.read_bytes() + b"\n")
|
||||
manifest = load_api_manifest(bundle)
|
||||
manifest["artifacts"][source_path] = hashlib.sha256(
|
||||
path.read_bytes()
|
||||
).hexdigest()
|
||||
write_api_manifest(bundle, manifest)
|
||||
|
||||
self.assert_generator_red(mutate, fragment)
|
||||
|
||||
def test_broad_declaration_identity_mutation(self) -> None:
|
||||
self._coordinated_api_artifact_mutation(
|
||||
"python/jshookz/src/jshookz/types/hooks-api.d.ts",
|
||||
broad_declaration_path,
|
||||
"hooks-api.d.ts disagrees with the sealed F0 table",
|
||||
)
|
||||
|
||||
def test_exact_v1_declaration_identity_mutation(self) -> None:
|
||||
self._coordinated_api_artifact_mutation(
|
||||
"python/jshookz/src/jshookz/types/xahau-quickjs-v1.d.ts",
|
||||
exact_v1_declaration_path,
|
||||
"xahau-quickjs-v1.d.ts disagrees with the sealed F0 table",
|
||||
)
|
||||
|
||||
def test_selected_surface_identity_mutation(self) -> None:
|
||||
self._coordinated_api_artifact_mutation(
|
||||
"python/jshookz/src/jshookz/types/xahau-quickjs-v1.surface.json",
|
||||
surface_path,
|
||||
"xahau-quickjs-v1.surface.json disagrees with the sealed F0 table",
|
||||
)
|
||||
|
||||
def test_api_artifact_manifest_identity_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_api_manifest(bundle)
|
||||
api_manifest_path(bundle).write_text(json.dumps(data, indent=4) + "\n")
|
||||
|
||||
self.assert_generator_red(mutate, "API artifact manifest SHA-256")
|
||||
|
||||
def test_declaration_sha_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_json(bundle)
|
||||
data["javascript_surface"]["declaration_sha256"] = (
|
||||
"00" + PIN["exact_v1_declaration_sha256"][2:]
|
||||
)
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
|
||||
self.assert_generator_red(mutate, "declaration SHA-256 disagrees")
|
||||
|
||||
def test_surface_sha_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_json(bundle)
|
||||
data["javascript_surface"]["sha256"] = "00" + PIN["surface_sha256"][2:]
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
|
||||
self.assert_generator_red(mutate, "surface SHA-256 disagrees")
|
||||
|
||||
def test_bytecode_abi_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
set_cmake(bundle, "BYTECODE_ABI_ID", "00" + PIN["bytecode_abi"][2:])
|
||||
|
||||
self.assert_generator_red(mutate, "bytecode ABI disagrees")
|
||||
|
||||
def test_coordinated_bytecode_abi_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
value = "00" + PIN["bytecode_abi"][2:]
|
||||
data = load_json(bundle)
|
||||
data["bytecode_abi_id"] = value
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
set_cmake(bundle, "BYTECODE_ABI_ID", value)
|
||||
|
||||
self.assert_generator_red(mutate, "bytecode ABI disagrees with the sealed F0")
|
||||
|
||||
def test_native_abi_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
set_cmake(bundle, "NATIVE_ABI_SHA256", "00" + PIN["native_abi"][2:])
|
||||
|
||||
self.assert_generator_red(mutate, "native ABI snapshot does not match")
|
||||
|
||||
def test_coordinated_native_abi_identity_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
path = native_path(bundle)
|
||||
path.write_bytes(path.read_bytes() + b"\n")
|
||||
rehash_native(bundle)
|
||||
|
||||
self.assert_generator_red(mutate, "native ABI SHA-256")
|
||||
|
||||
def test_import_signature_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_json(bundle)
|
||||
data["provider"]["imports"][0]["params"].append("i32")
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
|
||||
self.assert_generator_red(mutate, "import signatures disagree")
|
||||
|
||||
def test_export_signature_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_json(bundle)
|
||||
for item in data["provider"]["exports"]:
|
||||
if item["name"] == "qjs_hook":
|
||||
item["params"].append("i32")
|
||||
break
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
|
||||
self.assert_generator_red(mutate, "export signatures disagree")
|
||||
|
||||
def test_coordinated_export_signature_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_json(bundle)
|
||||
for collection in (
|
||||
data["provider"]["exports"],
|
||||
data["source"]["provider"]["allowed_exports"],
|
||||
):
|
||||
for item in collection:
|
||||
if item["name"] == "qjs_hook":
|
||||
item["params"].append("i32")
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
|
||||
self.assert_generator_red(mutate, "sealed F0 table")
|
||||
|
||||
def test_coordinated_wasi_import_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_json(bundle)
|
||||
for collection in (
|
||||
data["provider"]["imports"],
|
||||
data["source"]["provider"]["imports"],
|
||||
):
|
||||
for item in collection:
|
||||
if item["name"] == "accept":
|
||||
item["module"] = "wasi_snapshot_preview1"
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
|
||||
self.assert_generator_red(mutate, "sealed F0 table")
|
||||
|
||||
def test_coordinated_import_signature_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_json(bundle)
|
||||
for collection in (
|
||||
data["provider"]["imports"],
|
||||
data["source"]["provider"]["imports"],
|
||||
):
|
||||
for item in collection:
|
||||
if item["name"] == "accept":
|
||||
item["params"].append("i32")
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
|
||||
self.assert_generator_red(mutate, "sealed F0 table")
|
||||
|
||||
def test_export_extra_key_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_json(bundle)
|
||||
for collection in (
|
||||
data["provider"]["exports"],
|
||||
data["source"]["provider"]["allowed_exports"],
|
||||
):
|
||||
for item in collection:
|
||||
if item["name"] == "qjs_init":
|
||||
item["note"] = "extra"
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
|
||||
self.assert_generator_red(mutate, "extra or missing keys")
|
||||
|
||||
def _memory_shape_mutation(self, key: str, value) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_json(bundle)
|
||||
for collection in (
|
||||
data["provider"]["exports"],
|
||||
data["source"]["provider"]["allowed_exports"],
|
||||
):
|
||||
for item in collection:
|
||||
if item["kind"] == "memory":
|
||||
item[key] = value
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
|
||||
self.assert_generator_red(mutate, "memory")
|
||||
|
||||
def test_memory_minimum_shape_mutation(self) -> None:
|
||||
self._memory_shape_mutation("minimum_pages", 6)
|
||||
|
||||
def test_memory_maximum_shape_mutation(self) -> None:
|
||||
self._memory_shape_mutation("maximum_pages", 511)
|
||||
|
||||
def test_memory64_shape_mutation(self) -> None:
|
||||
self._memory_shape_mutation("memory64", True)
|
||||
|
||||
def test_shared_memory_shape_mutation(self) -> None:
|
||||
self._memory_shape_mutation("shared", True)
|
||||
|
||||
def test_serialized_object_max_bytes_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
set_cmake(bundle, "SERIALIZED_OBJECT_MAX_BYTES", "1048577")
|
||||
|
||||
self.assert_generator_red(mutate, "serialized_object_max_bytes")
|
||||
|
||||
def test_serialized_object_max_fields_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
set_cmake(bundle, "SERIALIZED_OBJECT_MAX_FIELDS", "32769")
|
||||
|
||||
self.assert_generator_red(mutate, "serialized_object_max_fields")
|
||||
|
||||
def test_serialized_object_max_scopes_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
set_cmake(bundle, "SERIALIZED_OBJECT_MAX_SCOPES", "32770")
|
||||
|
||||
self.assert_generator_red(mutate, "serialized_object_max_scopes")
|
||||
|
||||
def test_serialized_object_max_depth_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
set_cmake(bundle, "SERIALIZED_OBJECT_MAX_DEPTH", "11")
|
||||
|
||||
self.assert_generator_red(mutate, "serialized_object_max_depth")
|
||||
|
||||
def _coordinated_limit(self, json_key: str, cmake_key: str, value: int) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_json(bundle)
|
||||
data["source"]["limits"][json_key] = value
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
set_cmake(bundle, cmake_key, str(value))
|
||||
|
||||
self.assert_generator_red(mutate, "sealed F0 table")
|
||||
|
||||
def test_coordinated_serialized_object_max_bytes_mutation(self) -> None:
|
||||
self._coordinated_limit(
|
||||
"serialized_object_max_bytes", "SERIALIZED_OBJECT_MAX_BYTES", 1048578
|
||||
)
|
||||
|
||||
def test_coordinated_serialized_object_max_fields_mutation(self) -> None:
|
||||
self._coordinated_limit(
|
||||
"serialized_object_max_fields", "SERIALIZED_OBJECT_MAX_FIELDS", 1
|
||||
)
|
||||
|
||||
def test_coordinated_serialized_object_max_scopes_mutation(self) -> None:
|
||||
self._coordinated_limit(
|
||||
"serialized_object_max_scopes", "SERIALIZED_OBJECT_MAX_SCOPES", 1
|
||||
)
|
||||
|
||||
def test_coordinated_serialized_object_max_depth_mutation(self) -> None:
|
||||
self._coordinated_limit(
|
||||
"serialized_object_max_depth", "SERIALIZED_OBJECT_MAX_DEPTH", 1
|
||||
)
|
||||
|
||||
def test_coordinated_heap_limit_mutation(self) -> None:
|
||||
self._coordinated_limit("quickjs_heap_bytes", "HEAP_BYTES", 16777215)
|
||||
|
||||
def test_coordinated_stack_limit_mutation(self) -> None:
|
||||
self._coordinated_limit("quickjs_stack_bytes", "STACK_BYTES", 65535)
|
||||
|
||||
def test_coordinated_initialization_fuel_mutation(self) -> None:
|
||||
self._coordinated_limit(
|
||||
"wasmtime_fuel_per_initialization", "INITIALIZATION_FUEL", 4999999
|
||||
)
|
||||
|
||||
def test_coordinated_invocation_fuel_mutation(self) -> None:
|
||||
self._coordinated_limit(
|
||||
"wasmtime_fuel_per_invocation", "INVOCATION_FUEL", 49999999
|
||||
)
|
||||
|
||||
def test_coordinated_host_work_budget_mutation(self) -> None:
|
||||
self._coordinated_limit("host_work_budget", "HOST_WORK_BUDGET", 999999)
|
||||
|
||||
def test_coordinated_host_work_base_mutation(self) -> None:
|
||||
self._coordinated_limit(
|
||||
"host_work_base_per_call", "HOST_WORK_BASE_PER_CALL", 2
|
||||
)
|
||||
|
||||
def test_coordinated_host_work_per_byte_mutation(self) -> None:
|
||||
self._coordinated_limit(
|
||||
"host_work_per_addressed_byte", "HOST_WORK_PER_ADDRESSED_BYTE", 2
|
||||
)
|
||||
|
||||
def test_coordinated_host_work_meter_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_json(bundle)
|
||||
data["source"]["limits"]["host_work_meter"] = "other-meter"
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
set_cmake(bundle, "HOST_WORK_METER", "other-meter")
|
||||
|
||||
self.assert_generator_red(mutate, "host_work_meter")
|
||||
|
||||
def test_host_work_address_mapping_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_json(bundle)
|
||||
data["source"]["limits"]["host_work_addressed_length_indices"][
|
||||
"accept"
|
||||
] = [0]
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
|
||||
self.assert_generator_red(mutate, "host_work_addressed_length_indices")
|
||||
|
||||
def test_coordinated_host_adapter_policy_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_json(bundle)
|
||||
data["source"]["execution"]["host_adapter_policy"] = "other-policy"
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
set_cmake(bundle, "HOST_ADAPTER_POLICY", "other-policy")
|
||||
|
||||
self.assert_generator_red(mutate, "host_adapter_policy")
|
||||
|
||||
def test_coordinated_hook_api_version_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_json(bundle)
|
||||
data["source"]["artifact"]["hook_api_version"] = 2
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
set_cmake(bundle, "HOOK_API_VERSION", "2")
|
||||
|
||||
self.assert_generator_red(mutate, "hook_api_version")
|
||||
|
||||
def test_wasmtime_engine_configuration_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_json(bundle)
|
||||
data["source"]["engine"]["configuration"]["wasi"] = True
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
|
||||
self.assert_generator_red(mutate, "Wasmtime engine configuration")
|
||||
|
||||
def test_coordinated_wasmtime_version_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_json(bundle)
|
||||
data["source"]["engine"]["version"] = "48.0.0"
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
set_cmake(bundle, "WASMTIME_VERSION", "48.0.0")
|
||||
|
||||
self.assert_generator_red(
|
||||
mutate, "Wasmtime version disagrees with the sealed F0", "48.0.0"
|
||||
)
|
||||
|
||||
def test_provider_memory_max_bytes_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_json(bundle)
|
||||
data["provider"]["build"]["wasm_memory_max_bytes"] = 33554431
|
||||
data["source"]["provider"]["build"][
|
||||
"wasm_memory_max_bytes"
|
||||
] = 33554431
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
|
||||
self.assert_generator_red(mutate, "wasm_memory_max_bytes")
|
||||
|
||||
def test_wasm_stack_bytes_mutation(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_json(bundle)
|
||||
data["provider"]["build"]["wasm_stack_bytes"] = 65536
|
||||
data["source"]["provider"]["build"]["wasm_stack_bytes"] = 65536
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
|
||||
self.assert_generator_red(mutate, "wasm_stack_bytes")
|
||||
|
||||
def test_stale_receipt_b_lock_control(self) -> None:
|
||||
def mutate(bundle: Path) -> None:
|
||||
data = load_json(bundle)
|
||||
data["provider"]["sha256"] = RECEIPT_B["provider_sha256"]
|
||||
data["provider"]["size"] = int(RECEIPT_B["provider_size"])
|
||||
data["runtime_profile_id"] = RECEIPT_B["runtime_profile_id"]
|
||||
data["javascript_surface"]["declaration_sha256"] = RECEIPT_B[
|
||||
"declaration_sha256"
|
||||
]
|
||||
data["javascript_surface"]["sha256"] = RECEIPT_B["surface_sha256"]
|
||||
for collection in (
|
||||
data["provider"]["exports"],
|
||||
data["source"]["provider"]["allowed_exports"],
|
||||
):
|
||||
for item in collection:
|
||||
if item["kind"] == "memory":
|
||||
item["minimum_pages"] = 6
|
||||
write_json(bundle, data)
|
||||
rehash_manifest(bundle)
|
||||
set_cmake(bundle, "PROVIDER_SHA256", RECEIPT_B["provider_sha256"])
|
||||
set_cmake(bundle, "PROVIDER_SIZE", RECEIPT_B["provider_size"])
|
||||
set_cmake(
|
||||
bundle, "RUNTIME_PROFILE_ID", RECEIPT_B["runtime_profile_id"]
|
||||
)
|
||||
|
||||
self.assert_generator_red(
|
||||
mutate, "provider SHA-256 disagrees with the sealed F0"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -1,41 +0,0 @@
|
||||
include(isolate_headers)
|
||||
|
||||
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} EXCLUDE_FROM_ALL ${ARGN} ${sources})
|
||||
|
||||
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
|
||||
|
||||
add_test(NAME ${target} COMMAND ${target})
|
||||
set_tests_properties(
|
||||
${target} PROPERTIES
|
||||
FIXTURES_REQUIRED ${target}_fixture
|
||||
)
|
||||
|
||||
add_test(
|
||||
NAME ${target}.build
|
||||
COMMAND
|
||||
${CMAKE_COMMAND}
|
||||
--build ${CMAKE_BINARY_DIR}
|
||||
--config $<CONFIG>
|
||||
--target ${target}
|
||||
)
|
||||
set_tests_properties(${target}.build PROPERTIES
|
||||
FIXTURES_SETUP ${target}_fixture
|
||||
)
|
||||
endfunction()
|
||||
@@ -1,37 +0,0 @@
|
||||
{% set os = detect_api.detect_os() %}
|
||||
{% set arch = detect_api.detect_arch() %}
|
||||
{% set compiler, version, compiler_exe = detect_api.detect_default_compiler() %}
|
||||
{% set compiler_version = version %}
|
||||
{% if os == "Linux" %}
|
||||
{% set compiler_version = detect_api.default_compiler_version(compiler, version) %}
|
||||
{% endif %}
|
||||
|
||||
[settings]
|
||||
os={{ os }}
|
||||
arch={{ arch }}
|
||||
build_type=Debug
|
||||
compiler={{compiler}}
|
||||
compiler.version={{ compiler_version }}
|
||||
compiler.cppstd=20
|
||||
{% if os == "Windows" %}
|
||||
compiler.runtime=static
|
||||
{% else %}
|
||||
compiler.libcxx={{detect_api.detect_libcxx(compiler, version, compiler_exe)}}
|
||||
{% endif %}
|
||||
|
||||
[conf]
|
||||
{% if compiler == "clang" and compiler_version >= 19 %}
|
||||
grpc/1.50.1:tools.build:cxxflags+=['-Wno-missing-template-arg-list-after-template-kw']
|
||||
{% endif %}
|
||||
{% if compiler == "apple-clang" and compiler_version >= 17 %}
|
||||
grpc/1.50.1:tools.build:cxxflags+=['-Wno-missing-template-arg-list-after-template-kw']
|
||||
{% endif %}
|
||||
{% if compiler == "clang" and compiler_version == 16 %}
|
||||
tools.build:cxxflags=['-DBOOST_ASIO_DISABLE_CONCEPTS']
|
||||
{% endif %}
|
||||
{% if compiler == "gcc" and compiler_version < 13 %}
|
||||
tools.build:cxxflags+=['-Wno-restrict']
|
||||
{% endif %}
|
||||
|
||||
[tool_requires]
|
||||
!cmake/*: cmake/[>=3 <4]
|
||||
284
conanfile.py
284
conanfile.py
@@ -1,165 +1,163 @@
|
||||
from conan import ConanFile, __version__ as conan_version
|
||||
from conan import ConanFile
|
||||
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
|
||||
import re
|
||||
|
||||
class Xrpl(ConanFile):
|
||||
name = 'xrpl'
|
||||
|
||||
license = 'ISC'
|
||||
author = 'John Freeman <jfreeman@ripple.com>'
|
||||
url = 'https://github.com/xrplf/rippled'
|
||||
description = 'The XRP Ledger'
|
||||
settings = 'os', 'compiler', 'build_type', 'arch'
|
||||
class Xrpl(ConanFile):
|
||||
name = "xrpl"
|
||||
|
||||
license = "ISC"
|
||||
author = "John Freeman <jfreeman@ripple.com>"
|
||||
url = "https://github.com/xrplf/rippled"
|
||||
description = "The XRP Ledger"
|
||||
settings = "os", "compiler", "build_type", "arch"
|
||||
options = {
|
||||
'assertions': [True, False],
|
||||
'coverage': [True, False],
|
||||
'fPIC': [True, False],
|
||||
'jemalloc': [True, False],
|
||||
'rocksdb': [True, False],
|
||||
'shared': [True, False],
|
||||
'static': [True, False],
|
||||
'tests': [True, False],
|
||||
'unity': [True, False],
|
||||
'xrpld': [True, False],
|
||||
'with_wasmedge': [True, False],
|
||||
'tool_requires_b2': [True, False],
|
||||
"assertions": [True, False],
|
||||
"coverage": [True, False],
|
||||
"fPIC": [True, False],
|
||||
"jemalloc": [True, False],
|
||||
"rocksdb": [True, False],
|
||||
"shared": [True, False],
|
||||
"static": [True, False],
|
||||
"tests": [True, False],
|
||||
"unity": [True, False],
|
||||
"xrpld": [True, False],
|
||||
"with_wasmedge": [True, False],
|
||||
"tool_requires_b2": [True, False],
|
||||
}
|
||||
|
||||
requires = [
|
||||
'grpc/1.50.1',
|
||||
'libarchive/3.8.1',
|
||||
'magic_enum/0.9.5',
|
||||
'nudb/2.0.9',
|
||||
'openssl/3.6.0',
|
||||
'soci/4.0.3@xahaud/stable',
|
||||
'zlib/1.3.1',
|
||||
]
|
||||
|
||||
test_requires = [
|
||||
'doctest/2.4.11',
|
||||
"date/3.0.3",
|
||||
"grpc/1.50.1",
|
||||
"libarchive/3.7.6",
|
||||
"magic_enum/0.9.5",
|
||||
"nudb/2.0.8",
|
||||
"openssl/3.6.0",
|
||||
"soci/4.0.3@xahaud/stable",
|
||||
"xxhash/0.8.2",
|
||||
"zlib/1.3.1",
|
||||
]
|
||||
|
||||
tool_requires = [
|
||||
'protobuf/3.21.12',
|
||||
"protobuf/3.21.12",
|
||||
]
|
||||
|
||||
default_options = {
|
||||
'assertions': False,
|
||||
'coverage': False,
|
||||
'fPIC': True,
|
||||
'jemalloc': False,
|
||||
'rocksdb': True,
|
||||
'shared': False,
|
||||
'static': True,
|
||||
'tests': False,
|
||||
'unity': False,
|
||||
'xrpld': False,
|
||||
'with_wasmedge': True,
|
||||
'tool_requires_b2': False,
|
||||
|
||||
'date/*:header_only': False,
|
||||
'grpc/*:shared': False,
|
||||
'grpc/*:secure': True,
|
||||
'libarchive/*:shared': False,
|
||||
'libarchive/*:with_acl': False,
|
||||
'libarchive/*:with_bzip2': False,
|
||||
'libarchive/*:with_cng': False,
|
||||
'libarchive/*:with_expat': False,
|
||||
'libarchive/*:with_iconv': False,
|
||||
'libarchive/*:with_libxml2': False,
|
||||
'libarchive/*:with_lz4': True,
|
||||
'libarchive/*:with_lzma': False,
|
||||
'libarchive/*:with_lzo': False,
|
||||
'libarchive/*:with_nettle': False,
|
||||
'libarchive/*:with_openssl': False,
|
||||
'libarchive/*:with_pcreposix': False,
|
||||
'libarchive/*:with_xattr': False,
|
||||
'libarchive/*:with_zlib': False,
|
||||
'lz4/*:shared': False,
|
||||
'openssl/*:shared': False,
|
||||
'protobuf/*:shared': False,
|
||||
'protobuf/*:with_zlib': True,
|
||||
'rocksdb/*:enable_sse': False,
|
||||
'rocksdb/*:lite': False,
|
||||
'rocksdb/*:shared': False,
|
||||
'rocksdb/*:use_rtti': True,
|
||||
'rocksdb/*:with_jemalloc': False,
|
||||
'rocksdb/*:with_lz4': True,
|
||||
'rocksdb/*:with_snappy': True,
|
||||
'snappy/*:shared': False,
|
||||
'soci/*:shared': False,
|
||||
'soci/*:with_sqlite3': True,
|
||||
'soci/*:with_boost': True,
|
||||
'xxhash/*:shared': False,
|
||||
"assertions": False,
|
||||
"coverage": False,
|
||||
"fPIC": True,
|
||||
"jemalloc": False,
|
||||
"rocksdb": True,
|
||||
"shared": False,
|
||||
"static": True,
|
||||
"tests": False,
|
||||
"unity": False,
|
||||
"xrpld": False,
|
||||
"with_wasmedge": True,
|
||||
"tool_requires_b2": False,
|
||||
"date/*:header_only": False,
|
||||
"grpc/*:shared": False,
|
||||
"grpc/*:secure": True,
|
||||
"libarchive/*:shared": False,
|
||||
"libarchive/*:with_acl": False,
|
||||
"libarchive/*:with_bzip2": False,
|
||||
"libarchive/*:with_cng": False,
|
||||
"libarchive/*:with_expat": False,
|
||||
"libarchive/*:with_iconv": False,
|
||||
"libarchive/*:with_libxml2": False,
|
||||
"libarchive/*:with_lz4": True,
|
||||
"libarchive/*:with_lzma": False,
|
||||
"libarchive/*:with_lzo": False,
|
||||
"libarchive/*:with_nettle": False,
|
||||
"libarchive/*:with_openssl": False,
|
||||
"libarchive/*:with_pcreposix": False,
|
||||
"libarchive/*:with_xattr": False,
|
||||
"libarchive/*:with_zlib": False,
|
||||
"lz4/*:shared": False,
|
||||
"openssl/*:shared": False,
|
||||
"protobuf/*:shared": False,
|
||||
"protobuf/*:with_zlib": True,
|
||||
"rocksdb/*:enable_sse": False,
|
||||
"rocksdb/*:lite": False,
|
||||
"rocksdb/*:shared": False,
|
||||
"rocksdb/*:use_rtti": True,
|
||||
"rocksdb/*:with_jemalloc": False,
|
||||
"rocksdb/*:with_lz4": True,
|
||||
"rocksdb/*:with_snappy": True,
|
||||
"snappy/*:shared": False,
|
||||
"soci/*:shared": False,
|
||||
"soci/*:with_sqlite3": True,
|
||||
"soci/*:with_boost": True,
|
||||
"wasmtime/*:shared": False,
|
||||
"xxhash/*:shared": False,
|
||||
}
|
||||
|
||||
def set_version(self):
|
||||
if self.version is None:
|
||||
path = f'{self.recipe_folder}/src/libxrpl/protocol/BuildInfo.cpp'
|
||||
regex = r'versionString\s?=\s?\"(.*)\"'
|
||||
with open(path, encoding='utf-8') as file:
|
||||
matches = (re.search(regex, line) for line in file)
|
||||
match = next(m for m in matches if m)
|
||||
self.version = match.group(1)
|
||||
path = f"{self.recipe_folder}/src/libxrpl/protocol/BuildInfo.cpp"
|
||||
regex = r"versionString\s?=\s?\"(.*)\""
|
||||
with open(path, "r") as file:
|
||||
matches = (re.search(regex, line) for line in file)
|
||||
match = next(m for m in matches if m)
|
||||
self.version = match.group(1)
|
||||
|
||||
def build_requirements(self):
|
||||
# These provide build tools (protoc, grpc plugins) that run during build
|
||||
self.tool_requires('grpc/1.50.1')
|
||||
self.tool_requires("grpc/1.50.1")
|
||||
# Explicitly require b2 (e.g. for building from source for glibc compatibility)
|
||||
if self.options.tool_requires_b2:
|
||||
self.tool_requires('b2/5.3.2')
|
||||
self.tool_requires("b2/5.3.2")
|
||||
|
||||
def configure(self):
|
||||
if self.settings.compiler == 'apple-clang':
|
||||
self.options['boost/*'].visibility = 'global'
|
||||
if self.settings.compiler == "apple-clang":
|
||||
self.options["boost/*"].visibility = "global"
|
||||
|
||||
def requirements(self):
|
||||
# Conan 2 requires transitive headers to be specified
|
||||
transitive_headers_opt = {'transitive_headers': True} if conan_version.split('.')[0] == '2' else {}
|
||||
# Force sqlite3 version to avoid conflicts with soci
|
||||
self.requires('sqlite3/3.49.1', override=True)
|
||||
# Force our custom snappy build to avoid Conan CMakeDeps stdc++ heuristic bug
|
||||
self.requires('snappy/1.1.10@xahaud/stable', override=True)
|
||||
self.requires("sqlite3/3.47.0", override=True)
|
||||
# Force our custom snappy build for all dependencies
|
||||
self.requires("snappy/1.1.10@xahaud/stable", override=True)
|
||||
# Force boost version for all dependencies to avoid conflicts
|
||||
self.requires('boost/1.86.0', force=True, **transitive_headers_opt)
|
||||
self.requires('date/3.0.4', **transitive_headers_opt)
|
||||
self.requires('lz4/1.10.0', force=True)
|
||||
self.requires("boost/1.86.0", override=True)
|
||||
self.requires("lz4/1.10.0", force=True)
|
||||
|
||||
if self.options.with_wasmedge:
|
||||
self.requires('wasmedge/0.11.2@xahaud/stable', **transitive_headers_opt)
|
||||
self.requires("wasmedge/0.11.2@xahaud/stable")
|
||||
if self.options.xrpld:
|
||||
self.requires("wasmtime/47.0.3@xahaud/stable")
|
||||
if self.options.jemalloc:
|
||||
self.requires('jemalloc/5.3.0', **transitive_headers_opt)
|
||||
self.requires("jemalloc/5.3.0")
|
||||
if self.options.rocksdb:
|
||||
self.requires('rocksdb/10.0.1')
|
||||
self.requires('xxhash/0.8.3', **transitive_headers_opt)
|
||||
self.requires("rocksdb/6.29.5")
|
||||
|
||||
exports_sources = (
|
||||
'CMakeLists.txt',
|
||||
'cfg/*',
|
||||
'cmake/*',
|
||||
'external/*',
|
||||
'include/*',
|
||||
'src/*',
|
||||
"CMakeLists.txt",
|
||||
"bin/getRippledInfo",
|
||||
"cfg/*",
|
||||
"cmake/*",
|
||||
"external/*",
|
||||
"include/*",
|
||||
"src/*",
|
||||
)
|
||||
|
||||
def layout(self):
|
||||
cmake_layout(self)
|
||||
# Fix this setting to follow the default introduced in Conan 1.48
|
||||
# to align with our build instructions.
|
||||
self.folders.generators = 'build/generators'
|
||||
self.folders.generators = "build/generators"
|
||||
|
||||
generators = "CMakeDeps"
|
||||
|
||||
generators = 'CMakeDeps'
|
||||
def generate(self):
|
||||
tc = CMakeToolchain(self)
|
||||
tc.variables['tests'] = self.options.tests
|
||||
tc.variables['assert'] = self.options.assertions
|
||||
tc.variables['coverage'] = self.options.coverage
|
||||
tc.variables['jemalloc'] = self.options.jemalloc
|
||||
tc.variables['rocksdb'] = self.options.rocksdb
|
||||
tc.variables['BUILD_SHARED_LIBS'] = self.options.shared
|
||||
tc.variables['static'] = self.options.static
|
||||
tc.variables['unity'] = self.options.unity
|
||||
tc.variables['xrpld'] = self.options.xrpld
|
||||
tc.variables["tests"] = self.options.tests
|
||||
tc.variables["assert"] = self.options.assertions
|
||||
tc.variables["coverage"] = self.options.coverage
|
||||
tc.variables["jemalloc"] = self.options.jemalloc
|
||||
tc.variables["rocksdb"] = self.options.rocksdb
|
||||
tc.variables["BUILD_SHARED_LIBS"] = self.options.shared
|
||||
tc.variables["static"] = self.options.static
|
||||
tc.variables["unity"] = self.options.unity
|
||||
tc.variables["xrpld"] = self.options.xrpld
|
||||
tc.generate()
|
||||
|
||||
def build(self):
|
||||
@@ -174,39 +172,29 @@ class Xrpl(ConanFile):
|
||||
cmake.install()
|
||||
|
||||
def package_info(self):
|
||||
libxrpl = self.cpp_info.components['libxrpl']
|
||||
libxrpl = self.cpp_info.components["libxrpl"]
|
||||
libxrpl.libs = [
|
||||
'xrpl',
|
||||
'xrpl.libpb',
|
||||
'ed25519',
|
||||
'secp256k1',
|
||||
"xrpl",
|
||||
"xrpl.libpb",
|
||||
"ed25519",
|
||||
"secp256k1",
|
||||
]
|
||||
# TODO: Fix the protobufs to include each other relative to
|
||||
# `include/`, not `include/ripple/proto/`.
|
||||
libxrpl.includedirs = ['include', 'include/ripple/proto']
|
||||
libxrpl.includedirs = ["include", "include/ripple/proto"]
|
||||
libxrpl.requires = [
|
||||
'boost::headers',
|
||||
'boost::chrono',
|
||||
'boost::container',
|
||||
'boost::coroutine',
|
||||
'boost::date_time',
|
||||
'boost::filesystem',
|
||||
'boost::json',
|
||||
'boost::program_options',
|
||||
'boost::regex',
|
||||
'boost::system',
|
||||
'boost::thread',
|
||||
'date::date',
|
||||
'grpc::grpc++',
|
||||
'libarchive::libarchive',
|
||||
'lz4::lz4',
|
||||
'nudb::nudb',
|
||||
'openssl::crypto',
|
||||
'protobuf::libprotobuf',
|
||||
'soci::soci',
|
||||
'sqlite3::sqlite',
|
||||
'xxhash::xxhash',
|
||||
'zlib::zlib',
|
||||
"boost::boost",
|
||||
"date::date",
|
||||
"grpc::grpc++",
|
||||
"libarchive::libarchive",
|
||||
"lz4::lz4",
|
||||
"nudb::nudb",
|
||||
"openssl::crypto",
|
||||
"protobuf::libprotobuf",
|
||||
"soci::soci",
|
||||
"sqlite3::sqlite",
|
||||
"xxhash::xxhash",
|
||||
"zlib::zlib",
|
||||
]
|
||||
if self.options.rocksdb:
|
||||
libxrpl.requires.append('rocksdb::librocksdb')
|
||||
libxrpl.requires.append("rocksdb::librocksdb")
|
||||
|
||||
6
docs/build/environment.md
vendored
6
docs/build/environment.md
vendored
@@ -5,6 +5,7 @@ platforms: Linux, macOS, or Windows.
|
||||
|
||||
[BUILD.md]: ../../BUILD.md
|
||||
|
||||
|
||||
## Linux
|
||||
|
||||
Package ecosystems vary across Linux distributions,
|
||||
@@ -22,7 +23,7 @@ direction.
|
||||
|
||||
```
|
||||
apt update
|
||||
apt install --yes curl git libssl-dev pipx python3.10-dev python3-pip make g++-11 libprotobuf-dev protobuf-compiler
|
||||
apt install --yes curl git libssl-dev python3.10-dev python3-pip make g++-11 libprotobuf-dev protobuf-compiler
|
||||
|
||||
curl --location --remote-name \
|
||||
"https://github.com/Kitware/CMake/releases/download/v3.25.1/cmake-3.25.1.tar.gz"
|
||||
@@ -34,8 +35,7 @@ make --jobs $(nproc)
|
||||
make install
|
||||
cd ..
|
||||
|
||||
pipx install 'conan<2'
|
||||
pipx ensurepath
|
||||
pip3 install 'conan<2'
|
||||
```
|
||||
|
||||
[1]: https://github.com/thejohnfreeman/rippled-docker/blob/master/ubuntu-22.04/install.sh
|
||||
|
||||
@@ -9,7 +9,7 @@ project(
|
||||
LANGUAGES CXX
|
||||
)
|
||||
|
||||
find_package(xrpl CONFIG REQUIRED)
|
||||
find_package(xrpl REQUIRED)
|
||||
|
||||
add_executable(example)
|
||||
target_sources(example PRIVATE src/example.cpp)
|
||||
59
examples/example/conanfile.py
Normal file
59
examples/example/conanfile.py
Normal file
@@ -0,0 +1,59 @@
|
||||
from conan import ConanFile, conan_version
|
||||
from conan.tools.cmake import CMake, cmake_layout
|
||||
|
||||
class Example(ConanFile):
|
||||
|
||||
def set_name(self):
|
||||
if self.name is None:
|
||||
self.name = 'example'
|
||||
|
||||
def set_version(self):
|
||||
if self.version is None:
|
||||
self.version = '0.1.0'
|
||||
|
||||
license = 'ISC'
|
||||
author = 'John Freeman <jfreeman08@gmail.com>'
|
||||
|
||||
settings = 'os', 'compiler', 'build_type', 'arch'
|
||||
options = {'shared': [True, False], 'fPIC': [True, False]}
|
||||
default_options = {
|
||||
'shared': False,
|
||||
'fPIC': True,
|
||||
'xrpl:xrpld': False,
|
||||
}
|
||||
|
||||
requires = ['xrpl/2.2.0-rc1@jfreeman/nodestore']
|
||||
generators = ['CMakeDeps', 'CMakeToolchain']
|
||||
|
||||
exports_sources = [
|
||||
'CMakeLists.txt',
|
||||
'cmake/*',
|
||||
'external/*',
|
||||
'include/*',
|
||||
'src/*',
|
||||
]
|
||||
|
||||
# For out-of-source build.
|
||||
# https://docs.conan.io/en/latest/reference/build_helpers/cmake.html#configure
|
||||
no_copy_source = True
|
||||
|
||||
def layout(self):
|
||||
cmake_layout(self)
|
||||
|
||||
def config_options(self):
|
||||
if self.settings.os == 'Windows':
|
||||
del self.options.fPIC
|
||||
|
||||
def build(self):
|
||||
cmake = CMake(self)
|
||||
cmake.configure(variables={'BUILD_TESTING': 'NO'})
|
||||
cmake.build()
|
||||
|
||||
def package(self):
|
||||
cmake = CMake(self)
|
||||
cmake.install()
|
||||
|
||||
def package_info(self):
|
||||
path = f'{self.package_folder}/share/{self.name}/cpp_info.py'
|
||||
with open(path, 'r') as file:
|
||||
exec(file.read(), {}, {'self': self.cpp_info})
|
||||
@@ -1,10 +1,8 @@
|
||||
#include <xrpl/protocol/BuildInfo.h>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
int
|
||||
main(int argc, char const** argv)
|
||||
{
|
||||
#include <xrpl/protocol/BuildInfo.h>
|
||||
|
||||
int main(int argc, char const** argv) {
|
||||
std::printf("%s\n", ripple::BuildInfo::getVersionString().c_str());
|
||||
return 0;
|
||||
}
|
||||
13
external/README.md
vendored
13
external/README.md
vendored
@@ -2,8 +2,11 @@ The subdirectories in this directory contain either copies or Conan recipes
|
||||
of external libraries used by rippled.
|
||||
The Conan recipes include patches we have not yet pushed upstream.
|
||||
|
||||
| Folder | Upstream | Description |
|
||||
| :--------------- | :------------------------------------------------------------- | :------------------------------------------------------------------------------------------- |
|
||||
| `antithesis-sdk` | [Project](https://github.com/antithesishq/antithesis-sdk-cpp/) | [Antithesis](https://antithesis.com/docs/using_antithesis/sdk/cpp/overview.html) SDK for C++ |
|
||||
| `ed25519-donna` | [Project](https://github.com/floodyberry/ed25519-donna) | [Ed25519](http://ed25519.cr.yp.to/) digital signatures |
|
||||
| `secp256k1` | [Project](https://github.com/bitcoin-core/secp256k1) | ECDSA digital signatures using the **secp256k1** curve |
|
||||
| Folder | Upstream | Description |
|
||||
|:----------------|:---------------------------------------------|:------------|
|
||||
| `antithesis-sdk`| [Project](https://github.com/antithesishq/antithesis-sdk-cpp/) | [Antithesis](https://antithesis.com/docs/using_antithesis/sdk/cpp/overview.html) SDK for C++ |
|
||||
| `ed25519-donna` | [Project](https://github.com/floodyberry/ed25519-donna) | [Ed25519](http://ed25519.cr.yp.to/) digital signatures |
|
||||
| `rocksdb` | [Recipe](https://github.com/conan-io/conan-center-index/tree/master/recipes/rocksdb) | Fast key/value database. (Supports rotational disks better than NuDB.) |
|
||||
| `secp256k1` | [Project](https://github.com/bitcoin-core/secp256k1) | ECDSA digital signatures using the **secp256k1** curve |
|
||||
| `snappy` | [Recipe](https://github.com/conan-io/conan-center-index/tree/master/recipes/snappy) | "Snappy" lossless compression algorithm. |
|
||||
| `soci` | [Recipe](https://github.com/conan-io/conan-center-index/tree/master/recipes/soci) | Abstraction layer for database access. |
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
---
|
||||
DisableFormat: true
|
||||
SortIncludes: Never
|
||||
SortIncludes: false
|
||||
2
external/antithesis-sdk/CMakeLists.txt
vendored
2
external/antithesis-sdk/CMakeLists.txt
vendored
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
cmake_minimum_required(VERSION 3.25)
|
||||
|
||||
# Note, version set explicitly by rippled project
|
||||
project(antithesis-sdk-cpp VERSION 0.4.4 LANGUAGES CXX)
|
||||
|
||||
7
external/antithesis-sdk/README.md
vendored
7
external/antithesis-sdk/README.md
vendored
@@ -1,9 +1,8 @@
|
||||
# Antithesis C++ SDK
|
||||
|
||||
This library provides methods for C++ programs to configure the [Antithesis](https://antithesis.com) platform. It contains three kinds of functionality:
|
||||
|
||||
- Assertion macros that allow you to define test properties about your software or workload.
|
||||
- Randomness functions for requesting both structured and unstructured randomness from the Antithesis platform.
|
||||
- Lifecycle functions that inform the Antithesis environment that particular test phases or milestones have been reached.
|
||||
* Assertion macros that allow you to define test properties about your software or workload.
|
||||
* Randomness functions for requesting both structured and unstructured randomness from the Antithesis platform.
|
||||
* Lifecycle functions that inform the Antithesis environment that particular test phases or milestones have been reached.
|
||||
|
||||
For general usage guidance see the [Antithesis C++ SDK Documentation](https://antithesis.com/docs/using_antithesis/sdk/cpp/overview/)
|
||||
|
||||
3
external/ed25519-donna/CMakeLists.txt
vendored
3
external/ed25519-donna/CMakeLists.txt
vendored
@@ -17,9 +17,6 @@ add_library(ed25519 STATIC
|
||||
)
|
||||
add_library(ed25519::ed25519 ALIAS ed25519)
|
||||
target_link_libraries(ed25519 PUBLIC OpenSSL::SSL)
|
||||
if(NOT MSVC)
|
||||
target_compile_options(ed25519 PRIVATE -Wno-implicit-fallthrough)
|
||||
endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
|
||||
10
external/nudb/conandata.yml
vendored
Normal file
10
external/nudb/conandata.yml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
sources:
|
||||
"2.0.8":
|
||||
url: "https://github.com/CPPAlliance/NuDB/archive/2.0.8.tar.gz"
|
||||
sha256: "9b71903d8ba111cd893ab064b9a8b6ac4124ed8bd6b4f67250205bc43c7f13a8"
|
||||
patches:
|
||||
"2.0.8":
|
||||
- patch_file: "patches/2.0.8-0001-add-include-stdexcept-for-msvc.patch"
|
||||
patch_description: "Fix build for MSVC by including stdexcept"
|
||||
patch_type: "portability"
|
||||
patch_source: "https://github.com/cppalliance/NuDB/pull/100/files"
|
||||
72
external/nudb/conanfile.py
vendored
Normal file
72
external/nudb/conanfile.py
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
import os
|
||||
|
||||
from conan import ConanFile
|
||||
from conan.tools.build import check_min_cppstd
|
||||
from conan.tools.files import apply_conandata_patches, copy, export_conandata_patches, get
|
||||
from conan.tools.layout import basic_layout
|
||||
|
||||
required_conan_version = ">=1.52.0"
|
||||
|
||||
|
||||
class NudbConan(ConanFile):
|
||||
name = "nudb"
|
||||
description = "A fast key/value insert-only database for SSD drives in C++11"
|
||||
license = "BSL-1.0"
|
||||
url = "https://github.com/conan-io/conan-center-index"
|
||||
homepage = "https://github.com/CPPAlliance/NuDB"
|
||||
topics = ("header-only", "KVS", "insert-only")
|
||||
|
||||
package_type = "header-library"
|
||||
settings = "os", "arch", "compiler", "build_type"
|
||||
no_copy_source = True
|
||||
|
||||
@property
|
||||
def _min_cppstd(self):
|
||||
return 11
|
||||
|
||||
def export_sources(self):
|
||||
export_conandata_patches(self)
|
||||
|
||||
def layout(self):
|
||||
basic_layout(self, src_folder="src")
|
||||
|
||||
def requirements(self):
|
||||
self.requires("boost/1.83.0")
|
||||
|
||||
def package_id(self):
|
||||
self.info.clear()
|
||||
|
||||
def validate(self):
|
||||
if self.settings.compiler.cppstd:
|
||||
check_min_cppstd(self, self._min_cppstd)
|
||||
|
||||
def source(self):
|
||||
get(self, **self.conan_data["sources"][self.version], strip_root=True)
|
||||
|
||||
def build(self):
|
||||
apply_conandata_patches(self)
|
||||
|
||||
def package(self):
|
||||
copy(self, "LICENSE*",
|
||||
dst=os.path.join(self.package_folder, "licenses"),
|
||||
src=self.source_folder)
|
||||
copy(self, "*",
|
||||
dst=os.path.join(self.package_folder, "include"),
|
||||
src=os.path.join(self.source_folder, "include"))
|
||||
|
||||
def package_info(self):
|
||||
self.cpp_info.bindirs = []
|
||||
self.cpp_info.libdirs = []
|
||||
|
||||
self.cpp_info.set_property("cmake_target_name", "NuDB")
|
||||
self.cpp_info.set_property("cmake_target_aliases", ["NuDB::nudb"])
|
||||
self.cpp_info.set_property("cmake_find_mode", "both")
|
||||
|
||||
self.cpp_info.components["core"].set_property("cmake_target_name", "nudb")
|
||||
self.cpp_info.components["core"].names["cmake_find_package"] = "nudb"
|
||||
self.cpp_info.components["core"].names["cmake_find_package_multi"] = "nudb"
|
||||
self.cpp_info.components["core"].requires = ["boost::thread", "boost::system"]
|
||||
|
||||
# TODO: to remove in conan v2 once cmake_find_package_* generators removed
|
||||
self.cpp_info.names["cmake_find_package"] = "NuDB"
|
||||
self.cpp_info.names["cmake_find_package_multi"] = "NuDB"
|
||||
24
external/nudb/patches/2.0.8-0001-add-include-stdexcept-for-msvc.patch
vendored
Normal file
24
external/nudb/patches/2.0.8-0001-add-include-stdexcept-for-msvc.patch
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
diff --git a/include/nudb/detail/stream.hpp b/include/nudb/detail/stream.hpp
|
||||
index 6c07bf1..e0ce8ed 100644
|
||||
--- a/include/nudb/detail/stream.hpp
|
||||
+++ b/include/nudb/detail/stream.hpp
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
+#include <stdexcept>
|
||||
|
||||
namespace nudb {
|
||||
namespace detail {
|
||||
diff --git a/include/nudb/impl/context.ipp b/include/nudb/impl/context.ipp
|
||||
index beb7058..ffde0b3 100644
|
||||
--- a/include/nudb/impl/context.ipp
|
||||
+++ b/include/nudb/impl/context.ipp
|
||||
@@ -9,6 +9,7 @@
|
||||
#define NUDB_IMPL_CONTEXT_IPP
|
||||
|
||||
#include <nudb/detail/store_base.hpp>
|
||||
+#include <stdexcept>
|
||||
|
||||
namespace nudb {
|
||||
|
||||
48
external/quickjs-provider/README.md
vendored
Normal file
48
external/quickjs-provider/README.md
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
# QuickJS provider manifest
|
||||
|
||||
These files are generated or sealed together by a jshookz source checkout:
|
||||
|
||||
```sh
|
||||
# Current layout (cpp/provider, python/jshookz). Older checkouts used
|
||||
# packages/jshookz; bin/update-jshookz-snapshot accepts either CLI path.
|
||||
uv sync --project python/jshookz --locked --group dev
|
||||
python/jshookz/.venv/bin/jshookz build provider
|
||||
```
|
||||
|
||||
Update this Xahau branch from a clean, committed jshookz checkout with one
|
||||
command:
|
||||
|
||||
```sh
|
||||
bin/update-jshookz-snapshot /path/to/jshookz
|
||||
```
|
||||
|
||||
That builds and imports the sealed lock files plus the broad/exact-v1
|
||||
declarations, selected-surface manifest, and API-artifact manifest. CI checks out jshookz
|
||||
`main` and fails if `build provider` does not reproduce that lock. The
|
||||
importer then prints a self-contained `x-run-tests` command that
|
||||
regenerates the embedded Hook fixtures and verifies the cut.
|
||||
|
||||
`jshookz_provider.manifest.json` is the verified runtime-profile lock.
|
||||
`jshookz_provider.manifest.cmake` is its minimal CMake projection. Xahau checks
|
||||
the JSON hash before generating the C++ profile constants, and the runtime
|
||||
checks any supplied provider WASM against the projected size and SHA-256.
|
||||
`api-artifacts.json` closes the three tracked API artifacts; Xahau verifies its
|
||||
own digest and every named artifact before projecting their identities. These
|
||||
files add no parallel CMake lock-value fields.
|
||||
|
||||
The provider binary is not vendored in this integration slice. Tests inject
|
||||
the exact built artifact. Configure needs python3 to project these lock files.
|
||||
A daemon whose embed is empty will not start.
|
||||
|
||||
For a local producer-to-consumer build, point Xahau straight at the emitted
|
||||
bundle instead of copying it:
|
||||
|
||||
```sh
|
||||
cmake -S . -B build \
|
||||
-DXAHAU_QUICKJS_PROVIDER_BUNDLE_DIR=/path/to/jshookz/build/xahau-provider
|
||||
```
|
||||
|
||||
A build-time generator writes `QuickJSProviderValues.cpp` from those
|
||||
locks and, if present, the gitignored wasm. Configure only checks that
|
||||
the three lock files exist. Changing the bundle rebuilds that one
|
||||
translation unit; hash, Wasmtime, and optional-wasm checks run then.
|
||||
8
external/quickjs-provider/api-artifacts.json
vendored
Normal file
8
external/quickjs-provider/api-artifacts.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"artifacts": {
|
||||
"python/jshookz/src/jshookz/types/hooks-api.d.ts": "649079b831bc68eff0f440644649a505addafb08a3f5174e4031c8de6aedffa0",
|
||||
"python/jshookz/src/jshookz/types/xahau-quickjs-v1.d.ts": "20881232f0602e35de0fcbb8b5a3c1511606392749a0f79daebb386204f4f4da",
|
||||
"python/jshookz/src/jshookz/types/xahau-quickjs-v1.surface.json": "96a9218bf38abbf1bc9f2839408700d03572e0b065d625263f70477bc32597ac"
|
||||
},
|
||||
"schema": "jshookz.api-artifacts.v1"
|
||||
}
|
||||
3209
external/quickjs-provider/hooks-api.d.ts
vendored
Normal file
3209
external/quickjs-provider/hooks-api.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
27
external/quickjs-provider/jshookz_provider.manifest.cmake
generated
vendored
Normal file
27
external/quickjs-provider/jshookz_provider.manifest.cmake
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# Generated by jshookz build provider; do not edit.
|
||||
set(XAHAU_QUICKJS_MANIFEST_SCHEMA "xahau.quickjs.runtime-profile-lock.v1")
|
||||
set(XAHAU_QUICKJS_MANIFEST_SHA256 "1673b27d21063957cece9095cceb7e2dbfa53b6f49a5b7f824a486d7d90b2391")
|
||||
set(XAHAU_QUICKJS_PROVIDER_FILE "jshookz_provider.wasm")
|
||||
set(XAHAU_QUICKJS_PROVIDER_SHA256 "f60ab333acb547e50d7d087960839bd11833cb133d496af98e0b72a1bb3b84df")
|
||||
set(XAHAU_QUICKJS_PROVIDER_SIZE "1116638")
|
||||
set(XAHAU_QUICKJS_PROVIDER_IMPORT_COUNT "13")
|
||||
set(XAHAU_QUICKJS_PROVIDER_EXPORT_COUNT "22")
|
||||
set(XAHAU_QUICKJS_NATIVE_ABI_FILE "jshookz_provider.native-abi.json")
|
||||
set(XAHAU_QUICKJS_NATIVE_ABI_SHA256 "328ec938dcad875f3bdf25b8d779dd77f3571589818ca9271cb98c64c7018f99")
|
||||
set(XAHAU_QUICKJS_BYTECODE_ABI_ID "75ea54f357d397c4b33899e495bb385dad975a43b1c4a7a2cead30474327d33e")
|
||||
set(XAHAU_QUICKJS_RUNTIME_PROFILE_ID "29acf12e170436e5ccadfbc118d02a60909f86a88262106652b2f71994b0ea25")
|
||||
set(XAHAU_QUICKJS_HOOK_API_VERSION "1")
|
||||
set(XAHAU_QUICKJS_WASMTIME_VERSION "47.0.3")
|
||||
set(XAHAU_QUICKJS_INITIALIZATION_FUEL "5000000")
|
||||
set(XAHAU_QUICKJS_INVOCATION_FUEL "50000000")
|
||||
set(XAHAU_QUICKJS_HOST_WORK_METER "base-plus-addressed-byte-v1")
|
||||
set(XAHAU_QUICKJS_HOST_WORK_BUDGET "1000000")
|
||||
set(XAHAU_QUICKJS_HOST_WORK_BASE_PER_CALL "1")
|
||||
set(XAHAU_QUICKJS_HOST_WORK_PER_ADDRESSED_BYTE "1")
|
||||
set(XAHAU_QUICKJS_HOST_ADAPTER_POLICY "xahau-raw-hook-host-v1")
|
||||
set(XAHAU_QUICKJS_HEAP_BYTES "16777216")
|
||||
set(XAHAU_QUICKJS_STACK_BYTES "65536")
|
||||
set(XAHAU_QUICKJS_SERIALIZED_OBJECT_MAX_BYTES "1048576")
|
||||
set(XAHAU_QUICKJS_SERIALIZED_OBJECT_MAX_FIELDS "32768")
|
||||
set(XAHAU_QUICKJS_SERIALIZED_OBJECT_MAX_SCOPES "32769")
|
||||
set(XAHAU_QUICKJS_SERIALIZED_OBJECT_MAX_DEPTH "10")
|
||||
854
external/quickjs-provider/jshookz_provider.manifest.json
generated
vendored
Normal file
854
external/quickjs-provider/jshookz_provider.manifest.json
generated
vendored
Normal file
@@ -0,0 +1,854 @@
|
||||
{
|
||||
"bytecode_abi_id": "75ea54f357d397c4b33899e495bb385dad975a43b1c4a7a2cead30474327d33e",
|
||||
"javascript_surface": {
|
||||
"declaration": "python/jshookz/src/jshookz/types/xahau-quickjs-v1.d.ts",
|
||||
"declaration_sha256": "20881232f0602e35de0fcbb8b5a3c1511606392749a0f79daebb386204f4f4da",
|
||||
"manifest": "python/jshookz/src/jshookz/types/xahau-quickjs-v1.surface.json",
|
||||
"schema": "jshookz.javascript-surface.v1",
|
||||
"sha256": "96a9218bf38abbf1bc9f2839408700d03572e0b065d625263f70477bc32597ac"
|
||||
},
|
||||
"provider": {
|
||||
"build": {
|
||||
"wasm_memory_max_bytes": 33554432,
|
||||
"wasm_stack_bytes": 131072
|
||||
},
|
||||
"exports": [
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "_initialize",
|
||||
"params": [],
|
||||
"results": []
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "free",
|
||||
"params": [
|
||||
"i32"
|
||||
],
|
||||
"results": []
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "malloc",
|
||||
"params": [
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "memory",
|
||||
"maximum_pages": 512,
|
||||
"memory64": false,
|
||||
"minimum_pages": 7,
|
||||
"name": "memory",
|
||||
"shared": false
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_cbak",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_compile",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_compile_module",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_destroy",
|
||||
"params": [],
|
||||
"results": []
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_enable_coverage",
|
||||
"params": [
|
||||
"i32"
|
||||
],
|
||||
"results": []
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_eval",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_eval_bytecode",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_eval_module",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_get_bytecode_len",
|
||||
"params": [],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_get_bytecode_ptr",
|
||||
"params": [],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_get_result_len",
|
||||
"params": [],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_get_result_ptr",
|
||||
"params": [],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_hook",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_init",
|
||||
"params": [],
|
||||
"results": []
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_set_max_stack_size",
|
||||
"params": [
|
||||
"i32"
|
||||
],
|
||||
"results": []
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_set_memory_limit",
|
||||
"params": [
|
||||
"i32"
|
||||
],
|
||||
"results": []
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_set_seed",
|
||||
"params": [
|
||||
"i32"
|
||||
],
|
||||
"results": []
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_validate_hook_module",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
}
|
||||
],
|
||||
"imports": [
|
||||
{
|
||||
"module": "env",
|
||||
"name": "accept",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32",
|
||||
"i64"
|
||||
],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "emit",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32",
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "etxn_reserve",
|
||||
"params": [
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "hook_account",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "ledger_last_hash",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "ledger_last_time",
|
||||
"params": [],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "ledger_seq",
|
||||
"params": [],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "otxn_type",
|
||||
"params": [],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "prepare",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32",
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "rollback",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32",
|
||||
"i64"
|
||||
],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "state",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32",
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "state_set",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32",
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "trace",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32",
|
||||
"i32",
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
}
|
||||
],
|
||||
"sha256": "f60ab333acb547e50d7d087960839bd11833cb133d496af98e0b72a1bb3b84df",
|
||||
"size": 1116638
|
||||
},
|
||||
"runtime_profile_id": "29acf12e170436e5ccadfbc118d02a60909f86a88262106652b2f71994b0ea25",
|
||||
"schema": "xahau.quickjs.runtime-profile-lock.v1",
|
||||
"source": {
|
||||
"artifact": {
|
||||
"envelope_version": 1,
|
||||
"hook_api_version": 1,
|
||||
"kind": "quickjs-bytecode"
|
||||
},
|
||||
"bytecode_abi": {
|
||||
"entry_exports": {
|
||||
"callback": "optional-callable",
|
||||
"main": "required-callable"
|
||||
},
|
||||
"quickjs_bytecode_version": 5,
|
||||
"quickjs_version": "2025-09-13",
|
||||
"read_flags": [
|
||||
"JS_READ_OBJ_BYTECODE"
|
||||
],
|
||||
"root": "es-module",
|
||||
"write_flags": [
|
||||
"JS_WRITE_OBJ_BYTECODE"
|
||||
]
|
||||
},
|
||||
"engine": {
|
||||
"configuration": {
|
||||
"consume_fuel": true,
|
||||
"cranelift_nan_canonicalization": true,
|
||||
"wasi": false,
|
||||
"wasm_memory64": false,
|
||||
"wasm_multi_memory": false,
|
||||
"wasm_relaxed_simd": false,
|
||||
"wasm_tail_call": false,
|
||||
"wasm_threads": false
|
||||
},
|
||||
"implementation": "wasmtime-native-c-api",
|
||||
"module_lifecycle": "compile-once-fresh-store-and-instance-per-invocation",
|
||||
"version": "47.0.3"
|
||||
},
|
||||
"execution": {
|
||||
"host_adapter_policy": "xahau-raw-hook-host-v1",
|
||||
"host_work_exhaustion": "uncatchable-wasmtime-trap-to-wasm-error",
|
||||
"initialization": "finite-cold-qjs-init-budget-before-invocation-fuel-reset",
|
||||
"ordinary_host_status": "returned-as-i64-never-trapped",
|
||||
"pending_jobs_after_entry": "not-drained",
|
||||
"result_failure_policy": "rollback.onFail-preserves-coded-failure;rollback.requirePresent-requires-success-and-non-nullish-value;rollback.requireTruthy-requires-success-and-truthy-value;accept.unlessPresent-accepts-on-failure-or-nullish-value;accept.unlessTruthy-accepts-on-failure-or-falsy-value;guards-use-explicit-message-and-optional-code-default-zero",
|
||||
"sfHookInstructionCount": "initial-wasmtime-invocation-fuel-minus-remaining-fuel",
|
||||
"terminals": "record-hook-result-and-uncatchable-wasmtime-trap"
|
||||
},
|
||||
"javascript_surface": {
|
||||
"declaration": "python/jshookz/src/jshookz/types/xahau-quickjs-v1.d.ts",
|
||||
"manifest": "python/jshookz/src/jshookz/types/xahau-quickjs-v1.surface.json",
|
||||
"schema": "jshookz.javascript-surface.v1"
|
||||
},
|
||||
"limits": {
|
||||
"host_work_addressed_length_indices": {
|
||||
"accept": [
|
||||
1
|
||||
],
|
||||
"emit": [
|
||||
1,
|
||||
3
|
||||
],
|
||||
"hook_account": [
|
||||
1
|
||||
],
|
||||
"ledger_last_hash": [
|
||||
1
|
||||
],
|
||||
"prepare": [
|
||||
1,
|
||||
3
|
||||
],
|
||||
"rollback": [
|
||||
1
|
||||
],
|
||||
"state": [
|
||||
1,
|
||||
3
|
||||
],
|
||||
"state_set": [
|
||||
1,
|
||||
3
|
||||
],
|
||||
"trace": [
|
||||
1,
|
||||
3
|
||||
]
|
||||
},
|
||||
"host_work_base_per_call": 1,
|
||||
"host_work_budget": 1000000,
|
||||
"host_work_meter": "base-plus-addressed-byte-v1",
|
||||
"host_work_per_addressed_byte": 1,
|
||||
"quickjs_heap_bytes": 16777216,
|
||||
"quickjs_stack_bytes": 65536,
|
||||
"serialized_object_max_bytes": 1048576,
|
||||
"serialized_object_max_depth": 10,
|
||||
"serialized_object_max_fields": 32768,
|
||||
"serialized_object_max_scopes": 32769,
|
||||
"wasmtime_fuel_per_initialization": 5000000,
|
||||
"wasmtime_fuel_per_invocation": 50000000
|
||||
},
|
||||
"name": "xahau-quickjs-v1",
|
||||
"provider": {
|
||||
"allowed_exports": [
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "_initialize",
|
||||
"params": [],
|
||||
"results": []
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "free",
|
||||
"params": [
|
||||
"i32"
|
||||
],
|
||||
"results": []
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "malloc",
|
||||
"params": [
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "memory",
|
||||
"maximum_pages": 512,
|
||||
"memory64": false,
|
||||
"minimum_pages": 7,
|
||||
"name": "memory",
|
||||
"shared": false
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_cbak",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_compile",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_compile_module",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_destroy",
|
||||
"params": [],
|
||||
"results": []
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_enable_coverage",
|
||||
"params": [
|
||||
"i32"
|
||||
],
|
||||
"results": []
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_eval",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_eval_bytecode",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_eval_module",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_get_bytecode_len",
|
||||
"params": [],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_get_bytecode_ptr",
|
||||
"params": [],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_get_result_len",
|
||||
"params": [],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_get_result_ptr",
|
||||
"params": [],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_hook",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_init",
|
||||
"params": [],
|
||||
"results": []
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_set_max_stack_size",
|
||||
"params": [
|
||||
"i32"
|
||||
],
|
||||
"results": []
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_set_memory_limit",
|
||||
"params": [
|
||||
"i32"
|
||||
],
|
||||
"results": []
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_set_seed",
|
||||
"params": [
|
||||
"i32"
|
||||
],
|
||||
"results": []
|
||||
},
|
||||
{
|
||||
"kind": "function",
|
||||
"name": "qjs_validate_hook_module",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i32"
|
||||
]
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"c_flags": [
|
||||
"-fwrapv",
|
||||
"-funsigned-char",
|
||||
"-mllvm",
|
||||
"-wasm-enable-sjlj"
|
||||
],
|
||||
"cxx_flags": [
|
||||
"-fno-exceptions",
|
||||
"-fno-rtti",
|
||||
"-mllvm",
|
||||
"-wasm-enable-sjlj"
|
||||
],
|
||||
"optimization": "O2",
|
||||
"target": "wasm32-wasi",
|
||||
"wasi_sdk": "32",
|
||||
"wasm_memory_max_bytes": 33554432,
|
||||
"wasm_stack_bytes": 131072
|
||||
},
|
||||
"forbidden_import_modules": [
|
||||
"wasi_snapshot_preview1"
|
||||
],
|
||||
"imports": [
|
||||
{
|
||||
"module": "env",
|
||||
"name": "accept",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32",
|
||||
"i64"
|
||||
],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "emit",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32",
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "etxn_reserve",
|
||||
"params": [
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "hook_account",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "ledger_last_hash",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "ledger_last_time",
|
||||
"params": [],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "ledger_seq",
|
||||
"params": [],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "otxn_type",
|
||||
"params": [],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "prepare",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32",
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "rollback",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32",
|
||||
"i64"
|
||||
],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "state",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32",
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "state_set",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32",
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"module": "env",
|
||||
"name": "trace",
|
||||
"params": [
|
||||
"i32",
|
||||
"i32",
|
||||
"i32",
|
||||
"i32",
|
||||
"i32"
|
||||
],
|
||||
"results": [
|
||||
"i64"
|
||||
]
|
||||
}
|
||||
],
|
||||
"javascript": {
|
||||
"atomics": false,
|
||||
"date_now": "previous-ledger-close-ripple-epoch-to-unix-milliseconds",
|
||||
"dynamic_eval": "enabled-and-metered",
|
||||
"finalization_registry": false,
|
||||
"math_random": "absent-use-ledger-random-api",
|
||||
"number": "enabled",
|
||||
"promise": "required-for-module-evaluation-no-post-entry-job-drain",
|
||||
"shared_array_buffer": false,
|
||||
"timezone": "UTC",
|
||||
"weak_ref": false
|
||||
}
|
||||
},
|
||||
"schema": "xahau.quickjs.runtime-profile-source.v1"
|
||||
}
|
||||
}
|
||||
1
external/quickjs-provider/jshookz_provider.native-abi.json
generated
vendored
Normal file
1
external/quickjs-provider/jshookz_provider.native-abi.json
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"selected":[{"amendment":null,"name":"accept","param_types":["uint32_t","uint32_t","int64_t"],"return_type":"int64_t","wasm_signature":["0x7e","0x7f","0x7f","0x7e"]},{"amendment":null,"name":"rollback","param_types":["uint32_t","uint32_t","int64_t"],"return_type":"int64_t","wasm_signature":["0x7e","0x7f","0x7f","0x7e"]},{"amendment":null,"name":"ledger_seq","param_types":[],"return_type":"int64_t","wasm_signature":["0x7e"]},{"amendment":null,"name":"ledger_last_time","param_types":[],"return_type":"int64_t","wasm_signature":["0x7e"]},{"amendment":null,"name":"ledger_last_hash","param_types":["uint32_t","uint32_t"],"return_type":"int64_t","wasm_signature":["0x7e","0x7f","0x7f"]},{"amendment":null,"name":"otxn_type","param_types":[],"return_type":"int64_t","wasm_signature":["0x7e"]},{"amendment":null,"name":"hook_account","param_types":["uint32_t","uint32_t"],"return_type":"int64_t","wasm_signature":["0x7e","0x7f","0x7f"]},{"amendment":null,"name":"trace","param_types":["uint32_t","uint32_t","uint32_t","uint32_t","uint32_t"],"return_type":"int64_t","wasm_signature":["0x7e","0x7f","0x7f","0x7f","0x7f","0x7f"]},{"amendment":null,"name":"state","param_types":["uint32_t","uint32_t","uint32_t","uint32_t"],"return_type":"int64_t","wasm_signature":["0x7e","0x7f","0x7f","0x7f","0x7f"]},{"amendment":null,"name":"state_set","param_types":["uint32_t","uint32_t","uint32_t","uint32_t"],"return_type":"int64_t","wasm_signature":["0x7e","0x7f","0x7f","0x7f","0x7f"]},{"amendment":"featureHooksUpdate2","name":"prepare","param_types":["uint32_t","uint32_t","uint32_t","uint32_t"],"return_type":"int64_t","wasm_signature":["0x7e","0x7f","0x7f","0x7f","0x7f"]},{"amendment":null,"name":"etxn_reserve","param_types":["uint32_t"],"return_type":"int64_t","wasm_signature":["0x7e","0x7f"]},{"amendment":null,"name":"emit","param_types":["uint32_t","uint32_t","uint32_t","uint32_t"],"return_type":"int64_t","wasm_signature":["0x7e","0x7f","0x7f","0x7f","0x7f"]}],"source":{"commit":"bb244ef7729503a0317bcff0f8fdaa93ca5cb7d2","macro_function_count":75,"path":"include/xrpl/hook/hook_api.macro","repository":"https://github.com/Xahau/xahaud"}}
|
||||
1760
external/quickjs-provider/xahau-quickjs-v1.d.ts
vendored
Normal file
1760
external/quickjs-provider/xahau-quickjs-v1.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
581
external/quickjs-provider/xahau-quickjs-v1.surface.json
vendored
Normal file
581
external/quickjs-provider/xahau-quickjs-v1.surface.json
vendored
Normal file
@@ -0,0 +1,581 @@
|
||||
{
|
||||
"byte_policies": {
|
||||
"AccountID.from": {
|
||||
"0": "bytesLike"
|
||||
},
|
||||
"AccountID.fromHex": {
|
||||
"0": "hexString"
|
||||
},
|
||||
"Hash256.from": {
|
||||
"0": "bytesLike"
|
||||
},
|
||||
"Hash256.fromHex": {
|
||||
"0": "hexString"
|
||||
},
|
||||
"STBlob.equals": {
|
||||
"0": "bytesLikeOrSTBlob"
|
||||
},
|
||||
"STBlob.from": {
|
||||
"0": "bytesLike"
|
||||
},
|
||||
"STBlob.fromHex": {
|
||||
"0": "hexString"
|
||||
},
|
||||
"accept": {
|
||||
"0": "lifecycleMessage"
|
||||
},
|
||||
"emit.prepare": {
|
||||
"0": "bytesLikeOrSTBlob"
|
||||
},
|
||||
"emit.tx": {
|
||||
"0": "bytesLikeOrSTBlob"
|
||||
},
|
||||
"rollback": {
|
||||
"0": "lifecycleMessage"
|
||||
},
|
||||
"state.get": {
|
||||
"0": "stateKeyLike"
|
||||
},
|
||||
"state.set": {
|
||||
"0": "stateKeyLike",
|
||||
"1": "stateValueLike"
|
||||
}
|
||||
},
|
||||
"declaration": {
|
||||
"path": "python/jshookz/src/jshookz/types/xahau-quickjs-v1.d.ts",
|
||||
"sha256": "20881232f0602e35de0fcbb8b5a3c1511606392749a0f79daebb386204f4f4da"
|
||||
},
|
||||
"globals": {
|
||||
"AccountID": "object",
|
||||
"Amount": "object",
|
||||
"Currency": "object",
|
||||
"Field": "object",
|
||||
"Hash": "object",
|
||||
"Hash128": "object",
|
||||
"Hash160": "object",
|
||||
"Hash192": "object",
|
||||
"Hash256": "object",
|
||||
"IOUAmount": "object",
|
||||
"Issue": "object",
|
||||
"MPTAmount": "object",
|
||||
"NativeAmount": "object",
|
||||
"Path": "object",
|
||||
"PathHop": "object",
|
||||
"PathSet": "object",
|
||||
"Result": "object",
|
||||
"STArray": "object",
|
||||
"STBlob": "object",
|
||||
"STObject": "object",
|
||||
"SerializedField": "object",
|
||||
"UInt": "object",
|
||||
"UInt16": "object",
|
||||
"UInt32": "object",
|
||||
"UInt64": "object",
|
||||
"UInt8": "object",
|
||||
"Vector256": "object",
|
||||
"VoidResult": "object",
|
||||
"XChainBridge": "object",
|
||||
"XFLDecimal": "object",
|
||||
"accept": "function",
|
||||
"emit": "object",
|
||||
"hook": "object",
|
||||
"ledger": "object",
|
||||
"otxn": "object",
|
||||
"rollback": "function",
|
||||
"state": "object",
|
||||
"trace": "function",
|
||||
"util": "object"
|
||||
},
|
||||
"namespaces": {
|
||||
"accept": {
|
||||
"unlessPresent": "function",
|
||||
"unlessTruthy": "function",
|
||||
"when": "function"
|
||||
},
|
||||
"emit": {
|
||||
"prepare": "function",
|
||||
"reserve": "function",
|
||||
"tx": "function"
|
||||
},
|
||||
"hook": {
|
||||
"account": "function"
|
||||
},
|
||||
"ledger": {
|
||||
"lastHash": "value",
|
||||
"lastTime": "value",
|
||||
"sequence": "value"
|
||||
},
|
||||
"otxn": {
|
||||
"type": "function"
|
||||
},
|
||||
"rollback": {
|
||||
"onAllFail": "function",
|
||||
"onAnyFail": "function",
|
||||
"onFail": "function",
|
||||
"requirePresent": "function",
|
||||
"requireTruthy": "function",
|
||||
"when": "function"
|
||||
},
|
||||
"state": {
|
||||
"get": "function",
|
||||
"set": "function"
|
||||
},
|
||||
"util": {
|
||||
"decodeObject": "function",
|
||||
"safeDecodeObject": "function",
|
||||
"validateObject": "function"
|
||||
}
|
||||
},
|
||||
"prototypes": {
|
||||
"AccountID": {
|
||||
"members": {
|
||||
"equals": "function",
|
||||
"isZero": "function",
|
||||
"toBytes": "function",
|
||||
"toHex": "function"
|
||||
},
|
||||
"own": [
|
||||
"equals",
|
||||
"isZero",
|
||||
"toBytes",
|
||||
"toHex"
|
||||
],
|
||||
"probe": "AccountID.from(new Uint8Array(20))"
|
||||
},
|
||||
"Amount": {
|
||||
"members": {
|
||||
"asIOU": "function",
|
||||
"asMPT": "function",
|
||||
"asNative": "function",
|
||||
"byteLength": "value",
|
||||
"compare": "function",
|
||||
"currency": "value",
|
||||
"drops": "value",
|
||||
"equals": "function",
|
||||
"isIOU": "function",
|
||||
"isMPT": "function",
|
||||
"isNative": "function",
|
||||
"issue": "value",
|
||||
"issuer": "value",
|
||||
"kind": "value",
|
||||
"mptIssuanceId": "value",
|
||||
"toBytes": "function",
|
||||
"toString": "function",
|
||||
"toXFL": "function",
|
||||
"value": "value"
|
||||
},
|
||||
"own": [
|
||||
"asIOU",
|
||||
"asMPT",
|
||||
"asNative",
|
||||
"byteLength",
|
||||
"compare",
|
||||
"currency",
|
||||
"drops",
|
||||
"equals",
|
||||
"isIOU",
|
||||
"isMPT",
|
||||
"isNative",
|
||||
"issue",
|
||||
"issuer",
|
||||
"kind",
|
||||
"mptIssuanceId",
|
||||
"toBytes",
|
||||
"toString",
|
||||
"toXFL",
|
||||
"value"
|
||||
],
|
||||
"probe": "util.decodeObject(STBlob.fromHex('61D4838D7EA4C680000000000000000000000000005553440000000000B5F762798A53D543A014CAF8B297CFF8F2F937E8')).Amount"
|
||||
},
|
||||
"Currency": {
|
||||
"members": {
|
||||
"byteLength": "value",
|
||||
"equals": "function",
|
||||
"isNative": "value",
|
||||
"toBytes": "function",
|
||||
"toHex": "function",
|
||||
"toString": "function"
|
||||
},
|
||||
"own": [
|
||||
"byteLength",
|
||||
"equals",
|
||||
"isNative",
|
||||
"toBytes",
|
||||
"toHex",
|
||||
"toString"
|
||||
],
|
||||
"probe": "util.decodeObject(new Uint8Array()).withField('BaseAsset', new Uint8Array(20)).BaseAsset"
|
||||
},
|
||||
"Hash128": {
|
||||
"members": {
|
||||
"byteLength": "value",
|
||||
"compare": "function",
|
||||
"equals": "function",
|
||||
"isZero": "function",
|
||||
"toBytes": "function",
|
||||
"toHex": "function"
|
||||
},
|
||||
"own": [
|
||||
"byteLength",
|
||||
"compare",
|
||||
"equals",
|
||||
"isZero",
|
||||
"toBytes",
|
||||
"toHex"
|
||||
],
|
||||
"probe": "util.decodeObject(new Uint8Array()).withField('EmailHash', new Uint8Array(16)).EmailHash"
|
||||
},
|
||||
"Hash160": {
|
||||
"members": {
|
||||
"byteLength": "value",
|
||||
"compare": "function",
|
||||
"equals": "function",
|
||||
"isZero": "function",
|
||||
"toBytes": "function",
|
||||
"toHex": "function"
|
||||
},
|
||||
"own": [
|
||||
"byteLength",
|
||||
"compare",
|
||||
"equals",
|
||||
"isZero",
|
||||
"toBytes",
|
||||
"toHex"
|
||||
],
|
||||
"probe": "util.decodeObject(new Uint8Array()).withField('TakerPaysCurrency', new Uint8Array(20)).TakerPaysCurrency"
|
||||
},
|
||||
"Hash192": {
|
||||
"members": {
|
||||
"byteLength": "value",
|
||||
"compare": "function",
|
||||
"equals": "function",
|
||||
"isZero": "function",
|
||||
"toBytes": "function",
|
||||
"toHex": "function"
|
||||
},
|
||||
"own": [
|
||||
"byteLength",
|
||||
"compare",
|
||||
"equals",
|
||||
"isZero",
|
||||
"toBytes",
|
||||
"toHex"
|
||||
],
|
||||
"probe": "util.decodeObject(new Uint8Array()).withField('MPTokenIssuanceID', new Uint8Array(24)).MPTokenIssuanceID"
|
||||
},
|
||||
"Hash256": {
|
||||
"members": {
|
||||
"byteLength": "value",
|
||||
"compare": "function",
|
||||
"equals": "function",
|
||||
"isZero": "function",
|
||||
"toBytes": "function",
|
||||
"toHex": "function"
|
||||
},
|
||||
"own": [
|
||||
"byteLength",
|
||||
"compare",
|
||||
"equals",
|
||||
"isZero",
|
||||
"toBytes",
|
||||
"toHex"
|
||||
],
|
||||
"probe": "Hash256.from(new Uint8Array(32))"
|
||||
},
|
||||
"Issue": {
|
||||
"members": {
|
||||
"currency": "value",
|
||||
"equals": "function",
|
||||
"issuer": "value",
|
||||
"kind": "value",
|
||||
"mptIssuanceId": "value",
|
||||
"toBytes": "function"
|
||||
},
|
||||
"own": [
|
||||
"currency",
|
||||
"equals",
|
||||
"issuer",
|
||||
"kind",
|
||||
"mptIssuanceId",
|
||||
"toBytes"
|
||||
],
|
||||
"probe": "util.decodeObject(new Uint8Array()).withField('LockingChainIssue', new Uint8Array(20)).LockingChainIssue"
|
||||
},
|
||||
"Path": {
|
||||
"members": {
|
||||
"[Symbol.iterator]": "function",
|
||||
"at": "function",
|
||||
"length": "value"
|
||||
},
|
||||
"own": [
|
||||
"[Symbol.iterator]",
|
||||
"at",
|
||||
"length"
|
||||
],
|
||||
"probe": "util.decodeObject(STBlob.fromHex('011201B5F762798A53D543A014CAF8B297CFF8F2F937E800')).Paths.at(0)"
|
||||
},
|
||||
"PathHop": {
|
||||
"members": {
|
||||
"account": "value",
|
||||
"currency": "value",
|
||||
"issuer": "value"
|
||||
},
|
||||
"own": [
|
||||
"account",
|
||||
"currency",
|
||||
"issuer"
|
||||
],
|
||||
"probe": "util.decodeObject(STBlob.fromHex('011201B5F762798A53D543A014CAF8B297CFF8F2F937E800')).Paths.at(0).at(0)"
|
||||
},
|
||||
"PathSet": {
|
||||
"members": {
|
||||
"[Symbol.iterator]": "function",
|
||||
"at": "function",
|
||||
"length": "value",
|
||||
"toBytes": "function"
|
||||
},
|
||||
"own": [
|
||||
"[Symbol.iterator]",
|
||||
"at",
|
||||
"length",
|
||||
"toBytes"
|
||||
],
|
||||
"probe": "util.decodeObject(STBlob.fromHex('011201B5F762798A53D543A014CAF8B297CFF8F2F937E800')).Paths"
|
||||
},
|
||||
"Result": {
|
||||
"frozen": true,
|
||||
"members": {
|
||||
"okMapOr": "function",
|
||||
"okOr": "function",
|
||||
"okOrHandle": "function"
|
||||
},
|
||||
"own": [
|
||||
"okMapOr",
|
||||
"okOr",
|
||||
"okOrHandle"
|
||||
],
|
||||
"probe": "UInt64.from(0n)"
|
||||
},
|
||||
"STArray": {
|
||||
"exotic": {
|
||||
"array": false,
|
||||
"enumerable": [
|
||||
"0"
|
||||
],
|
||||
"extensible": false,
|
||||
"own": [
|
||||
"0",
|
||||
"length"
|
||||
]
|
||||
},
|
||||
"members": {
|
||||
"[Symbol.iterator]": "function",
|
||||
"at": "function",
|
||||
"length": "value",
|
||||
"toJSON": "function"
|
||||
},
|
||||
"own": [
|
||||
"[Symbol.iterator]",
|
||||
"at",
|
||||
"toJSON"
|
||||
],
|
||||
"probe": "util.decodeObject(new Uint8Array([0xF9, 0xEA, 0x22, 0, 0, 0, 1, 0xE1, 0xF1])).Memos"
|
||||
},
|
||||
"STBlob": {
|
||||
"members": {
|
||||
"byteAt": "function",
|
||||
"byteLength": "value",
|
||||
"equals": "function",
|
||||
"toBytes": "function",
|
||||
"toHex": "function"
|
||||
},
|
||||
"own": [
|
||||
"byteAt",
|
||||
"byteLength",
|
||||
"equals",
|
||||
"toBytes",
|
||||
"toHex"
|
||||
],
|
||||
"probe": "STBlob.from(new Uint8Array(0))"
|
||||
},
|
||||
"STObject": {
|
||||
"exotic": {
|
||||
"array": false,
|
||||
"enumerable": [
|
||||
"Flags"
|
||||
],
|
||||
"extensible": false,
|
||||
"own": [
|
||||
"Flags"
|
||||
]
|
||||
},
|
||||
"members": {
|
||||
"fieldBytes": "function",
|
||||
"get": "function",
|
||||
"has": "function",
|
||||
"toBytes": "function",
|
||||
"toJSON": "function",
|
||||
"withField": "function",
|
||||
"withoutField": "function"
|
||||
},
|
||||
"own": [
|
||||
"fieldBytes",
|
||||
"get",
|
||||
"has",
|
||||
"toBytes",
|
||||
"toJSON",
|
||||
"withField",
|
||||
"withoutField"
|
||||
],
|
||||
"probe": "util.decodeObject(new Uint8Array([0x22, 0, 0, 0, 9]))"
|
||||
},
|
||||
"UInt": {
|
||||
"members": {
|
||||
"add": "function",
|
||||
"bits": "value",
|
||||
"byteLength": "value",
|
||||
"compare": "function",
|
||||
"equals": "function",
|
||||
"isZero": "function",
|
||||
"saturatingAdd": "function",
|
||||
"saturatingSubtract": "function",
|
||||
"subtract": "function",
|
||||
"toBigInt": "function",
|
||||
"toNumber": "function",
|
||||
"toString": "function",
|
||||
"wrappingAdd": "function",
|
||||
"wrappingMultiply": "function",
|
||||
"wrappingSubtract": "function"
|
||||
},
|
||||
"own": [
|
||||
"add",
|
||||
"bits",
|
||||
"byteLength",
|
||||
"compare",
|
||||
"equals",
|
||||
"isZero",
|
||||
"saturatingAdd",
|
||||
"saturatingSubtract",
|
||||
"subtract",
|
||||
"toBigInt",
|
||||
"toNumber",
|
||||
"toString",
|
||||
"wrappingAdd",
|
||||
"wrappingMultiply",
|
||||
"wrappingSubtract"
|
||||
],
|
||||
"probe": "UInt8.zero"
|
||||
},
|
||||
"Vector256": {
|
||||
"exotic": {
|
||||
"array": false,
|
||||
"enumerable": [
|
||||
"0"
|
||||
],
|
||||
"extensible": false,
|
||||
"own": [
|
||||
"0",
|
||||
"length"
|
||||
]
|
||||
},
|
||||
"members": {
|
||||
"[Symbol.iterator]": "function",
|
||||
"at": "function",
|
||||
"length": "value",
|
||||
"toBytes": "function"
|
||||
},
|
||||
"own": [
|
||||
"[Symbol.iterator]",
|
||||
"at",
|
||||
"toBytes"
|
||||
],
|
||||
"probe": "util.decodeObject(STBlob.fromHex('011320000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F')).Indexes"
|
||||
},
|
||||
"VoidResult": {
|
||||
"frozen": true,
|
||||
"members": {
|
||||
"moot": "function",
|
||||
"okMapOr": "function",
|
||||
"okOr": "function",
|
||||
"okOrHandle": "function"
|
||||
},
|
||||
"own": [
|
||||
"moot"
|
||||
],
|
||||
"probe": "state.set('surface-probe', new Uint8Array(0))"
|
||||
},
|
||||
"XChainBridge": {
|
||||
"members": {
|
||||
"IssuingChainDoor": "value",
|
||||
"IssuingChainIssue": "value",
|
||||
"LockingChainDoor": "value",
|
||||
"LockingChainIssue": "value",
|
||||
"equals": "function",
|
||||
"toBytes": "function"
|
||||
},
|
||||
"own": [
|
||||
"IssuingChainDoor",
|
||||
"IssuingChainIssue",
|
||||
"LockingChainDoor",
|
||||
"LockingChainIssue",
|
||||
"equals",
|
||||
"toBytes"
|
||||
],
|
||||
"probe": "util.decodeObject(STBlob.fromHex('011914B5F762798A53D543A014CAF8B297CFF8F2F937E8000000000000000000000000000000000000000014B5F762798A53D543A014CAF8B297CFF8F2F937E80000000000000000000000000000000000000000')).XChainBridge"
|
||||
},
|
||||
"XFLDecimal": {
|
||||
"members": {
|
||||
"isNegative": "function",
|
||||
"isZero": "function"
|
||||
},
|
||||
"own": [
|
||||
"isNegative",
|
||||
"isZero"
|
||||
],
|
||||
"probe": "util.decodeObject(STBlob.fromHex('61D4838D7EA4C680000000000000000000000000005553440000000000B5F762798A53D543A014CAF8B297CFF8F2F937E8')).Amount.toXFL()"
|
||||
}
|
||||
},
|
||||
"schema": "jshookz.javascript-surface.v1",
|
||||
"statics": {
|
||||
"AccountID": {
|
||||
"from": "function",
|
||||
"fromHex": "function",
|
||||
"one": "value",
|
||||
"zero": "value"
|
||||
},
|
||||
"Hash256": {
|
||||
"from": "function",
|
||||
"fromHex": "function",
|
||||
"zero": "value"
|
||||
},
|
||||
"STBlob": {
|
||||
"from": "function",
|
||||
"fromHex": "function"
|
||||
},
|
||||
"UInt16": {
|
||||
"from": "function",
|
||||
"max": "value",
|
||||
"mulDiv": "function",
|
||||
"zero": "value"
|
||||
},
|
||||
"UInt32": {
|
||||
"from": "function",
|
||||
"max": "value",
|
||||
"mulDiv": "function",
|
||||
"zero": "value"
|
||||
},
|
||||
"UInt64": {
|
||||
"from": "function",
|
||||
"max": "value",
|
||||
"mulDiv": "function",
|
||||
"mulDivXfl": "function",
|
||||
"zero": "value"
|
||||
},
|
||||
"UInt8": {
|
||||
"from": "function",
|
||||
"max": "value",
|
||||
"mulDiv": "function",
|
||||
"zero": "value"
|
||||
}
|
||||
}
|
||||
}
|
||||
27
external/rocksdb/conandata.yml
vendored
Normal file
27
external/rocksdb/conandata.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
sources:
|
||||
"6.29.5":
|
||||
url: "https://github.com/facebook/rocksdb/archive/refs/tags/v6.29.5.tar.gz"
|
||||
sha256: "ddbf84791f0980c0bbce3902feb93a2c7006f6f53bfd798926143e31d4d756f0"
|
||||
"6.27.3":
|
||||
url: "https://github.com/facebook/rocksdb/archive/refs/tags/v6.27.3.tar.gz"
|
||||
sha256: "ee29901749b9132692b26f0a6c1d693f47d1a9ed8e3771e60556afe80282bf58"
|
||||
"6.20.3":
|
||||
url: "https://github.com/facebook/rocksdb/archive/refs/tags/v6.20.3.tar.gz"
|
||||
sha256: "c6502c7aae641b7e20fafa6c2b92273d935d2b7b2707135ebd9a67b092169dca"
|
||||
"8.8.1":
|
||||
url: "https://github.com/facebook/rocksdb/archive/refs/tags/v8.8.1.tar.gz"
|
||||
sha256: "056c7e21ad8ae36b026ac3b94b9d6e0fcc60e1d937fc80330921e4181be5c36e"
|
||||
patches:
|
||||
"6.29.5":
|
||||
- patch_file: "patches/6.29.5-0001-add-include-cstdint-for-gcc-13.patch"
|
||||
patch_description: "Fix build with gcc 13 by including cstdint"
|
||||
patch_type: "portability"
|
||||
patch_source: "https://github.com/facebook/rocksdb/pull/11118"
|
||||
- patch_file: "patches/6.29.5-0002-exclude-thirdparty.patch"
|
||||
patch_description: "Do not include thirdparty.inc"
|
||||
patch_type: "portability"
|
||||
"6.27.3":
|
||||
- patch_file: "patches/6.27.3-0001-add-include-cstdint-for-gcc-13.patch"
|
||||
patch_description: "Fix build with gcc 13 by including cstdint"
|
||||
patch_type: "portability"
|
||||
patch_source: "https://github.com/facebook/rocksdb/pull/11118"
|
||||
233
external/rocksdb/conanfile.py
vendored
Normal file
233
external/rocksdb/conanfile.py
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
import os
|
||||
import glob
|
||||
import shutil
|
||||
|
||||
from conan import ConanFile
|
||||
from conan.errors import ConanInvalidConfiguration
|
||||
from conan.tools.build import check_min_cppstd
|
||||
from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout
|
||||
from conan.tools.files import apply_conandata_patches, collect_libs, copy, export_conandata_patches, get, rm, rmdir
|
||||
from conan.tools.microsoft import check_min_vs, is_msvc, is_msvc_static_runtime
|
||||
from conan.tools.scm import Version
|
||||
|
||||
required_conan_version = ">=1.53.0"
|
||||
|
||||
|
||||
class RocksDBConan(ConanFile):
|
||||
name = "rocksdb"
|
||||
homepage = "https://github.com/facebook/rocksdb"
|
||||
license = ("GPL-2.0-only", "Apache-2.0")
|
||||
url = "https://github.com/conan-io/conan-center-index"
|
||||
description = "A library that provides an embeddable, persistent key-value store for fast storage"
|
||||
topics = ("database", "leveldb", "facebook", "key-value")
|
||||
package_type = "library"
|
||||
settings = "os", "arch", "compiler", "build_type"
|
||||
options = {
|
||||
"shared": [True, False],
|
||||
"fPIC": [True, False],
|
||||
"lite": [True, False],
|
||||
"with_gflags": [True, False],
|
||||
"with_snappy": [True, False],
|
||||
"with_lz4": [True, False],
|
||||
"with_zlib": [True, False],
|
||||
"with_zstd": [True, False],
|
||||
"with_tbb": [True, False],
|
||||
"with_jemalloc": [True, False],
|
||||
"enable_sse": [False, "sse42", "avx2"],
|
||||
"use_rtti": [True, False],
|
||||
}
|
||||
default_options = {
|
||||
"shared": False,
|
||||
"fPIC": True,
|
||||
"lite": False,
|
||||
"with_snappy": False,
|
||||
"with_lz4": False,
|
||||
"with_zlib": False,
|
||||
"with_zstd": False,
|
||||
"with_gflags": False,
|
||||
"with_tbb": False,
|
||||
"with_jemalloc": False,
|
||||
"enable_sse": False,
|
||||
"use_rtti": False,
|
||||
}
|
||||
|
||||
@property
|
||||
def _min_cppstd(self):
|
||||
return "11" if Version(self.version) < "8.8.1" else "17"
|
||||
|
||||
@property
|
||||
def _compilers_minimum_version(self):
|
||||
return {} if self._min_cppstd == "11" else {
|
||||
"apple-clang": "10",
|
||||
"clang": "7",
|
||||
"gcc": "7",
|
||||
"msvc": "191",
|
||||
"Visual Studio": "15",
|
||||
}
|
||||
|
||||
def export_sources(self):
|
||||
export_conandata_patches(self)
|
||||
|
||||
def config_options(self):
|
||||
if self.settings.os == "Windows":
|
||||
del self.options.fPIC
|
||||
if self.settings.arch != "x86_64":
|
||||
del self.options.with_tbb
|
||||
if self.settings.build_type == "Debug":
|
||||
self.options.use_rtti = True # Rtti are used in asserts for debug mode...
|
||||
|
||||
def configure(self):
|
||||
if self.options.shared:
|
||||
self.options.rm_safe("fPIC")
|
||||
|
||||
def layout(self):
|
||||
cmake_layout(self, src_folder="src")
|
||||
|
||||
def requirements(self):
|
||||
if self.options.with_gflags:
|
||||
self.requires("gflags/2.2.2")
|
||||
if self.options.with_snappy:
|
||||
self.requires("snappy/1.1.10")
|
||||
if self.options.with_lz4:
|
||||
self.requires("lz4/1.10.0")
|
||||
if self.options.with_zlib:
|
||||
self.requires("zlib/[>=1.2.11 <2]")
|
||||
if self.options.with_zstd:
|
||||
self.requires("zstd/1.5.6")
|
||||
if self.options.get_safe("with_tbb"):
|
||||
self.requires("onetbb/2021.12.0")
|
||||
if self.options.with_jemalloc:
|
||||
self.requires("jemalloc/5.3.0")
|
||||
|
||||
def validate(self):
|
||||
if self.settings.compiler.get_safe("cppstd"):
|
||||
check_min_cppstd(self, self._min_cppstd)
|
||||
|
||||
minimum_version = self._compilers_minimum_version.get(str(self.settings.compiler), False)
|
||||
if minimum_version and Version(self.settings.compiler.version) < minimum_version:
|
||||
raise ConanInvalidConfiguration(
|
||||
f"{self.ref} requires C++{self._min_cppstd}, which your compiler does not support."
|
||||
)
|
||||
|
||||
if self.settings.arch not in ["x86_64", "ppc64le", "ppc64", "mips64", "armv8"]:
|
||||
raise ConanInvalidConfiguration("Rocksdb requires 64 bits")
|
||||
|
||||
check_min_vs(self, "191")
|
||||
|
||||
if self.version == "6.20.3" and \
|
||||
self.settings.os == "Linux" and \
|
||||
self.settings.compiler == "gcc" and \
|
||||
Version(self.settings.compiler.version) < "5":
|
||||
raise ConanInvalidConfiguration("Rocksdb 6.20.3 is not compilable with gcc <5.") # See https://github.com/facebook/rocksdb/issues/3522
|
||||
|
||||
def source(self):
|
||||
get(self, **self.conan_data["sources"][self.version], strip_root=True)
|
||||
|
||||
def generate(self):
|
||||
tc = CMakeToolchain(self)
|
||||
tc.variables["FAIL_ON_WARNINGS"] = False
|
||||
tc.variables["WITH_TESTS"] = False
|
||||
tc.variables["WITH_TOOLS"] = False
|
||||
tc.variables["WITH_CORE_TOOLS"] = False
|
||||
tc.variables["WITH_BENCHMARK_TOOLS"] = False
|
||||
tc.variables["WITH_FOLLY_DISTRIBUTED_MUTEX"] = False
|
||||
if is_msvc(self):
|
||||
tc.variables["WITH_MD_LIBRARY"] = not is_msvc_static_runtime(self)
|
||||
tc.variables["ROCKSDB_INSTALL_ON_WINDOWS"] = self.settings.os == "Windows"
|
||||
tc.variables["ROCKSDB_LITE"] = self.options.lite
|
||||
tc.variables["WITH_GFLAGS"] = self.options.with_gflags
|
||||
tc.variables["WITH_SNAPPY"] = self.options.with_snappy
|
||||
tc.variables["WITH_LZ4"] = self.options.with_lz4
|
||||
tc.variables["WITH_ZLIB"] = self.options.with_zlib
|
||||
tc.variables["WITH_ZSTD"] = self.options.with_zstd
|
||||
tc.variables["WITH_TBB"] = self.options.get_safe("with_tbb", False)
|
||||
tc.variables["WITH_JEMALLOC"] = self.options.with_jemalloc
|
||||
tc.variables["ROCKSDB_BUILD_SHARED"] = self.options.shared
|
||||
tc.variables["ROCKSDB_LIBRARY_EXPORTS"] = self.settings.os == "Windows" and self.options.shared
|
||||
tc.variables["ROCKSDB_DLL" ] = self.settings.os == "Windows" and self.options.shared
|
||||
tc.variables["USE_RTTI"] = self.options.use_rtti
|
||||
if not bool(self.options.enable_sse):
|
||||
tc.variables["PORTABLE"] = True
|
||||
tc.variables["FORCE_SSE42"] = False
|
||||
elif self.options.enable_sse == "sse42":
|
||||
tc.variables["PORTABLE"] = True
|
||||
tc.variables["FORCE_SSE42"] = True
|
||||
elif self.options.enable_sse == "avx2":
|
||||
tc.variables["PORTABLE"] = False
|
||||
tc.variables["FORCE_SSE42"] = False
|
||||
# not available yet in CCI
|
||||
tc.variables["WITH_NUMA"] = False
|
||||
tc.generate()
|
||||
|
||||
deps = CMakeDeps(self)
|
||||
if self.options.with_jemalloc:
|
||||
deps.set_property("jemalloc", "cmake_file_name", "JeMalloc")
|
||||
deps.set_property("jemalloc", "cmake_target_name", "JeMalloc::JeMalloc")
|
||||
deps.generate()
|
||||
|
||||
def build(self):
|
||||
apply_conandata_patches(self)
|
||||
cmake = CMake(self)
|
||||
cmake.configure()
|
||||
cmake.build()
|
||||
|
||||
def _remove_static_libraries(self):
|
||||
rm(self, "rocksdb.lib", os.path.join(self.package_folder, "lib"))
|
||||
for lib in glob.glob(os.path.join(self.package_folder, "lib", "*.a")):
|
||||
if not lib.endswith(".dll.a"):
|
||||
os.remove(lib)
|
||||
|
||||
def _remove_cpp_headers(self):
|
||||
for path in glob.glob(os.path.join(self.package_folder, "include", "rocksdb", "*")):
|
||||
if path != os.path.join(self.package_folder, "include", "rocksdb", "c.h"):
|
||||
if os.path.isfile(path):
|
||||
os.remove(path)
|
||||
else:
|
||||
shutil.rmtree(path)
|
||||
|
||||
def package(self):
|
||||
copy(self, "COPYING", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"))
|
||||
copy(self, "LICENSE*", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"))
|
||||
cmake = CMake(self)
|
||||
cmake.install()
|
||||
if self.options.shared:
|
||||
self._remove_static_libraries()
|
||||
self._remove_cpp_headers() # Force stable ABI for shared libraries
|
||||
rmdir(self, os.path.join(self.package_folder, "lib", "cmake"))
|
||||
rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig"))
|
||||
|
||||
def package_info(self):
|
||||
cmake_target = "rocksdb-shared" if self.options.shared else "rocksdb"
|
||||
self.cpp_info.set_property("cmake_file_name", "RocksDB")
|
||||
self.cpp_info.set_property("cmake_target_name", f"RocksDB::{cmake_target}")
|
||||
# TODO: back to global scope in conan v2 once cmake_find_package* generators removed
|
||||
self.cpp_info.components["librocksdb"].libs = collect_libs(self)
|
||||
if self.settings.os == "Windows":
|
||||
self.cpp_info.components["librocksdb"].system_libs = ["shlwapi", "rpcrt4"]
|
||||
if self.options.shared:
|
||||
self.cpp_info.components["librocksdb"].defines = ["ROCKSDB_DLL"]
|
||||
elif self.settings.os in ["Linux", "FreeBSD"]:
|
||||
self.cpp_info.components["librocksdb"].system_libs = ["pthread", "m"]
|
||||
if self.options.lite:
|
||||
self.cpp_info.components["librocksdb"].defines.append("ROCKSDB_LITE")
|
||||
|
||||
# TODO: to remove in conan v2 once cmake_find_package* generators removed
|
||||
self.cpp_info.names["cmake_find_package"] = "RocksDB"
|
||||
self.cpp_info.names["cmake_find_package_multi"] = "RocksDB"
|
||||
self.cpp_info.components["librocksdb"].names["cmake_find_package"] = cmake_target
|
||||
self.cpp_info.components["librocksdb"].names["cmake_find_package_multi"] = cmake_target
|
||||
self.cpp_info.components["librocksdb"].set_property("cmake_target_name", f"RocksDB::{cmake_target}")
|
||||
if self.options.with_gflags:
|
||||
self.cpp_info.components["librocksdb"].requires.append("gflags::gflags")
|
||||
if self.options.with_snappy:
|
||||
self.cpp_info.components["librocksdb"].requires.append("snappy::snappy")
|
||||
if self.options.with_lz4:
|
||||
self.cpp_info.components["librocksdb"].requires.append("lz4::lz4")
|
||||
if self.options.with_zlib:
|
||||
self.cpp_info.components["librocksdb"].requires.append("zlib::zlib")
|
||||
if self.options.with_zstd:
|
||||
self.cpp_info.components["librocksdb"].requires.append("zstd::zstd")
|
||||
if self.options.get_safe("with_tbb"):
|
||||
self.cpp_info.components["librocksdb"].requires.append("onetbb::onetbb")
|
||||
if self.options.with_jemalloc:
|
||||
self.cpp_info.components["librocksdb"].requires.append("jemalloc::jemalloc")
|
||||
30
external/rocksdb/patches/6.29.5-0001-add-include-cstdint-for-gcc-13.patch
vendored
Normal file
30
external/rocksdb/patches/6.29.5-0001-add-include-cstdint-for-gcc-13.patch
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
--- a/include/rocksdb/utilities/checkpoint.h
|
||||
+++ b/include/rocksdb/utilities/checkpoint.h
|
||||
@@ -8,6 +8,7 @@
|
||||
#pragma once
|
||||
#ifndef ROCKSDB_LITE
|
||||
|
||||
+#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "rocksdb/status.h"
|
||||
--- a/table/block_based/data_block_hash_index.h
|
||||
+++ b/table/block_based/data_block_hash_index.h
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
+#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
--- a/util/string_util.h
|
||||
+++ b/util/string_util.h
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
+#include <cstdint>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
16
external/rocksdb/patches/6.29.5-0002-exclude-thirdparty.patch
vendored
Normal file
16
external/rocksdb/patches/6.29.5-0002-exclude-thirdparty.patch
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index ec59d4491..35577c998 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -101 +100,0 @@ if(MSVC)
|
||||
- option(WITH_GFLAGS "build with GFlags" OFF)
|
||||
@@ -103,2 +102,2 @@ if(MSVC)
|
||||
- include(${CMAKE_CURRENT_SOURCE_DIR}/thirdparty.inc)
|
||||
-else()
|
||||
+endif()
|
||||
+
|
||||
@@ -117 +116 @@ else()
|
||||
- if(MINGW)
|
||||
+ if(MINGW OR MSVC)
|
||||
@@ -183 +181,0 @@ else()
|
||||
-endif()
|
||||
2
external/secp256k1/include/secp256k1.h
vendored
2
external/secp256k1/include/secp256k1.h
vendored
@@ -541,7 +541,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
|
||||
/** Verify an ECDSA signature.
|
||||
*
|
||||
* Returns: 1: correct signature
|
||||
* 0: incorrect or unparsable signature
|
||||
* 0: incorrect or unparseable signature
|
||||
* Args: ctx: pointer to a context object
|
||||
* In: sig: the signature being verified.
|
||||
* msghash32: the 32-byte message hash being verified.
|
||||
|
||||
27
external/wasmtime/conandata.yml
vendored
Normal file
27
external/wasmtime/conandata.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
sources:
|
||||
47.0.3:
|
||||
Linux:
|
||||
armv8:
|
||||
sha256: c1ef99bb4ef0151282f339e22a67f8229d9ab336f9a17387e65f140b79c45be1
|
||||
url: https://github.com/bytecodealliance/wasmtime/releases/download/v47.0.3/wasmtime-v47.0.3-aarch64-linux-c-api.tar.xz
|
||||
x86_64:
|
||||
sha256: aaa3621f2a3d8393696702897f8f78a1cc504437d500701496d560125aefd732
|
||||
url: https://github.com/bytecodealliance/wasmtime/releases/download/v47.0.3/wasmtime-v47.0.3-x86_64-linux-c-api.tar.xz
|
||||
Macos:
|
||||
armv8:
|
||||
sha256: 1854c8f03a764c89afe77fa88d9092ab89a368e527cd27a12959b1d91152324e
|
||||
url: https://github.com/bytecodealliance/wasmtime/releases/download/v47.0.3/wasmtime-v47.0.3-aarch64-macos-c-api.tar.xz
|
||||
x86_64:
|
||||
sha256: 627622087b77b92c163e826ec6ebf834a70d78735828043edf7ace263f8a9e62
|
||||
url: https://github.com/bytecodealliance/wasmtime/releases/download/v47.0.3/wasmtime-v47.0.3-x86_64-macos-c-api.tar.xz
|
||||
MinGW:
|
||||
x86_64:
|
||||
sha256: 355a0c7b49b92bb011e74a4047cc1186271aeb8c8cfcc4360248caaf3c4d5f38
|
||||
url: https://github.com/bytecodealliance/wasmtime/releases/download/v47.0.3/wasmtime-v47.0.3-x86_64-mingw-c-api.zip
|
||||
Windows:
|
||||
armv8:
|
||||
sha256: 57107b14b28ac2152e903501fe1722007b90fc11ccd63ad6d62ed574c5dd90db
|
||||
url: https://github.com/bytecodealliance/wasmtime/releases/download/v47.0.3/wasmtime-v47.0.3-aarch64-windows-c-api.zip
|
||||
x86_64:
|
||||
sha256: 952dfbc864295eccc89caa92bc303686017ca4ea205a1f21878809f374bb77c5
|
||||
url: https://github.com/bytecodealliance/wasmtime/releases/download/v47.0.3/wasmtime-v47.0.3-x86_64-windows-c-api.zip
|
||||
162
external/wasmtime/conanfile.py
vendored
Normal file
162
external/wasmtime/conanfile.py
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
import os
|
||||
|
||||
from conan import ConanFile
|
||||
from conan.errors import ConanInvalidConfiguration
|
||||
from conan.tools.files import copy, get
|
||||
from conan.tools.microsoft import is_msvc
|
||||
|
||||
|
||||
required_conan_version = ">=2.0"
|
||||
|
||||
|
||||
class WasmtimeConan(ConanFile):
|
||||
name = "wasmtime"
|
||||
description = "Standalone WebAssembly runtime using Cranelift"
|
||||
license = "Apache-2.0 WITH LLVM-exception"
|
||||
url = "https://github.com/Xahau/xahaud"
|
||||
homepage = "https://github.com/bytecodealliance/wasmtime"
|
||||
topics = ("webassembly", "wasm")
|
||||
package_type = "library"
|
||||
settings = "os", "arch", "compiler", "build_type"
|
||||
options = {"shared": [True, False]}
|
||||
default_options = {"shared": False}
|
||||
no_copy_source = True
|
||||
|
||||
@property
|
||||
def _sources_os_key(self):
|
||||
if is_msvc(self):
|
||||
return "Windows"
|
||||
if self.settings.os == "Windows" and self.settings.compiler == "gcc":
|
||||
return "MinGW"
|
||||
return str(self.settings.os)
|
||||
|
||||
def configure(self):
|
||||
self.settings.rm_safe("compiler.libcxx")
|
||||
self.settings.rm_safe("compiler.cppstd")
|
||||
|
||||
def package_id(self):
|
||||
# Official release archives contain a prebuilt C ABI. Compiler patch
|
||||
# versions do not change the packaged bytes.
|
||||
if self.info.settings.compiler == "clang":
|
||||
self.info.settings.compiler = "gcc"
|
||||
del self.info.settings.compiler.version
|
||||
|
||||
def validate(self):
|
||||
try:
|
||||
self.conan_data["sources"][self.version][self._sources_os_key][
|
||||
str(self.settings.arch)
|
||||
]
|
||||
except KeyError as error:
|
||||
raise ConanInvalidConfiguration(
|
||||
"No official Wasmtime C-API archive for "
|
||||
f"{self.settings.os}/{self.settings.arch}"
|
||||
) from error
|
||||
|
||||
def build(self):
|
||||
get(
|
||||
self,
|
||||
**self.conan_data["sources"][self.version][self._sources_os_key][
|
||||
str(self.settings.arch)
|
||||
],
|
||||
destination=self.build_folder,
|
||||
strip_root=True,
|
||||
)
|
||||
|
||||
def package(self):
|
||||
copy(
|
||||
self,
|
||||
"*.h",
|
||||
dst=os.path.join(self.package_folder, "include"),
|
||||
src=os.path.join(self.build_folder, "include"),
|
||||
)
|
||||
copy(
|
||||
self,
|
||||
"*.hh",
|
||||
dst=os.path.join(self.package_folder, "include"),
|
||||
src=os.path.join(self.build_folder, "include"),
|
||||
)
|
||||
|
||||
source_lib = os.path.join(self.build_folder, "lib")
|
||||
package_lib = os.path.join(self.package_folder, "lib")
|
||||
package_bin = os.path.join(self.package_folder, "bin")
|
||||
if self.options.shared:
|
||||
copy(
|
||||
self,
|
||||
"wasmtime.dll.lib",
|
||||
dst=package_lib,
|
||||
src=source_lib,
|
||||
keep_path=False,
|
||||
)
|
||||
copy(
|
||||
self,
|
||||
"wasmtime.dll",
|
||||
dst=package_bin,
|
||||
src=source_lib,
|
||||
keep_path=False,
|
||||
)
|
||||
copy(
|
||||
self,
|
||||
"libwasmtime.dll.a",
|
||||
dst=package_lib,
|
||||
src=source_lib,
|
||||
keep_path=False,
|
||||
)
|
||||
copy(
|
||||
self,
|
||||
"libwasmtime.so*",
|
||||
dst=package_lib,
|
||||
src=source_lib,
|
||||
keep_path=False,
|
||||
)
|
||||
copy(
|
||||
self,
|
||||
"libwasmtime.dylib",
|
||||
dst=package_lib,
|
||||
src=source_lib,
|
||||
keep_path=False,
|
||||
)
|
||||
else:
|
||||
copy(
|
||||
self,
|
||||
"wasmtime.lib",
|
||||
dst=package_lib,
|
||||
src=source_lib,
|
||||
keep_path=False,
|
||||
)
|
||||
copy(
|
||||
self,
|
||||
"libwasmtime.a",
|
||||
dst=package_lib,
|
||||
src=source_lib,
|
||||
keep_path=False,
|
||||
)
|
||||
|
||||
copy(
|
||||
self,
|
||||
"LICENSE",
|
||||
dst=os.path.join(self.package_folder, "licenses"),
|
||||
src=self.build_folder,
|
||||
)
|
||||
|
||||
def package_info(self):
|
||||
if self.options.shared:
|
||||
self.cpp_info.libs = [
|
||||
"wasmtime.dll" if self.settings.os == "Windows" else "wasmtime"
|
||||
]
|
||||
else:
|
||||
if self.settings.os == "Windows":
|
||||
self.cpp_info.defines = ["WASM_API_EXTERN=", "WASI_API_EXTERN="]
|
||||
self.cpp_info.libs = ["wasmtime"]
|
||||
|
||||
if self.settings.os == "Windows":
|
||||
self.cpp_info.system_libs = [
|
||||
"ws2_32",
|
||||
"bcrypt",
|
||||
"advapi32",
|
||||
"userenv",
|
||||
"ntdll",
|
||||
"shell32",
|
||||
"ole32",
|
||||
]
|
||||
elif self.settings.os in ("Linux", "FreeBSD"):
|
||||
self.cpp_info.system_libs = ["pthread", "dl", "m", "rt"]
|
||||
@@ -100,14 +100,14 @@ update_hook_array() {
|
||||
echo -e "${BLUE}==> Updating ${hook_name}...${NC}"
|
||||
|
||||
# Check if hook already exists
|
||||
if grep -q "static std::vector<uint8_t> const ${hook_name} = {" "${XAHAU_H}"; then
|
||||
if grep -q "static const std::vector<uint8_t> ${hook_name} = {" "${XAHAU_H}"; then
|
||||
echo -e "${YELLOW} Replacing existing ${hook_name}${NC}"
|
||||
|
||||
# Use awk to replace the array content
|
||||
awk -v hook="${hook_name}" -v hex="${hex_array}" '
|
||||
BEGIN { in_array=0 }
|
||||
{
|
||||
if ($0 ~ "static std::vector<uint8_t> const " hook " = {") {
|
||||
if ($0 ~ "static const std::vector<uint8_t> " hook " = {") {
|
||||
print $0
|
||||
print hex
|
||||
in_array=1
|
||||
@@ -133,7 +133,7 @@ update_hook_array() {
|
||||
{
|
||||
if ($0 ~ /#endif.*XAHAU_GENESIS_HOOKS/) {
|
||||
print ""
|
||||
print "static std::vector<uint8_t> const " hook " = {"
|
||||
print "static const std::vector<uint8_t> " hook " = {"
|
||||
print hex
|
||||
print "};"
|
||||
print ""
|
||||
@@ -178,7 +178,7 @@ echo -e "${GREEN} Formatting completed${NC}"
|
||||
echo -e "${BLUE}==> Verifying changes...${NC}"
|
||||
for hook_entry in "${HOOK_FILES[@]}"; do
|
||||
hook_name="${hook_entry%%:*}"
|
||||
if grep -q "static std::vector<uint8_t> const ${hook_name} = {" "${XAHAU_H}"; then
|
||||
if grep -q "static const std::vector<uint8_t> ${hook_name} = {" "${XAHAU_H}"; then
|
||||
echo -e "${GREEN} ✓ ${hook_name} found in xahau.h${NC}"
|
||||
else
|
||||
echo -e "${RED} ✗ ${hook_name} NOT found in xahau.h${NC}" >&2
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
|
||||
#include "error.h"
|
||||
#include "extern.h"
|
||||
#include "macro.h"
|
||||
#include "sfcodes.h"
|
||||
#include "macro.h"
|
||||
#include "tts.h"
|
||||
|
||||
#include "ls_flags.h"
|
||||
|
||||
@@ -25,7 +25,6 @@ enum ltACCOUNT_ROOT {
|
||||
enum ltOFFER {
|
||||
lsfPassive = 0x00010000,
|
||||
lsfSell = 0x00020000,
|
||||
lsfHybrid = 0x00040000,
|
||||
};
|
||||
enum ltRIPPLE_STATE {
|
||||
lsfLowReserve = 0x00010000,
|
||||
@@ -65,14 +64,6 @@ enum ltMPTOKEN_ISSUANCE {
|
||||
lsfMPTCanTrade = 0x00000010,
|
||||
lsfMPTCanTransfer = 0x00000020,
|
||||
lsfMPTCanClawback = 0x00000040,
|
||||
lsmfMPTCanMutateCanLock = 0x00000002,
|
||||
lsmfMPTCanMutateRequireAuth = 0x00000004,
|
||||
lsmfMPTCanMutateCanEscrow = 0x00000008,
|
||||
lsmfMPTCanMutateCanTrade = 0x00000010,
|
||||
lsmfMPTCanMutateCanTransfer = 0x00000020,
|
||||
lsmfMPTCanMutateCanClawback = 0x00000040,
|
||||
lsmfMPTCanMutateMetadata = 0x00010000,
|
||||
lsmfMPTCanMutateTransferFee = 0x00020000,
|
||||
};
|
||||
enum ltMPTOKEN {
|
||||
lsfMPTAuthorized = 0x00000002,
|
||||
@@ -80,8 +71,5 @@ enum ltMPTOKEN {
|
||||
enum ltCREDENTIAL {
|
||||
lsfAccepted = 0x00010000,
|
||||
};
|
||||
enum ltVAULT {
|
||||
lsfVaultPrivate = 0x00010000,
|
||||
};
|
||||
|
||||
#endif // HOOKLSFLAGS_INCLUDED
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#define sfUNLModifyDisabling ((16U << 16U) + 17U)
|
||||
#define sfHookResult ((16U << 16U) + 18U)
|
||||
#define sfWasLockingChainSend ((16U << 16U) + 19U)
|
||||
#define sfWithdrawalPolicy ((16U << 16U) + 20U)
|
||||
#define sfLedgerEntryType ((1U << 16U) + 1U)
|
||||
#define sfTransactionType ((1U << 16U) + 2U)
|
||||
#define sfSignerWeight ((1U << 16U) + 3U)
|
||||
@@ -73,8 +72,6 @@
|
||||
#define sfLockCount ((2U << 16U) + 49U)
|
||||
#define sfFirstNFTokenSequence ((2U << 16U) + 50U)
|
||||
#define sfOracleDocumentID ((2U << 16U) + 51U)
|
||||
#define sfPermissionValue ((2U << 16U) + 52U)
|
||||
#define sfMutableFlags ((2U << 16U) + 53U)
|
||||
#define sfStartTime ((2U << 16U) + 93U)
|
||||
#define sfRepeatCount ((2U << 16U) + 94U)
|
||||
#define sfDelaySeconds ((2U << 16U) + 95U)
|
||||
@@ -118,7 +115,6 @@
|
||||
#define sfTakerGetsCurrency ((17U << 16U) + 3U)
|
||||
#define sfTakerGetsIssuer ((17U << 16U) + 4U)
|
||||
#define sfMPTokenIssuanceID ((21U << 16U) + 1U)
|
||||
#define sfShareMPTID ((21U << 16U) + 2U)
|
||||
#define sfLedgerHash ((5U << 16U) + 1U)
|
||||
#define sfParentHash ((5U << 16U) + 2U)
|
||||
#define sfTransactionHash ((5U << 16U) + 3U)
|
||||
@@ -156,8 +152,6 @@
|
||||
#define sfEscrowID ((5U << 16U) + 35U)
|
||||
#define sfURITokenID ((5U << 16U) + 36U)
|
||||
#define sfDomainID ((5U << 16U) + 37U)
|
||||
#define sfVaultID ((5U << 16U) + 38U)
|
||||
#define sfParentBatchID ((5U << 16U) + 39U)
|
||||
#define sfHookOnOutgoing ((5U << 16U) + 93U)
|
||||
#define sfHookOnIncoming ((5U << 16U) + 94U)
|
||||
#define sfCron ((5U << 16U) + 95U)
|
||||
@@ -166,10 +160,6 @@
|
||||
#define sfGovernanceMarks ((5U << 16U) + 98U)
|
||||
#define sfGovernanceFlags ((5U << 16U) + 99U)
|
||||
#define sfNumber ((9U << 16U) + 1U)
|
||||
#define sfAssetsAvailable ((9U << 16U) + 2U)
|
||||
#define sfAssetsMaximum ((9U << 16U) + 3U)
|
||||
#define sfAssetsTotal ((9U << 16U) + 4U)
|
||||
#define sfLossUnrealized ((9U << 16U) + 5U)
|
||||
#define sfAmount ((6U << 16U) + 1U)
|
||||
#define sfBalance ((6U << 16U) + 2U)
|
||||
#define sfLimitAmount ((6U << 16U) + 3U)
|
||||
@@ -244,7 +234,6 @@
|
||||
#define sfNFTokenMinter ((8U << 16U) + 9U)
|
||||
#define sfEmitCallback ((8U << 16U) + 10U)
|
||||
#define sfHolder ((8U << 16U) + 11U)
|
||||
#define sfDelegate ((8U << 16U) + 12U)
|
||||
#define sfHookAccount ((8U << 16U) + 16U)
|
||||
#define sfOtherChainSource ((8U << 16U) + 18U)
|
||||
#define sfOtherChainDestination ((8U << 16U) + 19U)
|
||||
@@ -283,7 +272,6 @@
|
||||
#define sfNFToken ((14U << 16U) + 12U)
|
||||
#define sfEmitDetails ((14U << 16U) + 13U)
|
||||
#define sfHook ((14U << 16U) + 14U)
|
||||
#define sfPermission ((14U << 16U) + 15U)
|
||||
#define sfSigner ((14U << 16U) + 16U)
|
||||
#define sfMajority ((14U << 16U) + 18U)
|
||||
#define sfDisabledValidator ((14U << 16U) + 19U)
|
||||
@@ -300,9 +288,6 @@
|
||||
#define sfXChainCreateAccountAttestationCollectionElement ((14U << 16U) + 31U)
|
||||
#define sfPriceData ((14U << 16U) + 32U)
|
||||
#define sfCredential ((14U << 16U) + 33U)
|
||||
#define sfRawTransaction ((14U << 16U) + 34U)
|
||||
#define sfBatchSigner ((14U << 16U) + 35U)
|
||||
#define sfBook ((14U << 16U) + 36U)
|
||||
#define sfAmountEntry ((14U << 16U) + 91U)
|
||||
#define sfMintURIToken ((14U << 16U) + 92U)
|
||||
#define sfHookEmission ((14U << 16U) + 93U)
|
||||
@@ -322,7 +307,6 @@
|
||||
#define sfNFTokens ((15U << 16U) + 10U)
|
||||
#define sfHooks ((15U << 16U) + 11U)
|
||||
#define sfVoteSlots ((15U << 16U) + 12U)
|
||||
#define sfAdditionalBooks ((15U << 16U) + 13U)
|
||||
#define sfMajorities ((15U << 16U) + 16U)
|
||||
#define sfDisabledValidators ((15U << 16U) + 17U)
|
||||
#define sfHookExecutions ((15U << 16U) + 18U)
|
||||
@@ -335,9 +319,6 @@
|
||||
#define sfAuthorizeCredentials ((15U << 16U) + 26U)
|
||||
#define sfUnauthorizeCredentials ((15U << 16U) + 27U)
|
||||
#define sfAcceptedCredentials ((15U << 16U) + 28U)
|
||||
#define sfPermissions ((15U << 16U) + 29U)
|
||||
#define sfRawTransactions ((15U << 16U) + 30U)
|
||||
#define sfBatchSigners ((15U << 16U) + 31U)
|
||||
#define sfAmounts ((15U << 16U) + 92U)
|
||||
#define sfHookEmissions ((15U << 16U) + 93U)
|
||||
#define sfImportVLKeys ((15U << 16U) + 94U)
|
||||
|
||||
@@ -61,14 +61,6 @@
|
||||
#define ttNFTOKEN_MODIFY 70
|
||||
#define ttPERMISSIONED_DOMAIN_SET 71
|
||||
#define ttPERMISSIONED_DOMAIN_DELETE 72
|
||||
#define ttDELEGATE_SET 73
|
||||
#define ttVAULT_CREATE 74
|
||||
#define ttVAULT_SET 75
|
||||
#define ttVAULT_DELETE 76
|
||||
#define ttVAULT_DEPOSIT 77
|
||||
#define ttVAULT_WITHDRAW 78
|
||||
#define ttVAULT_CLAWBACK 79
|
||||
#define ttBATCH 80
|
||||
#define ttCRON 92
|
||||
#define ttCRON_SET 93
|
||||
#define ttREMARKS_SET 94
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
enum UniversalFlags : uint32_t {
|
||||
tfFullyCanonicalSig = 0x80000000,
|
||||
tfInnerBatchTxn = 0x40000000,
|
||||
};
|
||||
|
||||
enum AccountSetFlags : uint32_t {
|
||||
@@ -41,7 +40,6 @@ enum OfferCreateFlags : uint32_t {
|
||||
tfImmediateOrCancel = 0x00020000,
|
||||
tfFillOrKill = 0x00040000,
|
||||
tfSell = 0x00080000,
|
||||
tfHybrid = 0x00100000,
|
||||
};
|
||||
|
||||
enum PaymentFlags : uint32_t {
|
||||
@@ -117,10 +115,3 @@ enum AMMClawbackFlags : uint32_t {
|
||||
enum BridgeModifyFlags : uint32_t {
|
||||
tfClearAccountCreateAmount = 0x00010000,
|
||||
};
|
||||
|
||||
enum BatchFlags : uint32_t {
|
||||
tfAllOrNothing = 0x00010000,
|
||||
tfOnlyOne = 0x00020000,
|
||||
tfUntilFailure = 0x00040000,
|
||||
tfIndependent = 0x00080000,
|
||||
};
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
@@ -367,7 +368,7 @@ get(Section const& section,
|
||||
}
|
||||
|
||||
inline std::string
|
||||
get(Section const& section, std::string const& name, char const* defaultValue)
|
||||
get(Section const& section, std::string const& name, const char* defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
|
||||
@@ -21,11 +21,9 @@
|
||||
#define RIPPLED_COMPRESSIONALGORITHMS_H_INCLUDED
|
||||
|
||||
#include <xrpl/basics/contract.h>
|
||||
|
||||
#include <lz4.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <lz4.h>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
@@ -55,7 +53,7 @@ lz4Compress(void const* in, std::size_t inSize, BufferFactory&& bf)
|
||||
auto compressed = bf(outCapacity);
|
||||
|
||||
auto compressedSize = LZ4_compress_default(
|
||||
reinterpret_cast<char const*>(in),
|
||||
reinterpret_cast<const char*>(in),
|
||||
reinterpret_cast<char*>(compressed),
|
||||
inSize,
|
||||
outCapacity);
|
||||
@@ -89,7 +87,7 @@ lz4Decompress(
|
||||
Throw<std::runtime_error>("lz4Decompress: integer overflow (output)");
|
||||
|
||||
if (LZ4_decompress_safe(
|
||||
reinterpret_cast<char const*>(in),
|
||||
reinterpret_cast<const char*>(in),
|
||||
reinterpret_cast<char*>(decompressed),
|
||||
inSize,
|
||||
decompressedSize) != decompressedSize)
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#define RIPPLE_BASICS_COUNTEDOBJECT_H_INCLUDED
|
||||
|
||||
#include <xrpl/beast/type_name.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
@@ -24,7 +24,9 @@
|
||||
|
||||
#include <boost/outcome.hpp>
|
||||
|
||||
#include <concepts>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -93,7 +95,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
constexpr E const&
|
||||
constexpr const E&
|
||||
value() const&
|
||||
{
|
||||
return val_;
|
||||
@@ -111,7 +113,7 @@ public:
|
||||
return std::move(val_);
|
||||
}
|
||||
|
||||
constexpr E const&&
|
||||
constexpr const E&&
|
||||
value() const&&
|
||||
{
|
||||
return std::move(val_);
|
||||
|
||||
@@ -1,515 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2023 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_BASICS_INTRUSIVEPOINTER_H_INCLUDED
|
||||
#define RIPPLE_BASICS_INTRUSIVEPOINTER_H_INCLUDED
|
||||
|
||||
#include <concepts>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Tag to create an intrusive pointer from another intrusive pointer by using a
|
||||
static cast. This is useful to create an intrusive pointer to a derived
|
||||
class from an intrusive pointer to a base class.
|
||||
*/
|
||||
struct StaticCastTagSharedIntrusive
|
||||
{
|
||||
};
|
||||
|
||||
/** Tag to create an intrusive pointer from another intrusive pointer by using a
|
||||
dynamic cast. This is useful to create an intrusive pointer to a derived
|
||||
class from an intrusive pointer to a base class. If the cast fails an empty
|
||||
(null) intrusive pointer is created.
|
||||
*/
|
||||
struct DynamicCastTagSharedIntrusive
|
||||
{
|
||||
};
|
||||
|
||||
/** When creating or adopting a raw pointer, controls whether the strong count
|
||||
is incremented or not. Use this tag to increment the strong count.
|
||||
*/
|
||||
struct SharedIntrusiveAdoptIncrementStrongTag
|
||||
{
|
||||
};
|
||||
|
||||
/** When creating or adopting a raw pointer, controls whether the strong count
|
||||
is incremented or not. Use this tag to leave the strong count unchanged.
|
||||
*/
|
||||
struct SharedIntrusiveAdoptNoIncrementTag
|
||||
{
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
|
||||
template <class T>
|
||||
concept CAdoptTag = std::is_same_v<T, SharedIntrusiveAdoptIncrementStrongTag> ||
|
||||
std::is_same_v<T, SharedIntrusiveAdoptNoIncrementTag>;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** A shared intrusive pointer class that supports weak pointers.
|
||||
|
||||
This is meant to be used for SHAMapInnerNodes, but may be useful for other
|
||||
cases. Since the reference counts are stored on the pointee, the pointee is
|
||||
not destroyed until both the strong _and_ weak pointer counts go to zero.
|
||||
When the strong pointer count goes to zero, the "partialDestructor" is
|
||||
called. This can be used to destroy as much of the object as possible while
|
||||
still retaining the reference counts. For example, for SHAMapInnerNodes the
|
||||
children may be reset in that function. Note that std::shared_poiner WILL
|
||||
run the destructor when the strong count reaches zero, but may not free the
|
||||
memory used by the object until the weak count reaches zero. In rippled, we
|
||||
typically allocate shared pointers with the `make_shared` function. When
|
||||
that is used, the memory is not reclaimed until the weak count reaches zero.
|
||||
*/
|
||||
template <class T>
|
||||
class SharedIntrusive
|
||||
{
|
||||
public:
|
||||
SharedIntrusive() = default;
|
||||
|
||||
template <CAdoptTag TAdoptTag>
|
||||
SharedIntrusive(T* p, TAdoptTag) noexcept;
|
||||
|
||||
SharedIntrusive(SharedIntrusive const& rhs);
|
||||
|
||||
template <class TT>
|
||||
// TODO: convertible_to isn't quite right. That include a static castable.
|
||||
// Find the right concept.
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedIntrusive(SharedIntrusive<TT> const& rhs);
|
||||
|
||||
SharedIntrusive(SharedIntrusive&& rhs);
|
||||
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedIntrusive(SharedIntrusive<TT>&& rhs);
|
||||
|
||||
SharedIntrusive&
|
||||
operator=(SharedIntrusive const& rhs);
|
||||
|
||||
bool
|
||||
operator!=(std::nullptr_t) const;
|
||||
|
||||
bool
|
||||
operator==(std::nullptr_t) const;
|
||||
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedIntrusive&
|
||||
operator=(SharedIntrusive<TT> const& rhs);
|
||||
|
||||
SharedIntrusive&
|
||||
operator=(SharedIntrusive&& rhs);
|
||||
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedIntrusive&
|
||||
operator=(SharedIntrusive<TT>&& rhs);
|
||||
|
||||
/** Adopt the raw pointer. The strong reference may or may not be
|
||||
incremented, depending on the TAdoptTag
|
||||
*/
|
||||
template <CAdoptTag TAdoptTag = SharedIntrusiveAdoptIncrementStrongTag>
|
||||
void
|
||||
adopt(T* p);
|
||||
|
||||
~SharedIntrusive();
|
||||
|
||||
/** Create a new SharedIntrusive by statically casting the pointer
|
||||
controlled by the rhs param.
|
||||
*/
|
||||
template <class TT>
|
||||
SharedIntrusive(
|
||||
StaticCastTagSharedIntrusive,
|
||||
SharedIntrusive<TT> const& rhs);
|
||||
|
||||
/** Create a new SharedIntrusive by statically casting the pointer
|
||||
controlled by the rhs param.
|
||||
*/
|
||||
template <class TT>
|
||||
SharedIntrusive(StaticCastTagSharedIntrusive, SharedIntrusive<TT>&& rhs);
|
||||
|
||||
/** Create a new SharedIntrusive by dynamically casting the pointer
|
||||
controlled by the rhs param.
|
||||
*/
|
||||
template <class TT>
|
||||
SharedIntrusive(
|
||||
DynamicCastTagSharedIntrusive,
|
||||
SharedIntrusive<TT> const& rhs);
|
||||
|
||||
/** Create a new SharedIntrusive by dynamically casting the pointer
|
||||
controlled by the rhs param.
|
||||
*/
|
||||
template <class TT>
|
||||
SharedIntrusive(DynamicCastTagSharedIntrusive, SharedIntrusive<TT>&& rhs);
|
||||
|
||||
T&
|
||||
operator*() const noexcept;
|
||||
|
||||
T*
|
||||
operator->() const noexcept;
|
||||
|
||||
explicit
|
||||
operator bool() const noexcept;
|
||||
|
||||
/** Set the pointer to null, decrement the strong count, and run the
|
||||
appropriate release action.
|
||||
*/
|
||||
void
|
||||
reset();
|
||||
|
||||
/** Get the raw pointer */
|
||||
T*
|
||||
get() const;
|
||||
|
||||
/** Return the strong count */
|
||||
std::size_t
|
||||
use_count() const;
|
||||
|
||||
template <class TT, class... Args>
|
||||
friend SharedIntrusive<TT>
|
||||
make_SharedIntrusive(Args&&... args);
|
||||
|
||||
template <class TT>
|
||||
friend class SharedIntrusive;
|
||||
|
||||
template <class TT>
|
||||
friend class SharedWeakUnion;
|
||||
|
||||
template <class TT>
|
||||
friend class WeakIntrusive;
|
||||
|
||||
private:
|
||||
/** Return the raw pointer held by this object. */
|
||||
T*
|
||||
unsafeGetRawPtr() const;
|
||||
|
||||
/** Exchange the current raw pointer held by this object with the given
|
||||
pointer. Decrement the strong count of the raw pointer previously held
|
||||
by this object and run the appropriate release action.
|
||||
*/
|
||||
void
|
||||
unsafeReleaseAndStore(T* next);
|
||||
|
||||
/** Set the raw pointer directly. This is wrapped in a function so the class
|
||||
can support both atomic and non-atomic pointers in a future patch.
|
||||
*/
|
||||
void
|
||||
unsafeSetRawPtr(T* p);
|
||||
|
||||
/** Exchange the raw pointer directly.
|
||||
This sets the raw pointer to the given value and returns the previous
|
||||
value. This is wrapped in a function so the class can support both
|
||||
atomic and non-atomic pointers in a future patch.
|
||||
*/
|
||||
T*
|
||||
unsafeExchange(T* p);
|
||||
|
||||
/** pointer to the type with an intrusive count */
|
||||
T* ptr_{nullptr};
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** A weak intrusive pointer class for the SharedIntrusive pointer class.
|
||||
|
||||
Note that this weak pointer class asks differently from normal weak pointer
|
||||
classes. When the strong pointer count goes to zero, the "partialDestructor"
|
||||
is called. See the comment on SharedIntrusive for a fuller explanation.
|
||||
*/
|
||||
template <class T>
|
||||
class WeakIntrusive
|
||||
{
|
||||
public:
|
||||
WeakIntrusive() = default;
|
||||
|
||||
WeakIntrusive(WeakIntrusive const& rhs);
|
||||
|
||||
WeakIntrusive(WeakIntrusive&& rhs);
|
||||
|
||||
WeakIntrusive(SharedIntrusive<T> const& rhs);
|
||||
|
||||
// There is no move constructor from a strong intrusive ptr because
|
||||
// moving would be move expensive than copying in this case (the strong
|
||||
// ref would need to be decremented)
|
||||
WeakIntrusive(SharedIntrusive<T> const&& rhs) = delete;
|
||||
|
||||
// Since there are no current use cases for copy assignment in
|
||||
// WeakIntrusive, we delete this operator to simplify the implementation. If
|
||||
// a need arises in the future, we can reintroduce it with proper
|
||||
// consideration."
|
||||
WeakIntrusive&
|
||||
operator=(WeakIntrusive const&) = delete;
|
||||
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
WeakIntrusive&
|
||||
operator=(SharedIntrusive<TT> const& rhs);
|
||||
|
||||
/** Adopt the raw pointer and increment the weak count. */
|
||||
void
|
||||
adopt(T* ptr);
|
||||
|
||||
~WeakIntrusive();
|
||||
|
||||
/** Get a strong pointer from the weak pointer, if possible. This will
|
||||
only return a seated pointer if the strong count on the raw pointer
|
||||
is non-zero before locking.
|
||||
*/
|
||||
SharedIntrusive<T>
|
||||
lock() const;
|
||||
|
||||
/** Return true if the strong count is zero. */
|
||||
bool
|
||||
expired() const;
|
||||
|
||||
/** Set the pointer to null and decrement the weak count.
|
||||
|
||||
Note: This may run the destructor if the strong count is zero.
|
||||
*/
|
||||
void
|
||||
reset();
|
||||
|
||||
private:
|
||||
T* ptr_ = nullptr;
|
||||
|
||||
/** Decrement the weak count. This does _not_ set the raw pointer to
|
||||
null.
|
||||
|
||||
Note: This may run the destructor if the strong count is zero.
|
||||
*/
|
||||
void
|
||||
unsafeReleaseNoStore();
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** A combination of a strong and a weak intrusive pointer stored in the
|
||||
space of a single pointer.
|
||||
|
||||
This class is similar to a `std::variant<SharedIntrusive,WeakIntrusive>`
|
||||
with some optimizations. In particular, it uses a low-order bit to
|
||||
determine if the raw pointer represents a strong pointer or a weak
|
||||
pointer. It can also be quickly switched between its strong pointer and
|
||||
weak pointer representations. This class is useful for storing intrusive
|
||||
pointers in tagged caches.
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
class SharedWeakUnion
|
||||
{
|
||||
// Tagged pointer. Low bit determines if this is a strong or a weak
|
||||
// pointer. The low bit must be masked to zero when converting back to a
|
||||
// pointer. If the low bit is '1', this is a weak pointer.
|
||||
static_assert(
|
||||
alignof(T) >= 2,
|
||||
"Bad alignment: Combo pointer requires low bit to be zero");
|
||||
|
||||
public:
|
||||
SharedWeakUnion() = default;
|
||||
|
||||
SharedWeakUnion(SharedWeakUnion const& rhs);
|
||||
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedWeakUnion(SharedIntrusive<TT> const& rhs);
|
||||
|
||||
SharedWeakUnion(SharedWeakUnion&& rhs);
|
||||
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedWeakUnion(SharedIntrusive<TT>&& rhs);
|
||||
|
||||
SharedWeakUnion&
|
||||
operator=(SharedWeakUnion const& rhs);
|
||||
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedWeakUnion&
|
||||
operator=(SharedIntrusive<TT> const& rhs);
|
||||
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedWeakUnion&
|
||||
operator=(SharedIntrusive<TT>&& rhs);
|
||||
|
||||
~SharedWeakUnion();
|
||||
|
||||
/** Return a strong pointer if this is already a strong pointer (i.e.
|
||||
don't lock the weak pointer. Use the `lock` method if that's what's
|
||||
needed)
|
||||
*/
|
||||
SharedIntrusive<T>
|
||||
getStrong() const;
|
||||
|
||||
/** Return true if this is a strong pointer and the strong pointer is
|
||||
seated.
|
||||
*/
|
||||
explicit
|
||||
operator bool() const noexcept;
|
||||
|
||||
/** Set the pointer to null, decrement the appropriate ref count, and
|
||||
run the appropriate release action.
|
||||
*/
|
||||
void
|
||||
reset();
|
||||
|
||||
/** If this is a strong pointer, return the raw pointer. Otherwise
|
||||
return null.
|
||||
*/
|
||||
T*
|
||||
get() const;
|
||||
|
||||
/** If this is a strong pointer, return the strong count. Otherwise
|
||||
* return 0
|
||||
*/
|
||||
std::size_t
|
||||
use_count() const;
|
||||
|
||||
/** Return true if there is a non-zero strong count. */
|
||||
bool
|
||||
expired() const;
|
||||
|
||||
/** If this is a strong pointer, return the strong pointer. Otherwise
|
||||
attempt to lock the weak pointer.
|
||||
*/
|
||||
SharedIntrusive<T>
|
||||
lock() const;
|
||||
|
||||
/** Return true is this represents a strong pointer. */
|
||||
bool
|
||||
isStrong() const;
|
||||
|
||||
/** Return true is this represents a weak pointer. */
|
||||
bool
|
||||
isWeak() const;
|
||||
|
||||
/** If this is a weak pointer, attempt to convert it to a strong
|
||||
pointer.
|
||||
|
||||
@return true if successfully converted to a strong pointer (or was
|
||||
already a strong pointer). Otherwise false.
|
||||
*/
|
||||
bool
|
||||
convertToStrong();
|
||||
|
||||
/** If this is a strong pointer, attempt to convert it to a weak
|
||||
pointer.
|
||||
|
||||
@return false if the pointer is null. Otherwise return true.
|
||||
*/
|
||||
bool
|
||||
convertToWeak();
|
||||
|
||||
private:
|
||||
// Tagged pointer. Low bit determines if this is a strong or a weak
|
||||
// pointer. The low bit must be masked to zero when converting back to a
|
||||
// pointer. If the low bit is '1', this is a weak pointer.
|
||||
std::uintptr_t tp_{0};
|
||||
static constexpr std::uintptr_t tagMask = 1;
|
||||
static constexpr std::uintptr_t ptrMask = ~tagMask;
|
||||
|
||||
private:
|
||||
/** Return the raw pointer held by this object.
|
||||
*/
|
||||
T*
|
||||
unsafeGetRawPtr() const;
|
||||
|
||||
enum class RefStrength { strong, weak };
|
||||
/** Set the raw pointer and tag bit directly.
|
||||
*/
|
||||
void
|
||||
unsafeSetRawPtr(T* p, RefStrength rs);
|
||||
|
||||
/** Set the raw pointer and tag bit to all zeros (strong null pointer).
|
||||
*/
|
||||
void unsafeSetRawPtr(std::nullptr_t);
|
||||
|
||||
/** Decrement the appropriate ref count, and run the appropriate release
|
||||
action. Note: this does _not_ set the raw pointer to null.
|
||||
*/
|
||||
void
|
||||
unsafeReleaseNoStore();
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Create a shared intrusive pointer.
|
||||
|
||||
Note: unlike std::shared_ptr, where there is an advantage of allocating
|
||||
the pointer and control block together, there is no benefit for intrusive
|
||||
pointers.
|
||||
*/
|
||||
template <class TT, class... Args>
|
||||
SharedIntrusive<TT>
|
||||
make_SharedIntrusive(Args&&... args)
|
||||
{
|
||||
auto p = new TT(std::forward<Args>(args)...);
|
||||
|
||||
static_assert(
|
||||
noexcept(SharedIntrusive<TT>(
|
||||
std::declval<TT*>(),
|
||||
std::declval<SharedIntrusiveAdoptNoIncrementTag>())),
|
||||
"SharedIntrusive constructor should not throw or this can leak "
|
||||
"memory");
|
||||
|
||||
return SharedIntrusive<TT>(p, SharedIntrusiveAdoptNoIncrementTag{});
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace intr_ptr {
|
||||
template <class T>
|
||||
using SharedPtr = SharedIntrusive<T>;
|
||||
|
||||
template <class T>
|
||||
using WeakPtr = WeakIntrusive<T>;
|
||||
|
||||
template <class T>
|
||||
using SharedWeakUnionPtr = SharedWeakUnion<T>;
|
||||
|
||||
template <class T, class... A>
|
||||
SharedPtr<T>
|
||||
make_shared(A&&... args)
|
||||
{
|
||||
return make_SharedIntrusive<T>(std::forward<A>(args)...);
|
||||
}
|
||||
|
||||
template <class T, class TT>
|
||||
SharedPtr<T>
|
||||
static_pointer_cast(TT const& v)
|
||||
{
|
||||
return SharedPtr<T>(StaticCastTagSharedIntrusive{}, v);
|
||||
}
|
||||
|
||||
template <class T, class TT>
|
||||
SharedPtr<T>
|
||||
dynamic_pointer_cast(TT const& v)
|
||||
{
|
||||
return SharedPtr<T>(DynamicCastTagSharedIntrusive{}, v);
|
||||
}
|
||||
} // namespace intr_ptr
|
||||
} // namespace ripple
|
||||
#endif
|
||||
@@ -1,742 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2023 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_BASICS_INTRUSIVEPOINTER_IPP_INCLUDED
|
||||
#define RIPPLE_BASICS_INTRUSIVEPOINTER_IPP_INCLUDED
|
||||
|
||||
#include <xrpl/basics/IntrusivePointer.h>
|
||||
#include <xrpl/basics/IntrusiveRefCounts.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
template <class T>
|
||||
template <CAdoptTag TAdoptTag>
|
||||
SharedIntrusive<T>::SharedIntrusive(T* p, TAdoptTag) noexcept : ptr_{p}
|
||||
{
|
||||
if constexpr (std::is_same_v<
|
||||
TAdoptTag,
|
||||
SharedIntrusiveAdoptIncrementStrongTag>)
|
||||
{
|
||||
if (p)
|
||||
p->addStrongRef();
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SharedIntrusive<T>::SharedIntrusive(SharedIntrusive const& rhs)
|
||||
: ptr_{[&] {
|
||||
auto p = rhs.unsafeGetRawPtr();
|
||||
if (p)
|
||||
p->addStrongRef();
|
||||
return p;
|
||||
}()}
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedIntrusive<T>::SharedIntrusive(SharedIntrusive<TT> const& rhs)
|
||||
: ptr_{[&] {
|
||||
auto p = rhs.unsafeGetRawPtr();
|
||||
if (p)
|
||||
p->addStrongRef();
|
||||
return p;
|
||||
}()}
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SharedIntrusive<T>::SharedIntrusive(SharedIntrusive&& rhs)
|
||||
: ptr_{rhs.unsafeExchange(nullptr)}
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedIntrusive<T>::SharedIntrusive(SharedIntrusive<TT>&& rhs)
|
||||
: ptr_{rhs.unsafeExchange(nullptr)}
|
||||
{
|
||||
}
|
||||
template <class T>
|
||||
SharedIntrusive<T>&
|
||||
SharedIntrusive<T>::operator=(SharedIntrusive const& rhs)
|
||||
{
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
auto p = rhs.unsafeGetRawPtr();
|
||||
if (p)
|
||||
p->addStrongRef();
|
||||
unsafeReleaseAndStore(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
// clang-format off
|
||||
requires std::convertible_to<TT*, T*>
|
||||
// clang-format on
|
||||
SharedIntrusive<T>&
|
||||
SharedIntrusive<T>::operator=(SharedIntrusive<TT> const& rhs)
|
||||
{
|
||||
if constexpr (std::is_same_v<T, TT>)
|
||||
{
|
||||
// This case should never be hit. The operator above will run instead.
|
||||
// (The normal operator= is needed or it will be marked `deleted`)
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
}
|
||||
auto p = rhs.unsafeGetRawPtr();
|
||||
if (p)
|
||||
p->addStrongRef();
|
||||
unsafeReleaseAndStore(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SharedIntrusive<T>&
|
||||
SharedIntrusive<T>::operator=(SharedIntrusive&& rhs)
|
||||
{
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
|
||||
unsafeReleaseAndStore(rhs.unsafeExchange(nullptr));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
// clang-format off
|
||||
requires std::convertible_to<TT*, T*>
|
||||
// clang-format on
|
||||
SharedIntrusive<T>&
|
||||
SharedIntrusive<T>::operator=(SharedIntrusive<TT>&& rhs)
|
||||
{
|
||||
static_assert(
|
||||
!std::is_same_v<T, TT>,
|
||||
"This overload should not be instantiated for T == TT");
|
||||
|
||||
unsafeReleaseAndStore(rhs.unsafeExchange(nullptr));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
SharedIntrusive<T>::operator!=(std::nullptr_t) const
|
||||
{
|
||||
return this->get() != nullptr;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
SharedIntrusive<T>::operator==(std::nullptr_t) const
|
||||
{
|
||||
return this->get() == nullptr;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <CAdoptTag TAdoptTag>
|
||||
void
|
||||
SharedIntrusive<T>::adopt(T* p)
|
||||
{
|
||||
if constexpr (std::is_same_v<
|
||||
TAdoptTag,
|
||||
SharedIntrusiveAdoptIncrementStrongTag>)
|
||||
{
|
||||
if (p)
|
||||
p->addStrongRef();
|
||||
}
|
||||
unsafeReleaseAndStore(p);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SharedIntrusive<T>::~SharedIntrusive()
|
||||
{
|
||||
unsafeReleaseAndStore(nullptr);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
SharedIntrusive<T>::SharedIntrusive(
|
||||
StaticCastTagSharedIntrusive,
|
||||
SharedIntrusive<TT> const& rhs)
|
||||
: ptr_{[&] {
|
||||
auto p = static_cast<T*>(rhs.unsafeGetRawPtr());
|
||||
if (p)
|
||||
p->addStrongRef();
|
||||
return p;
|
||||
}()}
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
SharedIntrusive<T>::SharedIntrusive(
|
||||
StaticCastTagSharedIntrusive,
|
||||
SharedIntrusive<TT>&& rhs)
|
||||
: ptr_{static_cast<T*>(rhs.unsafeExchange(nullptr))}
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
SharedIntrusive<T>::SharedIntrusive(
|
||||
DynamicCastTagSharedIntrusive,
|
||||
SharedIntrusive<TT> const& rhs)
|
||||
: ptr_{[&] {
|
||||
auto p = dynamic_cast<T*>(rhs.unsafeGetRawPtr());
|
||||
if (p)
|
||||
p->addStrongRef();
|
||||
return p;
|
||||
}()}
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
SharedIntrusive<T>::SharedIntrusive(
|
||||
DynamicCastTagSharedIntrusive,
|
||||
SharedIntrusive<TT>&& rhs)
|
||||
{
|
||||
// This can be simplified without the `exchange`, but the `exchange` is kept
|
||||
// in anticipation of supporting atomic operations.
|
||||
auto toSet = rhs.unsafeExchange(nullptr);
|
||||
if (toSet)
|
||||
{
|
||||
ptr_ = dynamic_cast<T*>(toSet);
|
||||
if (!ptr_)
|
||||
// need to set the pointer back or will leak
|
||||
rhs.unsafeExchange(toSet);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T&
|
||||
SharedIntrusive<T>::operator*() const noexcept
|
||||
{
|
||||
return *unsafeGetRawPtr();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T*
|
||||
SharedIntrusive<T>::operator->() const noexcept
|
||||
{
|
||||
return unsafeGetRawPtr();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SharedIntrusive<T>::operator bool() const noexcept
|
||||
{
|
||||
return bool(unsafeGetRawPtr());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
SharedIntrusive<T>::reset()
|
||||
{
|
||||
unsafeReleaseAndStore(nullptr);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T*
|
||||
SharedIntrusive<T>::get() const
|
||||
{
|
||||
return unsafeGetRawPtr();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::size_t
|
||||
SharedIntrusive<T>::use_count() const
|
||||
{
|
||||
if (auto p = unsafeGetRawPtr())
|
||||
return p->use_count();
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T*
|
||||
SharedIntrusive<T>::unsafeGetRawPtr() const
|
||||
{
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
SharedIntrusive<T>::unsafeSetRawPtr(T* p)
|
||||
{
|
||||
ptr_ = p;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T*
|
||||
SharedIntrusive<T>::unsafeExchange(T* p)
|
||||
{
|
||||
return std::exchange(ptr_, p);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
SharedIntrusive<T>::unsafeReleaseAndStore(T* next)
|
||||
{
|
||||
auto prev = unsafeExchange(next);
|
||||
if (!prev)
|
||||
return;
|
||||
|
||||
using enum ReleaseStrongRefAction;
|
||||
auto action = prev->releaseStrongRef();
|
||||
switch (action)
|
||||
{
|
||||
case noop:
|
||||
break;
|
||||
case destroy:
|
||||
delete prev;
|
||||
break;
|
||||
case partialDestroy:
|
||||
prev->partialDestructor();
|
||||
partialDestructorFinished(&prev);
|
||||
// prev is null and may no longer be used
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class T>
|
||||
WeakIntrusive<T>::WeakIntrusive(WeakIntrusive const& rhs) : ptr_{rhs.ptr_}
|
||||
{
|
||||
if (ptr_)
|
||||
ptr_->addWeakRef();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
WeakIntrusive<T>::WeakIntrusive(WeakIntrusive&& rhs) : ptr_{rhs.ptr_}
|
||||
{
|
||||
rhs.ptr_ = nullptr;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
WeakIntrusive<T>::WeakIntrusive(SharedIntrusive<T> const& rhs)
|
||||
: ptr_{rhs.unsafeGetRawPtr()}
|
||||
{
|
||||
if (ptr_)
|
||||
ptr_->addWeakRef();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
// clang-format off
|
||||
requires std::convertible_to<TT*, T*>
|
||||
// clang-format on
|
||||
WeakIntrusive<T>&
|
||||
WeakIntrusive<T>::operator=(SharedIntrusive<TT> const& rhs)
|
||||
{
|
||||
unsafeReleaseNoStore();
|
||||
auto p = rhs.unsafeGetRawPtr();
|
||||
if (p)
|
||||
p->addWeakRef();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
WeakIntrusive<T>::adopt(T* ptr)
|
||||
{
|
||||
unsafeReleaseNoStore();
|
||||
if (ptr)
|
||||
ptr->addWeakRef();
|
||||
ptr_ = ptr;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
WeakIntrusive<T>::~WeakIntrusive()
|
||||
{
|
||||
unsafeReleaseNoStore();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SharedIntrusive<T>
|
||||
WeakIntrusive<T>::lock() const
|
||||
{
|
||||
if (ptr_ && ptr_->checkoutStrongRefFromWeak())
|
||||
{
|
||||
return SharedIntrusive<T>{ptr_, SharedIntrusiveAdoptNoIncrementTag{}};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
WeakIntrusive<T>::expired() const
|
||||
{
|
||||
return (!ptr_ || ptr_->expired());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
WeakIntrusive<T>::reset()
|
||||
{
|
||||
unsafeReleaseNoStore();
|
||||
ptr_ = nullptr;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
WeakIntrusive<T>::unsafeReleaseNoStore()
|
||||
{
|
||||
if (!ptr_)
|
||||
return;
|
||||
|
||||
using enum ReleaseWeakRefAction;
|
||||
auto action = ptr_->releaseWeakRef();
|
||||
switch (action)
|
||||
{
|
||||
case noop:
|
||||
break;
|
||||
case destroy:
|
||||
delete ptr_;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class T>
|
||||
SharedWeakUnion<T>::SharedWeakUnion(SharedWeakUnion const& rhs) : tp_{rhs.tp_}
|
||||
{
|
||||
auto p = rhs.unsafeGetRawPtr();
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
if (rhs.isStrong())
|
||||
p->addStrongRef();
|
||||
else
|
||||
p->addWeakRef();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedWeakUnion<T>::SharedWeakUnion(SharedIntrusive<TT> const& rhs)
|
||||
{
|
||||
auto p = rhs.unsafeGetRawPtr();
|
||||
if (p)
|
||||
p->addStrongRef();
|
||||
unsafeSetRawPtr(p, RefStrength::strong);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SharedWeakUnion<T>::SharedWeakUnion(SharedWeakUnion&& rhs) : tp_{rhs.tp_}
|
||||
{
|
||||
rhs.unsafeSetRawPtr(nullptr);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedWeakUnion<T>::SharedWeakUnion(SharedIntrusive<TT>&& rhs)
|
||||
{
|
||||
auto p = rhs.unsafeGetRawPtr();
|
||||
if (p)
|
||||
unsafeSetRawPtr(p, RefStrength::strong);
|
||||
rhs.unsafeSetRawPtr(nullptr);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SharedWeakUnion<T>&
|
||||
SharedWeakUnion<T>::operator=(SharedWeakUnion const& rhs)
|
||||
{
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
unsafeReleaseNoStore();
|
||||
|
||||
if (auto p = rhs.unsafeGetRawPtr())
|
||||
{
|
||||
if (rhs.isStrong())
|
||||
{
|
||||
p->addStrongRef();
|
||||
unsafeSetRawPtr(p, RefStrength::strong);
|
||||
}
|
||||
else
|
||||
{
|
||||
p->addWeakRef();
|
||||
unsafeSetRawPtr(p, RefStrength::weak);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsafeSetRawPtr(nullptr);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
// clang-format off
|
||||
requires std::convertible_to<TT*, T*>
|
||||
// clang-format on
|
||||
SharedWeakUnion<T>&
|
||||
SharedWeakUnion<T>::operator=(SharedIntrusive<TT> const& rhs)
|
||||
{
|
||||
unsafeReleaseNoStore();
|
||||
auto p = rhs.unsafeGetRawPtr();
|
||||
if (p)
|
||||
p->addStrongRef();
|
||||
unsafeSetRawPtr(p, RefStrength::strong);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
// clang-format off
|
||||
requires std::convertible_to<TT*, T*>
|
||||
// clang-format on
|
||||
SharedWeakUnion<T>&
|
||||
SharedWeakUnion<T>::operator=(SharedIntrusive<TT>&& rhs)
|
||||
{
|
||||
unsafeReleaseNoStore();
|
||||
unsafeSetRawPtr(rhs.unsafeGetRawPtr(), RefStrength::strong);
|
||||
rhs.unsafeSetRawPtr(nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SharedWeakUnion<T>::~SharedWeakUnion()
|
||||
{
|
||||
unsafeReleaseNoStore();
|
||||
};
|
||||
|
||||
// Return a strong pointer if this is already a strong pointer (i.e. don't
|
||||
// lock the weak pointer. Use the `lock` method if that's what's needed)
|
||||
template <class T>
|
||||
SharedIntrusive<T>
|
||||
SharedWeakUnion<T>::getStrong() const
|
||||
{
|
||||
SharedIntrusive<T> result;
|
||||
auto p = unsafeGetRawPtr();
|
||||
if (p && isStrong())
|
||||
{
|
||||
result.template adopt<SharedIntrusiveAdoptIncrementStrongTag>(p);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SharedWeakUnion<T>::operator bool() const noexcept
|
||||
{
|
||||
return bool(get());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
SharedWeakUnion<T>::reset()
|
||||
{
|
||||
unsafeReleaseNoStore();
|
||||
unsafeSetRawPtr(nullptr);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T*
|
||||
SharedWeakUnion<T>::get() const
|
||||
{
|
||||
return isStrong() ? unsafeGetRawPtr() : nullptr;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::size_t
|
||||
SharedWeakUnion<T>::use_count() const
|
||||
{
|
||||
if (auto p = get())
|
||||
return p->use_count();
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
SharedWeakUnion<T>::expired() const
|
||||
{
|
||||
auto p = unsafeGetRawPtr();
|
||||
return (!p || p->expired());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SharedIntrusive<T>
|
||||
SharedWeakUnion<T>::lock() const
|
||||
{
|
||||
SharedIntrusive<T> result;
|
||||
auto p = unsafeGetRawPtr();
|
||||
if (!p)
|
||||
return result;
|
||||
|
||||
if (isStrong())
|
||||
{
|
||||
result.template adopt<SharedIntrusiveAdoptIncrementStrongTag>(p);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (p->checkoutStrongRefFromWeak())
|
||||
{
|
||||
result.template adopt<SharedIntrusiveAdoptNoIncrementTag>(p);
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
SharedWeakUnion<T>::isStrong() const
|
||||
{
|
||||
return !(tp_ & tagMask);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
SharedWeakUnion<T>::isWeak() const
|
||||
{
|
||||
return tp_ & tagMask;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
SharedWeakUnion<T>::convertToStrong()
|
||||
{
|
||||
if (isStrong())
|
||||
return true;
|
||||
|
||||
auto p = unsafeGetRawPtr();
|
||||
if (p && p->checkoutStrongRefFromWeak())
|
||||
{
|
||||
[[maybe_unused]] auto action = p->releaseWeakRef();
|
||||
XRPL_ASSERT(
|
||||
(action == ReleaseWeakRefAction::noop),
|
||||
"ripple::SharedWeakUnion::convertToStrong : "
|
||||
"action is noop");
|
||||
unsafeSetRawPtr(p, RefStrength::strong);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
SharedWeakUnion<T>::convertToWeak()
|
||||
{
|
||||
if (isWeak())
|
||||
return true;
|
||||
|
||||
auto p = unsafeGetRawPtr();
|
||||
if (!p)
|
||||
return false;
|
||||
|
||||
using enum ReleaseStrongRefAction;
|
||||
auto action = p->addWeakReleaseStrongRef();
|
||||
switch (action)
|
||||
{
|
||||
case noop:
|
||||
break;
|
||||
case destroy:
|
||||
// We just added a weak ref. How could we destroy?
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE(
|
||||
"ripple::SharedWeakUnion::convertToWeak : destroying freshly "
|
||||
"added ref");
|
||||
delete p;
|
||||
unsafeSetRawPtr(nullptr);
|
||||
return true; // Should never happen
|
||||
// LCOV_EXCL_STOP
|
||||
case partialDestroy:
|
||||
// This is a weird case. We just converted the last strong
|
||||
// pointer to a weak pointer.
|
||||
p->partialDestructor();
|
||||
partialDestructorFinished(&p);
|
||||
// p is null and may no longer be used
|
||||
break;
|
||||
}
|
||||
unsafeSetRawPtr(p, RefStrength::weak);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T*
|
||||
SharedWeakUnion<T>::unsafeGetRawPtr() const
|
||||
{
|
||||
return reinterpret_cast<T*>(tp_ & ptrMask);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
SharedWeakUnion<T>::unsafeSetRawPtr(T* p, RefStrength rs)
|
||||
{
|
||||
tp_ = reinterpret_cast<std::uintptr_t>(p);
|
||||
if (tp_ && rs == RefStrength::weak)
|
||||
tp_ |= tagMask;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
SharedWeakUnion<T>::unsafeSetRawPtr(std::nullptr_t)
|
||||
{
|
||||
tp_ = 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
SharedWeakUnion<T>::unsafeReleaseNoStore()
|
||||
{
|
||||
auto p = unsafeGetRawPtr();
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
if (isStrong())
|
||||
{
|
||||
using enum ReleaseStrongRefAction;
|
||||
auto strongAction = p->releaseStrongRef();
|
||||
switch (strongAction)
|
||||
{
|
||||
case noop:
|
||||
break;
|
||||
case destroy:
|
||||
delete p;
|
||||
break;
|
||||
case partialDestroy:
|
||||
p->partialDestructor();
|
||||
partialDestructorFinished(&p);
|
||||
// p is null and may no longer be used
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using enum ReleaseWeakRefAction;
|
||||
auto weakAction = p->releaseWeakRef();
|
||||
switch (weakAction)
|
||||
{
|
||||
case noop:
|
||||
break;
|
||||
case destroy:
|
||||
delete p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
#endif
|
||||
@@ -1,502 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2023 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_BASICS_INTRUSIVEREFCOUNTS_H_INCLUDED
|
||||
#define RIPPLE_BASICS_INTRUSIVEREFCOUNTS_H_INCLUDED
|
||||
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** Action to perform when releasing a strong pointer.
|
||||
|
||||
noop: Do nothing. For example, a `noop` action will occur when a count is
|
||||
decremented to a non-zero value.
|
||||
|
||||
partialDestroy: Run the `partialDestructor`. This action will happen when a
|
||||
strong count is decremented to zero and the weak count is non-zero.
|
||||
|
||||
destroy: Run the destructor. This action will occur when either the strong
|
||||
count or weak count is decremented and the other count is also zero.
|
||||
*/
|
||||
enum class ReleaseStrongRefAction { noop, partialDestroy, destroy };
|
||||
|
||||
/** Action to perform when releasing a weak pointer.
|
||||
|
||||
noop: Do nothing. For example, a `noop` action will occur when a count is
|
||||
decremented to a non-zero value.
|
||||
|
||||
destroy: Run the destructor. This action will occur when either the strong
|
||||
count or weak count is decremented and the other count is also zero.
|
||||
*/
|
||||
enum class ReleaseWeakRefAction { noop, destroy };
|
||||
|
||||
/** Implement the strong count, weak count, and bit flags for an intrusive
|
||||
pointer.
|
||||
|
||||
A class can satisfy the requirements of a ripple::IntrusivePointer by
|
||||
inheriting from this class.
|
||||
*/
|
||||
struct IntrusiveRefCounts
|
||||
{
|
||||
virtual ~IntrusiveRefCounts() noexcept;
|
||||
|
||||
// This must be `noexcept` or the make_SharedIntrusive function could leak
|
||||
// memory.
|
||||
void
|
||||
addStrongRef() const noexcept;
|
||||
|
||||
void
|
||||
addWeakRef() const noexcept;
|
||||
|
||||
ReleaseStrongRefAction
|
||||
releaseStrongRef() const;
|
||||
|
||||
// Same as:
|
||||
// {
|
||||
// addWeakRef();
|
||||
// return releaseStrongRef;
|
||||
// }
|
||||
// done as one atomic operation
|
||||
ReleaseStrongRefAction
|
||||
addWeakReleaseStrongRef() const;
|
||||
|
||||
ReleaseWeakRefAction
|
||||
releaseWeakRef() const;
|
||||
|
||||
// Returns true is able to checkout a strong ref. False otherwise
|
||||
bool
|
||||
checkoutStrongRefFromWeak() const noexcept;
|
||||
|
||||
bool
|
||||
expired() const noexcept;
|
||||
|
||||
std::size_t
|
||||
use_count() const noexcept;
|
||||
|
||||
// This function MUST be called after a partial destructor finishes running.
|
||||
// Calling this function may cause other threads to delete the object
|
||||
// pointed to by `o`, so `o` should never be used after calling this
|
||||
// function. The parameter will be set to a `nullptr` after calling this
|
||||
// function to emphasize that it should not be used.
|
||||
// Note: This is intentionally NOT called at the end of `partialDestructor`.
|
||||
// The reason for this is if new classes are written to support this smart
|
||||
// pointer class, they need to write their own `partialDestructor` function
|
||||
// and ensure `partialDestructorFinished` is called at the end. Putting this
|
||||
// call inside the smart pointer class itself is expected to be less error
|
||||
// prone.
|
||||
// Note: The "two-star" programming is intentional. It emphasizes that `o`
|
||||
// may be deleted and the unergonomic API is meant to signal the special
|
||||
// nature of this function call to callers.
|
||||
// Note: This is a template to support incompletely defined classes.
|
||||
template <class T>
|
||||
friend void
|
||||
partialDestructorFinished(T** o);
|
||||
|
||||
private:
|
||||
// TODO: We may need to use a uint64_t for both counts. This will reduce the
|
||||
// memory savings. We need to audit the code to make sure 16 bit counts are
|
||||
// enough for strong pointers and 14 bit counts are enough for weak
|
||||
// pointers. Use type aliases to make it easy to switch types.
|
||||
using CountType = std::uint16_t;
|
||||
static constexpr size_t StrongCountNumBits = sizeof(CountType) * 8;
|
||||
static constexpr size_t WeakCountNumBits = StrongCountNumBits - 2;
|
||||
using FieldType = std::uint32_t;
|
||||
static constexpr size_t FieldTypeBits = sizeof(FieldType) * 8;
|
||||
static constexpr FieldType one = 1;
|
||||
|
||||
/** `refCounts` consists of four fields that are treated atomically:
|
||||
|
||||
1. Strong count. This is a count of the number of shared pointers that
|
||||
hold a reference to this object. When the strong counts goes to zero,
|
||||
if the weak count is zero, the destructor is run. If the weak count is
|
||||
non-zero when the strong count goes to zero then the partialDestructor
|
||||
is run.
|
||||
|
||||
2. Weak count. This is a count of the number of weak pointer that hold
|
||||
a reference to this object. When the weak count goes to zero and the
|
||||
strong count is also zero, then the destructor is run.
|
||||
|
||||
3. Partial destroy started bit. This bit is set if the
|
||||
`partialDestructor` function has been started (or is about to be
|
||||
started). This is used to prevent the destructor from running
|
||||
concurrently with the partial destructor. This can easily happen when
|
||||
the last strong pointer release its reference in one thread and starts
|
||||
the partialDestructor, while in another thread the last weak pointer
|
||||
goes out of scope and starts the destructor while the partialDestructor
|
||||
is still running. Both a start and finished bit is needed to handle a
|
||||
corner-case where the last strong pointer goes out of scope, then then
|
||||
last `weakPointer` goes out of scope, but this happens before the
|
||||
`partialDestructor` bit is set. It would be possible to use a single
|
||||
bit if it could also be set atomically when the strong count goes to
|
||||
zero and the weak count is non-zero, but that would add complexity (and
|
||||
likely slow down common cases as well).
|
||||
|
||||
4. Partial destroy finished bit. This bit is set when the
|
||||
`partialDestructor` has finished running. See (3) above for more
|
||||
information.
|
||||
|
||||
*/
|
||||
|
||||
mutable std::atomic<FieldType> refCounts{strongDelta};
|
||||
|
||||
/** Amount to change the strong count when adding or releasing a reference
|
||||
|
||||
Note: The strong count is stored in the low `StrongCountNumBits` bits
|
||||
of refCounts
|
||||
*/
|
||||
static constexpr FieldType strongDelta = 1;
|
||||
|
||||
/** Amount to change the weak count when adding or releasing a reference
|
||||
|
||||
Note: The weak count is stored in the high `WeakCountNumBits` bits of
|
||||
refCounts
|
||||
*/
|
||||
static constexpr FieldType weakDelta = (one << StrongCountNumBits);
|
||||
|
||||
/** Flag that is set when the partialDestroy function has started running
|
||||
(or is about to start running).
|
||||
|
||||
See description of the `refCounts` field for a fuller description of
|
||||
this field.
|
||||
*/
|
||||
static constexpr FieldType partialDestroyStartedMask =
|
||||
(one << (FieldTypeBits - 1));
|
||||
|
||||
/** Flag that is set when the partialDestroy function has finished running
|
||||
|
||||
See description of the `refCounts` field for a fuller description of
|
||||
this field.
|
||||
*/
|
||||
static constexpr FieldType partialDestroyFinishedMask =
|
||||
(one << (FieldTypeBits - 2));
|
||||
|
||||
/** Mask that will zero out all the `count` bits and leave the tag bits
|
||||
unchanged.
|
||||
*/
|
||||
static constexpr FieldType tagMask =
|
||||
partialDestroyStartedMask | partialDestroyFinishedMask;
|
||||
|
||||
/** Mask that will zero out the `tag` bits and leave the count bits
|
||||
unchanged.
|
||||
*/
|
||||
static constexpr FieldType valueMask = ~tagMask;
|
||||
|
||||
/** Mask that will zero out everything except the strong count.
|
||||
*/
|
||||
static constexpr FieldType strongMask =
|
||||
((one << StrongCountNumBits) - 1) & valueMask;
|
||||
|
||||
/** Mask that will zero out everything except the weak count.
|
||||
*/
|
||||
static constexpr FieldType weakMask =
|
||||
(((one << WeakCountNumBits) - 1) << StrongCountNumBits) & valueMask;
|
||||
|
||||
/** Unpack the count and tag fields from the packed atomic integer form. */
|
||||
struct RefCountPair
|
||||
{
|
||||
CountType strong;
|
||||
CountType weak;
|
||||
/** The `partialDestroyStartedBit` is set to on when the partial
|
||||
destroy function is started. It is not a boolean; it is a uint32
|
||||
with all bits zero with the possible exception of the
|
||||
`partialDestroyStartedMask` bit. This is done so it can be directly
|
||||
masked into the `combinedValue`.
|
||||
*/
|
||||
FieldType partialDestroyStartedBit{0};
|
||||
/** The `partialDestroyFinishedBit` is set to on when the partial
|
||||
destroy function has finished.
|
||||
*/
|
||||
FieldType partialDestroyFinishedBit{0};
|
||||
RefCountPair(FieldType v) noexcept;
|
||||
RefCountPair(CountType s, CountType w) noexcept;
|
||||
|
||||
/** Convert back to the packed integer form. */
|
||||
FieldType
|
||||
combinedValue() const noexcept;
|
||||
|
||||
static constexpr CountType maxStrongValue =
|
||||
static_cast<CountType>((one << StrongCountNumBits) - 1);
|
||||
static constexpr CountType maxWeakValue =
|
||||
static_cast<CountType>((one << WeakCountNumBits) - 1);
|
||||
/** Put an extra margin to detect when running up against limits.
|
||||
This is only used in debug code, and is useful if we reduce the
|
||||
number of bits in the strong and weak counts (to 16 and 14 bits).
|
||||
*/
|
||||
static constexpr CountType checkStrongMaxValue = maxStrongValue - 32;
|
||||
static constexpr CountType checkWeakMaxValue = maxWeakValue - 32;
|
||||
};
|
||||
};
|
||||
|
||||
inline void
|
||||
IntrusiveRefCounts::addStrongRef() const noexcept
|
||||
{
|
||||
refCounts.fetch_add(strongDelta, std::memory_order_acq_rel);
|
||||
}
|
||||
|
||||
inline void
|
||||
IntrusiveRefCounts::addWeakRef() const noexcept
|
||||
{
|
||||
refCounts.fetch_add(weakDelta, std::memory_order_acq_rel);
|
||||
}
|
||||
|
||||
inline ReleaseStrongRefAction
|
||||
IntrusiveRefCounts::releaseStrongRef() const
|
||||
{
|
||||
// Subtract `strongDelta` from refCounts. If this releases the last strong
|
||||
// ref, set the `partialDestroyStarted` bit. It is important that the ref
|
||||
// count and the `partialDestroyStartedBit` are changed atomically (hence
|
||||
// the loop and `compare_exchange` op). If this didn't need to be done
|
||||
// atomically, the loop could be replaced with a `fetch_sub` and a
|
||||
// conditional `fetch_or`. This loop will almost always run once.
|
||||
|
||||
using enum ReleaseStrongRefAction;
|
||||
auto prevIntVal = refCounts.load(std::memory_order_acquire);
|
||||
while (1)
|
||||
{
|
||||
RefCountPair const prevVal{prevIntVal};
|
||||
XRPL_ASSERT(
|
||||
(prevVal.strong >= strongDelta),
|
||||
"ripple::IntrusiveRefCounts::releaseStrongRef : previous ref "
|
||||
"higher than new");
|
||||
auto nextIntVal = prevIntVal - strongDelta;
|
||||
ReleaseStrongRefAction action = noop;
|
||||
if (prevVal.strong == 1)
|
||||
{
|
||||
if (prevVal.weak == 0)
|
||||
{
|
||||
action = destroy;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextIntVal |= partialDestroyStartedMask;
|
||||
action = partialDestroy;
|
||||
}
|
||||
}
|
||||
|
||||
if (refCounts.compare_exchange_weak(
|
||||
prevIntVal, nextIntVal, std::memory_order_acq_rel))
|
||||
{
|
||||
// Can't be in partial destroy because only decrementing the strong
|
||||
// count to zero can start a partial destroy, and that can't happen
|
||||
// twice.
|
||||
XRPL_ASSERT(
|
||||
(action == noop) || !(prevIntVal & partialDestroyStartedMask),
|
||||
"ripple::IntrusiveRefCounts::releaseStrongRef : not in partial "
|
||||
"destroy");
|
||||
return action;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline ReleaseStrongRefAction
|
||||
IntrusiveRefCounts::addWeakReleaseStrongRef() const
|
||||
{
|
||||
using enum ReleaseStrongRefAction;
|
||||
|
||||
static_assert(weakDelta > strongDelta);
|
||||
auto constexpr delta = weakDelta - strongDelta;
|
||||
auto prevIntVal = refCounts.load(std::memory_order_acquire);
|
||||
// This loop will almost always run once. The loop is needed to atomically
|
||||
// change the counts and flags (the count could be atomically changed, but
|
||||
// the flags depend on the current value of the counts).
|
||||
//
|
||||
// Note: If this becomes a perf bottleneck, the `partialDestoryStartedMask`
|
||||
// may be able to be set non-atomically. But it is easier to reason about
|
||||
// the code if the flag is set atomically.
|
||||
while (1)
|
||||
{
|
||||
RefCountPair const prevVal{prevIntVal};
|
||||
// Converted the last strong pointer to a weak pointer.
|
||||
//
|
||||
// Can't be in partial destroy because only decrementing the
|
||||
// strong count to zero can start a partial destroy, and that
|
||||
// can't happen twice.
|
||||
XRPL_ASSERT(
|
||||
(!prevVal.partialDestroyStartedBit),
|
||||
"ripple::IntrusiveRefCounts::addWeakReleaseStrongRef : not in "
|
||||
"partial destroy");
|
||||
|
||||
auto nextIntVal = prevIntVal + delta;
|
||||
ReleaseStrongRefAction action = noop;
|
||||
if (prevVal.strong == 1)
|
||||
{
|
||||
if (prevVal.weak == 0)
|
||||
{
|
||||
action = noop;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextIntVal |= partialDestroyStartedMask;
|
||||
action = partialDestroy;
|
||||
}
|
||||
}
|
||||
if (refCounts.compare_exchange_weak(
|
||||
prevIntVal, nextIntVal, std::memory_order_acq_rel))
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
(!(prevIntVal & partialDestroyStartedMask)),
|
||||
"ripple::IntrusiveRefCounts::addWeakReleaseStrongRef : not "
|
||||
"started partial destroy");
|
||||
return action;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline ReleaseWeakRefAction
|
||||
IntrusiveRefCounts::releaseWeakRef() const
|
||||
{
|
||||
auto prevIntVal = refCounts.fetch_sub(weakDelta, std::memory_order_acq_rel);
|
||||
RefCountPair prev = prevIntVal;
|
||||
if (prev.weak == 1 && prev.strong == 0)
|
||||
{
|
||||
if (!prev.partialDestroyStartedBit)
|
||||
{
|
||||
// This case should only be hit if the partialDestroyStartedBit is
|
||||
// set non-atomically (and even then very rarely). The code is kept
|
||||
// in case we need to set the flag non-atomically for perf reasons.
|
||||
refCounts.wait(prevIntVal, std::memory_order_acquire);
|
||||
prevIntVal = refCounts.load(std::memory_order_acquire);
|
||||
prev = RefCountPair{prevIntVal};
|
||||
}
|
||||
if (!prev.partialDestroyFinishedBit)
|
||||
{
|
||||
// partial destroy MUST finish before running a full destroy (when
|
||||
// using weak pointers)
|
||||
refCounts.wait(prevIntVal - weakDelta, std::memory_order_acquire);
|
||||
}
|
||||
return ReleaseWeakRefAction::destroy;
|
||||
}
|
||||
return ReleaseWeakRefAction::noop;
|
||||
}
|
||||
|
||||
inline bool
|
||||
IntrusiveRefCounts::checkoutStrongRefFromWeak() const noexcept
|
||||
{
|
||||
auto curValue = RefCountPair{1, 1}.combinedValue();
|
||||
auto desiredValue = RefCountPair{2, 1}.combinedValue();
|
||||
|
||||
while (!refCounts.compare_exchange_weak(
|
||||
curValue, desiredValue, std::memory_order_acq_rel))
|
||||
{
|
||||
RefCountPair const prev{curValue};
|
||||
if (!prev.strong)
|
||||
return false;
|
||||
|
||||
desiredValue = curValue + strongDelta;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
IntrusiveRefCounts::expired() const noexcept
|
||||
{
|
||||
RefCountPair const val = refCounts.load(std::memory_order_acquire);
|
||||
return val.strong == 0;
|
||||
}
|
||||
|
||||
inline std::size_t
|
||||
IntrusiveRefCounts::use_count() const noexcept
|
||||
{
|
||||
RefCountPair const val = refCounts.load(std::memory_order_acquire);
|
||||
return val.strong;
|
||||
}
|
||||
|
||||
inline IntrusiveRefCounts::~IntrusiveRefCounts() noexcept
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
auto v = refCounts.load(std::memory_order_acquire);
|
||||
XRPL_ASSERT(
|
||||
(!(v & valueMask)),
|
||||
"ripple::IntrusiveRefCounts::~IntrusiveRefCounts : count must be zero");
|
||||
auto t = v & tagMask;
|
||||
XRPL_ASSERT(
|
||||
(!t || t == tagMask),
|
||||
"ripple::IntrusiveRefCounts::~IntrusiveRefCounts : valid tag");
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline IntrusiveRefCounts::RefCountPair::RefCountPair(
|
||||
IntrusiveRefCounts::FieldType v) noexcept
|
||||
: strong{static_cast<CountType>(v & strongMask)}
|
||||
, weak{static_cast<CountType>((v & weakMask) >> StrongCountNumBits)}
|
||||
, partialDestroyStartedBit{v & partialDestroyStartedMask}
|
||||
, partialDestroyFinishedBit{v & partialDestroyFinishedMask}
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
(strong < checkStrongMaxValue && weak < checkWeakMaxValue),
|
||||
"ripple::IntrusiveRefCounts::RefCountPair(FieldType) : inputs inside "
|
||||
"range");
|
||||
}
|
||||
|
||||
inline IntrusiveRefCounts::RefCountPair::RefCountPair(
|
||||
IntrusiveRefCounts::CountType s,
|
||||
IntrusiveRefCounts::CountType w) noexcept
|
||||
: strong{s}, weak{w}
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
(strong < checkStrongMaxValue && weak < checkWeakMaxValue),
|
||||
"ripple::IntrusiveRefCounts::RefCountPair(CountType, CountType) : "
|
||||
"inputs inside range");
|
||||
}
|
||||
|
||||
inline IntrusiveRefCounts::FieldType
|
||||
IntrusiveRefCounts::RefCountPair::combinedValue() const noexcept
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
(strong < checkStrongMaxValue && weak < checkWeakMaxValue),
|
||||
"ripple::IntrusiveRefCounts::RefCountPair::combinedValue : inputs "
|
||||
"inside range");
|
||||
return (static_cast<IntrusiveRefCounts::FieldType>(weak)
|
||||
<< IntrusiveRefCounts::StrongCountNumBits) |
|
||||
static_cast<IntrusiveRefCounts::FieldType>(strong) |
|
||||
partialDestroyStartedBit | partialDestroyFinishedBit;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void
|
||||
partialDestructorFinished(T** o)
|
||||
{
|
||||
T& self = **o;
|
||||
IntrusiveRefCounts::RefCountPair p =
|
||||
self.refCounts.fetch_or(IntrusiveRefCounts::partialDestroyFinishedMask);
|
||||
XRPL_ASSERT(
|
||||
(!p.partialDestroyFinishedBit && p.partialDestroyStartedBit &&
|
||||
!p.strong),
|
||||
"ripple::partialDestructorFinished : not a weak ref");
|
||||
if (!p.weak)
|
||||
{
|
||||
// There was a weak count before the partial destructor ran (or we would
|
||||
// have run the full destructor) and now there isn't a weak count. Some
|
||||
// thread is waiting to run the destructor.
|
||||
self.refCounts.notify_one();
|
||||
}
|
||||
// Set the pointer to null to emphasize that the object shouldn't be used
|
||||
// after calling this function as it may be destroyed in another thread.
|
||||
*o = nullptr;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // namespace ripple
|
||||
#endif
|
||||
@@ -21,7 +21,6 @@
|
||||
#define RIPPLE_BASICS_LOCALVALUE_H_INCLUDED
|
||||
|
||||
#include <boost/thread/tss.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
@@ -22,11 +22,10 @@
|
||||
|
||||
#include <xrpl/basics/UnorderedContainers.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
|
||||
#include <boost/beast/core/string.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@@ -167,6 +166,8 @@ private:
|
||||
beast::severities::Severity thresh_;
|
||||
File file_;
|
||||
bool silent_ = false;
|
||||
using Transform = std::function<std::string(std::string const&)>;
|
||||
Transform transform_;
|
||||
|
||||
public:
|
||||
Logs(beast::severities::Severity level);
|
||||
@@ -205,6 +206,28 @@ public:
|
||||
std::string const& text,
|
||||
bool console);
|
||||
|
||||
/** Rewrite test log lines. Not synchronized.
|
||||
*
|
||||
* Test-only. Installed once for the life of Logs. Empty is a null check.
|
||||
*/
|
||||
void
|
||||
setTransform(Transform fn)
|
||||
{
|
||||
transform_ = std::move(fn);
|
||||
}
|
||||
|
||||
bool
|
||||
hasTransform() const
|
||||
{
|
||||
return static_cast<bool>(transform_);
|
||||
}
|
||||
|
||||
std::string
|
||||
applyTransform(std::string const& text) const
|
||||
{
|
||||
return transform_ ? transform_(text) : text;
|
||||
}
|
||||
|
||||
std::string
|
||||
rotate();
|
||||
|
||||
|
||||
@@ -4,34 +4,37 @@ Utility functions and classes.
|
||||
|
||||
ripple/basic should contain no dependencies on other modules.
|
||||
|
||||
# Choosing a rippled container.
|
||||
|
||||
- `std::vector`
|
||||
- For ordered containers with most insertions or erases at the end.
|
||||
Choosing a rippled container.
|
||||
=============================
|
||||
|
||||
- `std::deque`
|
||||
- For ordered containers with most insertions or erases at the start or end.
|
||||
* `std::vector`
|
||||
* For ordered containers with most insertions or erases at the end.
|
||||
|
||||
- `std::list`
|
||||
- For ordered containers with inserts and erases to the middle.
|
||||
- For containers with iterators stable over insert and erase.
|
||||
- Generally slower and bigger than `std::vector` or `std::deque` except for
|
||||
* `std::deque`
|
||||
* For ordered containers with most insertions or erases at the start or end.
|
||||
|
||||
* `std::list`
|
||||
* For ordered containers with inserts and erases to the middle.
|
||||
* For containers with iterators stable over insert and erase.
|
||||
* Generally slower and bigger than `std::vector` or `std::deque` except for
|
||||
those cases.
|
||||
|
||||
- `std::set`
|
||||
- For sorted containers.
|
||||
* `std::set`
|
||||
* For sorted containers.
|
||||
|
||||
- `ripple::hash_set`
|
||||
- Where inserts and contains need to be O(1).
|
||||
- For "small" sets, `std::set` might be faster and smaller.
|
||||
* `ripple::hash_set`
|
||||
* Where inserts and contains need to be O(1).
|
||||
* For "small" sets, `std::set` might be faster and smaller.
|
||||
|
||||
- `ripple::hardened_hash_set`
|
||||
- For data sets where the key could be manipulated by an attacker
|
||||
in an attempt to mount an algorithmic complexity attack: see
|
||||
* `ripple::hardened_hash_set`
|
||||
* For data sets where the key could be manipulated by an attacker
|
||||
in an attempt to mount an algorithmic complexity attack: see
|
||||
http://en.wikipedia.org/wiki/Algorithmic_complexity_attack
|
||||
|
||||
|
||||
The following container is deprecated
|
||||
|
||||
- `std::unordered_set`
|
||||
- Use `ripple::hash_set` instead, which uses a better hashing algorithm.
|
||||
- Or use `ripple::hardened_hash_set` to prevent algorithmic complexity attacks.
|
||||
* `std::unordered_set`
|
||||
* Use `ripple::hash_set` instead, which uses a better hashing algorithm.
|
||||
* Or use `ripple::hardened_hash_set` to prevent algorithmic complexity attacks.
|
||||
|
||||
@@ -20,11 +20,11 @@
|
||||
#ifndef RIPPLE_BASICS_RESOLVER_H_INCLUDED
|
||||
#define RIPPLE_BASICS_RESOLVER_H_INCLUDED
|
||||
|
||||
#include <xrpl/beast/net/IPEndpoint.h>
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
#include <xrpl/beast/net/IPEndpoint.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class Resolver
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
#include <xrpl/basics/Resolver.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
|
||||
#include <boost/asio/io_service.hpp>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2023 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_BASICS_SHAREDWEAKCACHEPOINTER_H_INCLUDED
|
||||
#define RIPPLE_BASICS_SHAREDWEAKCACHEPOINTER_H_INCLUDED
|
||||
|
||||
#include <memory>
|
||||
#include <variant>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** A combination of a std::shared_ptr and a std::weak_pointer.
|
||||
|
||||
|
||||
This class is a wrapper to a `std::variant<std::shared_ptr,std::weak_ptr>`
|
||||
This class is useful for storing intrusive pointers in tagged caches using less
|
||||
memory than storing both pointers directly.
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
class SharedWeakCachePointer
|
||||
{
|
||||
public:
|
||||
SharedWeakCachePointer() = default;
|
||||
|
||||
SharedWeakCachePointer(SharedWeakCachePointer const& rhs);
|
||||
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedWeakCachePointer(std::shared_ptr<TT> const& rhs);
|
||||
|
||||
SharedWeakCachePointer(SharedWeakCachePointer&& rhs);
|
||||
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedWeakCachePointer(std::shared_ptr<TT>&& rhs);
|
||||
|
||||
SharedWeakCachePointer&
|
||||
operator=(SharedWeakCachePointer const& rhs);
|
||||
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedWeakCachePointer&
|
||||
operator=(std::shared_ptr<TT> const& rhs);
|
||||
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedWeakCachePointer&
|
||||
operator=(std::shared_ptr<TT>&& rhs);
|
||||
|
||||
~SharedWeakCachePointer();
|
||||
|
||||
/** Return a strong pointer if this is already a strong pointer (i.e. don't
|
||||
lock the weak pointer. Use the `lock` method if that's what's needed)
|
||||
*/
|
||||
std::shared_ptr<T> const&
|
||||
getStrong() const;
|
||||
|
||||
/** Return true if this is a strong pointer and the strong pointer is
|
||||
seated.
|
||||
*/
|
||||
explicit
|
||||
operator bool() const noexcept;
|
||||
|
||||
/** Set the pointer to null, decrement the appropriate ref count, and run
|
||||
the appropriate release action.
|
||||
*/
|
||||
void
|
||||
reset();
|
||||
|
||||
/** If this is a strong pointer, return the raw pointer. Otherwise return
|
||||
null.
|
||||
*/
|
||||
T*
|
||||
get() const;
|
||||
|
||||
/** If this is a strong pointer, return the strong count. Otherwise return 0
|
||||
*/
|
||||
std::size_t
|
||||
use_count() const;
|
||||
|
||||
/** Return true if there is a non-zero strong count. */
|
||||
bool
|
||||
expired() const;
|
||||
|
||||
/** If this is a strong pointer, return the strong pointer. Otherwise
|
||||
attempt to lock the weak pointer.
|
||||
*/
|
||||
std::shared_ptr<T>
|
||||
lock() const;
|
||||
|
||||
/** Return true is this represents a strong pointer. */
|
||||
bool
|
||||
isStrong() const;
|
||||
|
||||
/** Return true is this represents a weak pointer. */
|
||||
bool
|
||||
isWeak() const;
|
||||
|
||||
/** If this is a weak pointer, attempt to convert it to a strong pointer.
|
||||
|
||||
@return true if successfully converted to a strong pointer (or was
|
||||
already a strong pointer). Otherwise false.
|
||||
*/
|
||||
bool
|
||||
convertToStrong();
|
||||
|
||||
/** If this is a strong pointer, attempt to convert it to a weak pointer.
|
||||
|
||||
@return false if the pointer is null. Otherwise return true.
|
||||
*/
|
||||
bool
|
||||
convertToWeak();
|
||||
|
||||
private:
|
||||
std::variant<std::shared_ptr<T>, std::weak_ptr<T>> combo_;
|
||||
};
|
||||
} // namespace ripple
|
||||
#endif
|
||||
@@ -1,192 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2023 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_BASICS_SHAREDWEAKCACHEPOINTER_IPP_INCLUDED
|
||||
#define RIPPLE_BASICS_SHAREDWEAKCACHEPOINTER_IPP_INCLUDED
|
||||
|
||||
#include <xrpl/basics/SharedWeakCachePointer.h>
|
||||
|
||||
namespace ripple {
|
||||
template <class T>
|
||||
SharedWeakCachePointer<T>::SharedWeakCachePointer(
|
||||
SharedWeakCachePointer const& rhs) = default;
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedWeakCachePointer<T>::SharedWeakCachePointer(
|
||||
std::shared_ptr<TT> const& rhs)
|
||||
: combo_{rhs}
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SharedWeakCachePointer<T>::SharedWeakCachePointer(
|
||||
SharedWeakCachePointer&& rhs) = default;
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedWeakCachePointer<T>::SharedWeakCachePointer(std::shared_ptr<TT>&& rhs)
|
||||
: combo_{std::move(rhs)}
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SharedWeakCachePointer<T>&
|
||||
SharedWeakCachePointer<T>::operator=(SharedWeakCachePointer const& rhs) =
|
||||
default;
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedWeakCachePointer<T>&
|
||||
SharedWeakCachePointer<T>::operator=(std::shared_ptr<TT> const& rhs)
|
||||
{
|
||||
combo_ = rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <class TT>
|
||||
requires std::convertible_to<TT*, T*>
|
||||
SharedWeakCachePointer<T>&
|
||||
SharedWeakCachePointer<T>::operator=(std::shared_ptr<TT>&& rhs)
|
||||
{
|
||||
combo_ = std::move(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SharedWeakCachePointer<T>::~SharedWeakCachePointer() = default;
|
||||
|
||||
// Return a strong pointer if this is already a strong pointer (i.e. don't
|
||||
// lock the weak pointer. Use the `lock` method if that's what's needed)
|
||||
template <class T>
|
||||
std::shared_ptr<T> const&
|
||||
SharedWeakCachePointer<T>::getStrong() const
|
||||
{
|
||||
static std::shared_ptr<T> const empty;
|
||||
if (auto p = std::get_if<std::shared_ptr<T>>(&combo_))
|
||||
return *p;
|
||||
return empty;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SharedWeakCachePointer<T>::operator bool() const noexcept
|
||||
{
|
||||
return !!std::get_if<std::shared_ptr<T>>(&combo_);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
SharedWeakCachePointer<T>::reset()
|
||||
{
|
||||
combo_ = std::shared_ptr<T>{};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T*
|
||||
SharedWeakCachePointer<T>::get() const
|
||||
{
|
||||
return std::get_if<std::shared_ptr<T>>(&combo_).get();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::size_t
|
||||
SharedWeakCachePointer<T>::use_count() const
|
||||
{
|
||||
if (auto p = std::get_if<std::shared_ptr<T>>(&combo_))
|
||||
return p->use_count();
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
SharedWeakCachePointer<T>::expired() const
|
||||
{
|
||||
if (auto p = std::get_if<std::weak_ptr<T>>(&combo_))
|
||||
return p->expired();
|
||||
return !std::get_if<std::shared_ptr<T>>(&combo_);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::shared_ptr<T>
|
||||
SharedWeakCachePointer<T>::lock() const
|
||||
{
|
||||
if (auto p = std::get_if<std::shared_ptr<T>>(&combo_))
|
||||
return *p;
|
||||
|
||||
if (auto p = std::get_if<std::weak_ptr<T>>(&combo_))
|
||||
return p->lock();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
SharedWeakCachePointer<T>::isStrong() const
|
||||
{
|
||||
if (auto p = std::get_if<std::shared_ptr<T>>(&combo_))
|
||||
return !!p->get();
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
SharedWeakCachePointer<T>::isWeak() const
|
||||
{
|
||||
return !isStrong();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
SharedWeakCachePointer<T>::convertToStrong()
|
||||
{
|
||||
if (isStrong())
|
||||
return true;
|
||||
|
||||
if (auto p = std::get_if<std::weak_ptr<T>>(&combo_))
|
||||
{
|
||||
if (auto s = p->lock())
|
||||
{
|
||||
combo_ = std::move(s);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
SharedWeakCachePointer<T>::convertToWeak()
|
||||
{
|
||||
if (isWeak())
|
||||
return true;
|
||||
|
||||
if (auto p = std::get_if<std::shared_ptr<T>>(&combo_))
|
||||
{
|
||||
combo_ = std::weak_ptr<T>(*p);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
} // namespace ripple
|
||||
#endif
|
||||
@@ -176,7 +176,7 @@ public:
|
||||
@param count the number of items the slab allocator can allocate; note
|
||||
that a count of 0 is valid and means that the allocator
|
||||
is, effectively, disabled. This can be very useful in some
|
||||
contexts (e.g. when minimal memory usage is needed) and
|
||||
contexts (e.g. when mimimal memory usage is needed) and
|
||||
allows for graceful failure.
|
||||
*/
|
||||
constexpr explicit SlabAllocator(
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user