Compare commits

..
Author SHA1 Message Date
Richard Holland 62d7b120b8 Merge branch 'dev' into fix-enhanced-logging 2026-04-24 11:11:12 +10:00
tequ 66f7294120 Test: hint build_test_hooks.sh when hook wasm is empty in hso() 2026-04-24 11:10:46 +10:00
Nicholas Dudfield 7f6ac75617 Revert "chore: use improved levelization script with threading and argparse"
This reverts commit 5c1d7d9ae9.
2026-04-24 11:09:19 +10:00
Nicholas Dudfield 4150f0383c chore: use improved levelization script with threading and argparse 2026-04-24 11:09:19 +10:00
Nicholas Dudfield 25123b370a chore: replace levelization shell script with python
Backport of XRPLF/rippled#6325. The python version runs ~80x faster.
2026-04-24 11:09:19 +10:00
tequ f90ed41802 enable ccache direct_mode 2026-04-24 11:06:51 +10:00
tequ 8c4c158d3a output ccache configuration in release-builder 2026-04-24 11:06:51 +10:00
tequ 2d2951875d fix: typo SignersListSet 2026-04-24 11:05:20 +10:00
tequ 9bfca63574 Update util_keylet fee test 2026-04-24 11:00:31 +10:00
tequ 1ba444ae7f Updated tests to align with the changes merged into the dev branch. 2026-04-24 11:00:31 +10:00
tequ f96d9b6e51 Add tests for Hooks fee 2026-04-24 11:00:31 +10:00
tequ c7e5801a35 Fix BEAST_ENHANCED_LOGGING not working and restore original behavior 2026-03-06 20:58:07 +09:00
tequ 8cfee6c8a3 Merge fixAMMClawbackRounding amendment into featureAMMClawback amendment 2026-02-25 19:07:45 +10:00
yinyiqian1 8673599d2b fixAMMClawbackRounding: adjust last holder's LPToken balance (#5513)
Due to rounding, the LPTokenBalance of the last LP might not match the LP's trustline balance. This was fixed for `AMMWithdraw` in `fixAMMv1_1` by adjusting the LPTokenBalance to be the same as the trustline balance. Since `AMMClawback` is also performing a withdrawal, we need to adjust LPTokenBalance as well in `AMMClawback.`

This change includes:
1. Refactored `verifyAndAdjustLPTokenBalance` function in `AMMUtils`, which both`AMMWithdraw` and `AMMClawback` call to adjust LPTokenBalance.
2. Added the unit test `testLastHolderLPTokenBalance` to test the scenario.
3. Modify the existing unit tests for `fixAMMClawbackRounding`.
2026-02-25 19:07:45 +10:00
tequ ec65e622aa Merge fixAMMv1_3 amendment into featureAMM amendment 2026-02-25 16:20:43 +10:00
Gregory Tsipenyuk 65837f49e1 fix: Add AMMv1_3 amendment (#5203)
* Add AMM bid/create/deposit/swap/withdraw/vote invariants:
  - Deposit, Withdrawal invariants: `sqrt(asset1Balance * asset2Balance) >= LPTokens`.
  - Bid: `sqrt(asset1Balance * asset2Balance) > LPTokens` and the pool balances don't change.
  - Create: `sqrt(asset1Balance * assetBalance2) == LPTokens`.
  - Swap: `asset1BalanceAfter * asset2BalanceAfter >= asset1BalanceBefore * asset2BalanceBefore`
     and `LPTokens` don't change.
  - Vote: `LPTokens` and pool balances don't change.
  - All AMM and swap transactions: amounts and tokens are greater than zero, except on withdrawal if all tokens
    are withdrawn.
* Add AMM deposit and withdraw rounding to ensure AMM invariant:
  - On deposit, tokens out are rounded downward and deposit amount is rounded upward.
  - On withdrawal, tokens in are rounded upward and withdrawal amount is rounded downward.
* Add Order Book Offer invariant to verify consumed amounts. Consumed amounts are less than the offer.
* Fix Bid validation. `AuthAccount` can't have duplicate accounts or the submitter account.
2026-02-25 16:20:43 +10:00
RichardAH e5b21f026e Merge pull request #692 from Xahau/sync-2.4.0-rebased
Sync: Ripple(d) 2.4.0
2026-02-24 16:07:09 +10:00
463 changed files with 16845 additions and 52666 deletions

No files matched your search

-46
View File
@@ -1,46 +0,0 @@
codecov:
require_ci_to_pass: true
comment:
behavior: default
layout: reach,diff,flags,tree,reach
show_carryforward_flags: false
coverage:
range: "60..80"
precision: 1
round: nearest
status:
project:
default:
target: 60%
threshold: 2%
patch:
default:
target: auto
threshold: 2%
paths:
# PeerImp is historically hard to exercise in the current unit-test
# harness. Keep this list narrow; new testable code should remain
# covered by the default patch gate.
- "!src/xrpld/overlay/detail/PeerImp.cpp"
historically-untested:
target: 0%
paths:
- "src/xrpld/overlay/detail/PeerImp.cpp"
changes: false
github_checks:
annotations: true
parsers:
cobertura:
partials_as_hits: true
handle_missing_conditions : true
slack_app: false
ignore:
- "src/test/"
- "include/xrpl/beast/test/"
- "include/xrpl/beast/unit_test/"
+4 -21
View File
@@ -1,25 +1,8 @@
# This feature requires Git >= 2.24
# To use it by default in git blame:
# git config blame.ignoreRevsFile .git-blame-ignore-revs
# Format first-party source according to .clang-format
50760c693510894ca368e90369b0cc2dabfd07f3
# Reintroduce Clang-Format & Levelization
da1d20d6d5d862716125d60899b80fab5302954a
# Consolidate external libraries
da1d20d6d5d862716125d60899b80fab5302954a
# Rename .hpp to .h
0345a2645d0f5ad900f4fbbcaff96040d3a887fc
# Format formerly .hpp files
5a227dc719016e10045e17c9396ad401118044f1
# Rewrite includes
e61880699997398f5a746e6c4034edc7632661f5
# Move CMake directory (#4997)
e47b1c1b3b97c3f6d11858ee02f463596e29e7f0
# Rearrange sources (#4997)
bfafa2bb39e562901736d656806bd700c3699a2f
# Rewrite includes (#4997)
e61880699997398f5a746e6c4034edc7632661f5
# Recompute loops (#4997)
d25b5dcd568bb96c18e347d55fac10fe901a1bfb
# Reformat code with clang-format-18
02749feea88ce61c1f7eeb2d61a57d8ecf07ab11
e2384885f5f630c8f0ffe4bf21a169b433a16858
241b9ddde9e11beb7480600fd5ed90e1ef109b21
760f16f56835663d9286bd29294d074de26a7ba6
0eebe6a5f4246fced516d52b83ec4e7f47373edd
+8 -21
View File
@@ -2,14 +2,6 @@ name: build
description: 'Builds the project with ccache integration'
inputs:
cmake-target:
description: 'CMake target to build'
required: false
default: all
cmake-args:
description: 'Additional CMake arguments'
required: false
default: null
generator:
description: 'CMake generator to use'
required: true
@@ -28,10 +20,6 @@ inputs:
description: 'C++ compiler to use'
required: false
default: ''
gcov:
description: 'Gcov to use'
required: false
default: ''
compiler-id:
description: 'Unique identifier: compiler-version-stdlib[-gccversion] (e.g. clang-14-libstdcxx-gcc11, gcc-13-libstdcxx)'
required: false
@@ -53,11 +41,10 @@ inputs:
required: false
default: 'dev'
stdlib:
description: 'C++ standard library to use (default = compiler default, e.g. GCC always uses libstdc++)'
description: 'C++ standard library to use'
required: true
type: choice
options:
- default
- libstdcxx
- libcxx
clang_gcc_toolchain:
@@ -100,6 +87,11 @@ runs:
export CCACHE_CONFIGPATH="$HOME/.config/ccache/ccache.conf"
echo "CCACHE_CONFIGPATH=$CCACHE_CONFIGPATH" >> $GITHUB_ENV
# Keep config separate from cache_dir so configs aren't swapped when CCACHE_DIR changes between steps
mkdir -p ~/.config/ccache
export CCACHE_CONFIGPATH="$HOME/.config/ccache/ccache.conf"
echo "CCACHE_CONFIGPATH=$CCACHE_CONFIGPATH" >> $GITHUB_ENV
# Configure ccache settings AFTER cache restore (prevents stale cached config)
ccache --set-config=max_size=${{ inputs.ccache_max_size }}
ccache --set-config=hash_dir=${{ inputs.ccache_hash_dir }}
@@ -130,10 +122,6 @@ runs:
export CXX="${{ inputs.cxx }}"
fi
if [ -n "${{ inputs.gcov }}" ]; then
ln -sf /usr/bin/${{ inputs.gcov }} /usr/local/bin/gcov
fi
# Create wrapper toolchain that overlays ccache on top of Conan's toolchain
# This enables ccache for the main app build without affecting Conan dependency builds
if [ "${{ inputs.ccache_enabled }}" = "true" ]; then
@@ -197,8 +185,7 @@ runs:
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${TOOLCHAIN_FILE} \
-DCMAKE_BUILD_TYPE=${{ inputs.configuration }} \
-Dtests=TRUE \
-Dxrpld=TRUE \
${{ inputs.cmake-args }}
-Dxrpld=TRUE
- name: Show ccache config before build
if: inputs.ccache_enabled == 'true'
@@ -222,7 +209,7 @@ runs:
VERBOSE_FLAG="-- -v"
fi
cmake --build . --config ${{ inputs.configuration }} --parallel $(nproc) --target ${{ inputs.cmake-target }} ${VERBOSE_FLAG}
cmake --build . --config ${{ inputs.configuration }} --parallel $(nproc) ${VERBOSE_FLAG}
- name: Show ccache statistics
if: inputs.ccache_enabled == 'true'
@@ -50,10 +50,6 @@ inputs:
options:
- libstdcxx
- libcxx
conan_deps_cxxflags:
description: 'Extra cxxflags applied to Conan dependency package builds only (NOT the rippled build). JSON object keyed by Conan package pattern, e.g. {"grpc/*":["-Wno-foo"]}. Maps to <pattern>:tools.build:cxxflags.'
required: false
default: '{}'
outputs:
cache-hit:
@@ -85,8 +81,6 @@ runs:
- name: Configure Conan
shell: bash
env:
CONAN_DEPS_CXXFLAGS: ${{ inputs.conan_deps_cxxflags }}
run: |
# Create the default profile directory if it doesn't exist
mkdir -p ~/.conan2/profiles
@@ -111,14 +105,7 @@ runs:
os=${{ inputs.os }}
EOF
# [buildenv] + [conf] sections.
# Linux pins compiler executables; macOS uses the system toolchain.
# conan_deps_cxxflags (matrix-driven) optionally adds package-pattern
# scoped tools.build:cxxflags for Conan dependency builds only - typically
# grpc workarounds for newer clang's stricter diagnostics. Because these
# are profile-pattern scoped (e.g. grpc/*:...), they do NOT affect the
# consumer/rippled toolchain generated for the main build.
NEED_CONF=0
# Add buildenv and conf sections for Linux (not needed for macOS)
if [ "${{ inputs.os }}" = "Linux" ] && [ -n "${{ inputs.cc }}" ]; then
cat >> ~/.conan2/profiles/default <<EOF
@@ -129,38 +116,16 @@ runs:
[conf]
tools.build:compiler_executables={"c": "/usr/bin/${{ inputs.cc }}", "cpp": "/usr/bin/${{ inputs.cxx }}"}
EOF
NEED_CONF=1
fi
if [ -n "${CONAN_DEPS_CXXFLAGS}" ] && [ "${CONAN_DEPS_CXXFLAGS}" != "{}" ]; then
CONAN_DEPS_CXXFLAGS_LINES="$(python3 - <<'PY'
import json
import os
import sys
# Add macOS-specific conf if needed
if [ "${{ inputs.os }}" = "Macos" ]; then
cat >> ~/.conan2/profiles/default <<EOF
raw = os.environ["CONAN_DEPS_CXXFLAGS"]
data = json.loads(raw)
if not isinstance(data, dict):
sys.exit("conan_deps_cxxflags must be a JSON object like {\"grpc/*\": [\"-Wno-...\"]}")
for pattern, flags in data.items():
if not isinstance(pattern, str) or not pattern:
sys.exit("conan_deps_cxxflags keys must be non-empty Conan package patterns")
if pattern == "&":
sys.exit("conan_deps_cxxflags must target dependency package patterns, not the consumer (&)")
if not isinstance(flags, list) or not all(isinstance(flag, str) for flag in flags):
sys.exit(f"{pattern}: cxxflags must be a JSON string list")
if flags:
print(f"{pattern}:tools.build:cxxflags={json.dumps(flags, separators=(',', ':'))}")
PY
)"
if [ -n "${CONAN_DEPS_CXXFLAGS_LINES}" ] && [ "$NEED_CONF" = "0" ]; then
echo "" >> ~/.conan2/profiles/default
echo "[conf]" >> ~/.conan2/profiles/default
fi
if [ -n "${CONAN_DEPS_CXXFLAGS_LINES}" ]; then
printf '%s\n' "${CONAN_DEPS_CXXFLAGS_LINES}" >> ~/.conan2/profiles/default
fi
[conf]
# Workaround for gRPC with newer Apple Clang
tools.build:cxxflags=["-Wno-missing-template-arg-list-after-template-kw"]
EOF
fi
# Display profile for verification
+1 -10
View File
@@ -15,9 +15,6 @@ env:
jobs:
checkout:
# build publishes to build.xahau.tech, so this workflow only runs from
# Xahau/xahaud. build and tests are skipped along with this job.
if: github.repository == 'Xahau/xahaud'
runs-on: [self-hosted, vanity]
outputs:
checkout_path: ${{ steps.vars.outputs.checkout_path }}
@@ -89,16 +86,10 @@ jobs:
cleanup:
runs-on: [self-hosted, xahaud-build]
needs: [tests, checkout]
if: always() && github.repository == 'Xahau/xahaud'
if: always()
steps:
- name: Cleanup workspace
run: |
CHECKOUT_PATH="${{ needs.checkout.outputs.checkout_path }}"
# A run cancelled before checkout has no path; an empty one would
# make the rm below delete every run's checkout on the runner.
if [[ -z "${CHECKOUT_PATH}" ]]; then
echo "No checkout path (cancelled before checkout); nothing to clean"
exit 0
fi
echo "Cleaning workspace for ${CHECKOUT_PATH}"
rm -rf "${{ github.workspace }}/${CHECKOUT_PATH}"
-107
View File
@@ -1,107 +0,0 @@
name: Check Genesis Hooks
on:
push:
pull_request:
jobs:
check-genesis-hooks:
runs-on: ubuntu-24.04
env:
CLANG_VERSION: 18
name: Verify xahau.h is in sync with genesis hooks
steps:
- name: Checkout repository
uses: actions/checkout@v6
# Install binaryen from GitHub Releases (pinned to version 100)
- name: Install binaryen (version 100)
run: |
curl -LO https://github.com/WebAssembly/binaryen/releases/download/version_100/binaryen-version_100-x86_64-linux.tar.gz
tar -xzf binaryen-version_100-x86_64-linux.tar.gz
sudo cp binaryen-version_100/bin/* /usr/local/bin/
wasm-opt --version
- name: Install clang-format
run: |
codename=$( lsb_release --codename --short )
sudo tee /etc/apt/sources.list.d/llvm.list >/dev/null <<EOF
deb http://apt.llvm.org/${codename}/ llvm-toolchain-${codename}-${CLANG_VERSION} main
deb-src http://apt.llvm.org/${codename}/ llvm-toolchain-${codename}-${CLANG_VERSION} main
EOF
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add
sudo apt-get update
sudo apt-get install clang-format-${CLANG_VERSION}
clang-format --version
# Install wasienv (WebAssembly SDK)
- name: Install wasienv
run: |
# Download install.sh
curl -o /tmp/wasienv-install.sh https://raw.githubusercontent.com/wasienv/wasienv/master/install.sh
# Replace /bin to /local/bin
sed -i 's|/bin|/local/bin|g' /tmp/wasienv-install.sh
# Execute the installed script
bash /tmp/wasienv-install.sh
# Add wasienv to PATH for subsequent steps
- name: Setup wasienv
run: |
echo "$HOME/.wasienv/bin" >> $GITHUB_PATH
wasmcc -v || true
# Build and install hook-cleaner tool
- name: Build and install hook-cleaner
run: |
git clone https://github.com/richardah/hook-cleaner-c.git /tmp/hook-cleaner
cd /tmp/hook-cleaner
make
cp hook-cleaner /usr/local/bin/
chmod +x /usr/local/bin/hook-cleaner
# Build and install guard_checker tool
- name: Build and install guard_checker
run: |
cd include/xrpl/hook
make
cp guard_checker /usr/local/bin/
chmod +x /usr/local/bin/guard_checker
# Verify all required tools are available
- name: Verify required tools
run: |
echo "Checking tool availability..."
command -v wasmcc || (echo "Error: wasmcc not found" && exit 1)
command -v wasm-opt || (echo "Error: wasm-opt not found" && exit 1)
command -v hook-cleaner || (echo "Error: hook-cleaner not found" && exit 1)
command -v guard_checker || (echo "Error: guard_checker not found" && exit 1)
command -v xxd || (echo "Error: xxd not found" && exit 1)
command -v clang-format || (echo "Error: clang-format not found" && exit 1)
echo "All tools verified successfully"
# Execute build script to regenerate xahau.h
- name: Run build_xahau_h.sh
run: |
cd hook/genesis
./build_xahau_h.sh
# Check if xahau.h has changed (fail if out of sync)
- name: Verify xahau.h is in sync
run: |
if ! git diff --exit-code include/xrpl/hook/xahau.h; then
echo ""
echo "❌ ERROR: xahau.h is out of sync with genesis hooks"
echo ""
echo "The generated xahau.h differs from the committed version."
echo "Please run the following command and commit the changes:"
echo ""
echo " cd hook/genesis && ./build_xahau_h.sh"
echo ""
echo "Diff:"
git diff include/xrpl/hook/xahau.h
exit 1
fi
echo "✅ xahau.h is in sync with genesis hooks"
+1 -1
View File
@@ -20,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 -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' \) -not -path "src/magic/magic_enum.h" -exec clang-format-${CLANG_VERSION} -i {} +
- name: Check for differences
id: assert
run: |
@@ -18,10 +18,6 @@ jobs:
generator: bash ./hook/generate_sfcodes.sh
- target: hook/tts.h
generator: ./hook/generate_tts.sh
- target: hook/ls_flags.h
generator: ./hook/generate_lsflags.sh
- target: hook/tx_flags.h
generator: ./hook/generate_txflags.sh
runs-on: ubuntu-24.04
env:
CLANG_VERSION: 18
-3
View File
@@ -107,9 +107,6 @@ jobs:
compiler: apple-clang
compiler_version: ${{ steps.detect-compiler.outputs.compiler_version }}
stdlib: libcxx
# grpc 1.50.1 trips clang-19+ -Werror=missing-template-arg-list-after-template-kw
# on Apple Clang. Drop when grpc is bumped past the fix.
conan_deps_cxxflags: '{"grpc/*":["-Wno-missing-template-arg-list-after-template-kw"]}'
- name: Build
uses: ./.github/actions/xahau-ga-build
+146 -143
View File
@@ -8,6 +8,12 @@ on:
types: [opened, synchronize, reopened, labeled, unlabeled]
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
inputs:
full_matrix:
description: "Force full matrix (6 configs)"
required: false
default: "false"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
@@ -24,45 +30,54 @@ jobs:
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: escape double quotes
id: escape
shell: bash
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: |
ESCAPED_PR_TITLE="${PR_TITLE//\"/\\\"}"
echo "title=${ESCAPED_PR_TITLE}" >> "$GITHUB_OUTPUT"
- name: Generate build matrix
id: set-matrix
shell: python
env:
GH_TOKEN: ${{ github.token }}
run: |
import json
import os
import urllib.request
matrix = [
# Full matrix with all 6 compiler configurations
# Each configuration includes all parameters needed by the build job
full_matrix = [
{
"compiler_id": "gcc-11-libstdcxx",
"compiler": "gcc",
"cc": "gcc-11",
"cxx": "g++-11",
"compiler_version": 11,
"stdlib": "libstdcxx",
"configuration": "Debug"
},
{
"compiler_id": "gcc-13-libstdcxx",
"compiler": "gcc",
"cc": "gcc-13",
"cxx": "g++-13",
"compiler_version": 13,
"stdlib": "default",
"configuration": "Debug",
"job_type": "build"
"stdlib": "libstdcxx",
"configuration": "Debug"
},
{
# Latest stable Clang for the most accurate source-based
# coverage mapping (newer language features, fewer bugs in
# llvm-cov region inference). Pulled from apt.llvm.org since
# Ubuntu 24.04 default repos cap at clang-18.
"compiler_id": "clang-20-libcxx",
"compiler_id": "clang-14-libstdcxx-gcc11",
"compiler": "clang",
"cc": "clang-20",
"cxx": "clang++-20",
"compiler_version": 20,
"stdlib": "libcxx",
"configuration": "Debug",
"job_type": "coverage",
"coverage_tool": "llvm",
"coverage_format": "lcov",
# grpc 1.50.1 uses `Foo::template Bar(...)` without an
# angle-bracket arg list; clang-19+ promoted that to
# -Werror. Drop when grpc is bumped past the fix.
"conan_deps_cxxflags": {
"grpc/*": ["-Wno-missing-template-arg-list-after-template-kw"]
}
"cc": "clang-14",
"cxx": "clang++-14",
"compiler_version": 14,
"stdlib": "libstdcxx",
"clang_gcc_toolchain": 11,
"configuration": "Debug"
},
{
"compiler_id": "clang-16-libstdcxx-gcc13",
@@ -72,18 +87,116 @@ jobs:
"compiler_version": 16,
"stdlib": "libstdcxx",
"clang_gcc_toolchain": 13,
"configuration": "Debug",
"job_type": "build"
"configuration": "Debug"
},
{
"compiler_id": "clang-17-libcxx",
"compiler": "clang",
"cc": "clang-17",
"cxx": "clang++-17",
"compiler_version": 17,
"stdlib": "libcxx",
"configuration": "Debug"
},
{
# Clang 18 - testing if it's faster than Clang 17 with libc++
# Requires patching Conan v1 settings.yml to add version 18
"compiler_id": "clang-18-libcxx",
"compiler": "clang",
"cc": "clang-18",
"cxx": "clang++-18",
"compiler_version": 18,
"stdlib": "libcxx",
"configuration": "Debug"
}
]
# Minimal matrix for PRs and feature branches
minimal_matrix = [
full_matrix[1], # gcc-13 (middle-ground gcc)
full_matrix[2] # clang-14 (mature, stable clang)
]
# Determine which matrix to use based on the target branch
ref = "${{ github.ref }}"
base_ref = "${{ github.base_ref }}" # For PRs, this is the target branch
event_name = "${{ github.event_name }}"
pr_title = """${{ steps.escape.outputs.title }}"""
pr_labels = """${{ join(github.event.pull_request.labels.*.name, ',') }}"""
pr_head_sha = "${{ github.event.pull_request.head.sha }}"
# Add runs_on based on job_type
for entry in matrix:
if entry.get("job_type") == "coverage":
entry["runs_on"] = '["self-hosted", "generic", 24.04]'
# Get commit message - for PRs, fetch via API since head_commit.message is empty
if event_name == "pull_request" and pr_head_sha:
try:
url = f"https://api.github.com/repos/${{ github.repository }}/commits/{pr_head_sha}"
req = urllib.request.Request(url, headers={
"Accept": "application/vnd.github.v3+json",
"Authorization": f"Bearer {os.environ.get('GH_TOKEN', '')}"
})
with urllib.request.urlopen(req) as response:
data = json.load(response)
commit_message = data["commit"]["message"]
except Exception as e:
print(f"Failed to fetch commit message: {e}")
commit_message = ""
else:
commit_message = """${{ github.event.head_commit.message }}"""
# Debug logging
print(f"Event: {event_name}")
print(f"Ref: {ref}")
print(f"Base ref: {base_ref}")
print(f"PR head SHA: {pr_head_sha}")
print(f"PR title: {pr_title}")
print(f"PR labels: {pr_labels}")
print(f"Commit message: {commit_message}")
# Manual trigger input to force full matrix.
manual_full = "${{ github.event.inputs.full_matrix || 'false' }}" == "true"
# Label/manual overrides, while preserving existing title/commit behavior.
force_full = (
manual_full
or "[ci-nix-full-matrix]" in commit_message
or "[ci-nix-full-matrix]" in pr_title
or ("ci-full-build" in pr_labels and "ci-nix-full-matrix" in pr_labels)
)
force_min = (
"ci-full-build" in pr_labels
)
print(f"Force full matrix: {force_full}")
print(f"Force min matrix: {force_min}")
# Check if this is targeting a main branch
# For PRs: check base_ref (target branch)
# For pushes: check ref (current branch)
main_branches = ["refs/heads/dev", "refs/heads/release", "refs/heads/candidate"]
if force_full:
# Override: always use full matrix if forced by manual input or label.
use_full = True
elif force_min:
# Override: always use minimal matrix if ci-full-build label is present.
use_full = False
elif event_name == "pull_request":
# For PRs, base_ref is just the branch name (e.g., "dev", not "refs/heads/dev")
# Check if the PR targets release or candidate (more critical branches)
use_full = base_ref in ["release", "candidate"]
else:
# For pushes, ref is the full reference (e.g., "refs/heads/dev")
use_full = ref in main_branches
# Select the appropriate matrix
if use_full:
if force_full:
print(f"Using FULL matrix (6 configs) - forced by [ci-nix-full-matrix] tag")
else:
entry["runs_on"] = '["self-hosted", "generic", 20.04]'
print(f"Using FULL matrix (6 configs) - targeting main branch")
matrix = full_matrix
else:
print(f"Using MINIMAL matrix (2 configs) - feature branch/PR")
matrix = minimal_matrix
# Output the matrix as JSON
output = json.dumps({"include": matrix})
with open(os.environ['GITHUB_OUTPUT'], 'a') as f:
@@ -91,10 +204,7 @@ jobs:
build:
needs: matrix-setup
runs-on: ${{ fromJSON(matrix.runs_on) }}
permissions:
id-token: write
contents: read
runs-on: [self-hosted, generic, 20.04]
container:
image: ubuntu:24.04
volumes:
@@ -119,27 +229,11 @@ jobs:
- name: Install build dependencies
run: |
# Bump apt's default 3 retries; papers over short upstream blips
# like the recurring ppa.launchpadcontent.net outages.
echo 'Acquire::Retries "5";' > /etc/apt/apt.conf.d/80-retries
apt-get update
apt-get install -y software-properties-common
add-apt-repository ppa:ubuntu-toolchain-r/test -y
# apt.llvm.org for Clang versions newer than what Ubuntu 24.04 ships
# (24.04 default repos cap at clang-18). The bootstrap script adds
# the LLVM apt source for the requested version and runs apt-get update.
if [ "${{ matrix.compiler }}" = "clang" ] && [ "${{ matrix.compiler_version }}" -ge 19 ]; then
apt-get install -y wget gnupg lsb-release
wget -qO /tmp/llvm.sh https://apt.llvm.org/llvm.sh
chmod +x /tmp/llvm.sh
# `all` installs clang + libllvm + lldb + lld + the llvm-N package
# (which provides llvm-profdata-N / llvm-cov-N for coverage runs).
/tmp/llvm.sh ${{ matrix.compiler_version }} all
fi
apt-get update
apt-get install -y git python3 python-is-python3 pipx
apt-get install -y python3 python-is-python3 pipx
pipx ensurepath
apt-get install -y cmake ninja-build ${{ matrix.cc }} ${{ matrix.cxx }} ccache
apt-get install -y perl # for openssl build
@@ -210,18 +304,6 @@ jobs:
pipx install "conan>=2.0,<3"
echo "$HOME/.local/bin" >> $GITHUB_PATH
# Install coverage tooling
if [ "${{ matrix.job_type }}" = "coverage" ]; then
apt-get install -y curl lcov
if [ "${{ matrix.coverage_tool }}" = "llvm" ]; then
# Native LLVM source-based coverage: llvm-profdata + llvm-cov.
# The clang-N package doesn't pull these in; the llvm-N package does.
apt-get install -y "llvm-${{ matrix.compiler_version }}"
else
pipx install "gcovr>=7,<9"
fi
fi
- name: Check environment
run: |
echo "PATH:"
@@ -231,18 +313,6 @@ jobs:
which ${{ matrix.cc }} && ${{ matrix.cc }} --version || echo "${{ matrix.cc }} not found"
which ${{ matrix.cxx }} && ${{ matrix.cxx }} --version || echo "${{ matrix.cxx }} not found"
which ccache && ccache --version || echo "ccache not found"
# Check coverage tooling
if [ "${{ matrix.job_type }}" = "coverage" ]; then
if [ "${{ matrix.coverage_tool }}" = "llvm" ]; then
which "llvm-profdata-${{ matrix.compiler_version }}" && "llvm-profdata-${{ matrix.compiler_version }}" --version || echo "llvm-profdata not found"
which "llvm-cov-${{ matrix.compiler_version }}" && "llvm-cov-${{ matrix.compiler_version }}" --version || echo "llvm-cov not found"
else
which gcov && gcov --version || echo "gcov not found"
which gcovr && gcovr --version || echo "gcovr not found"
fi
fi
echo "---- Full Environment ----"
env
@@ -267,11 +337,9 @@ jobs:
cc: ${{ matrix.cc }}
cxx: ${{ matrix.cxx }}
stdlib: ${{ matrix.stdlib }}
conan_deps_cxxflags: ${{ matrix.conan_deps_cxxflags && toJson(matrix.conan_deps_cxxflags) || '{}' }}
gha_cache_enabled: 'false' # Disable caching for self hosted runner
- name: Build
if: matrix.job_type == 'build'
uses: ./.github/actions/xahau-ga-build
with:
generator: Ninja
@@ -286,28 +354,7 @@ jobs:
clang_gcc_toolchain: ${{ matrix.clang_gcc_toolchain || '' }}
ccache_max_size: '100G'
- name: Build (Coverage)
if: matrix.job_type == 'coverage'
uses: ./.github/actions/xahau-ga-build
with:
generator: Ninja
configuration: ${{ matrix.configuration }}
build_dir: ${{ env.build_dir }}
cc: ${{ matrix.cc }}
cxx: ${{ matrix.cxx }}
gcov: ${{ matrix.gcov }}
compiler-id: ${{ matrix.compiler_id }}
cache_version: ${{ env.CACHE_VERSION }}
main_branch: ${{ env.MAIN_BRANCH_NAME }}
stdlib: ${{ matrix.stdlib }}
# Coverage builds are slower due to instrumentation; use fewer parallel jobs to avoid flakiness.
# Use *_FLAGS_DEBUG so the build action's stdlib flag (e.g. -stdlib=libc++) in CMAKE_CXX_FLAGS isn't clobbered.
cmake-args: '-Dcoverage=ON -Dcoverage_tool=${{ matrix.coverage_tool }} -Dcoverage_format=${{ matrix.coverage_format }} -Dcoverage_test_parallelism=$(($(nproc)/2)) -DCODE_COVERAGE_VERBOSE=ON -DCMAKE_CXX_FLAGS_DEBUG="-g -O0" -DCMAKE_C_FLAGS_DEBUG="-g -O0"'
cmake-target: 'coverage'
ccache_max_size: '100G'
- name: Set artifact name
if: matrix.job_type == 'build'
id: set-artifact-name
run: |
ARTIFACT_NAME="build-output-nix-${{ github.run_id }}-${{ matrix.compiler }}-${{ matrix.configuration }}"
@@ -320,7 +367,6 @@ jobs:
ls -la ${{ env.build_dir }} || echo "Build directory not found or empty"
- name: Run tests
if: matrix.job_type == 'build'
run: |
# Ensure the binary exists before trying to run
if [ -f "${{ env.build_dir }}/rippled" ]; then
@@ -329,46 +375,3 @@ jobs:
echo "Error: rippled executable not found in ${{ env.build_dir }}"
exit 1
fi
# Coverage-specific steps
- name: Move coverage report
if: matrix.job_type == 'coverage'
shell: bash
env:
COVERAGE_FILE: ${{ matrix.coverage_tool == 'llvm' && 'coverage.lcov' || 'coverage.xml' }}
run: |
mv "${{ env.build_dir }}/${COVERAGE_FILE}" ./
echo "COVERAGE_FILE=${COVERAGE_FILE}" >> "$GITHUB_ENV"
- name: Archive coverage report
if: matrix.job_type == 'coverage'
uses: actions/upload-artifact@v4
with:
name: ${{ env.COVERAGE_FILE }}-${{ matrix.compiler_id }}
path: ${{ env.COVERAGE_FILE }}
retention-days: 30
- name: Upload coverage report
if: matrix.job_type == 'coverage' && github.repository == 'Xahau/xahaud'
uses: codecov/codecov-action@v5
with:
files: ${{ env.COVERAGE_FILE }}
flags: ${{ matrix.coverage_tool }}
fail_ci_if_error: true
disable_search: true
verbose: true
plugins: noop
use_oidc: true
- name: Export server definitions
if: matrix.job_type == 'build' && matrix.compiler_id == 'gcc-13-libstdcxx'
run: |
${{ env.build_dir }}/rippled --definitions | python3 -m json.tool > server_definitions.json
- name: Upload server definitions
if: matrix.job_type == 'build' && matrix.compiler_id == 'gcc-13-libstdcxx'
uses: actions/upload-artifact@v7
with:
name: server-definitions
path: server_definitions.json
archive: false
+2 -2
View File
@@ -26,7 +26,7 @@ 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.app > xrpld.peerfinder
@@ -41,7 +41,7 @@ Loop: xrpld.core xrpld.net
xrpld.net > xrpld.core
Loop: xrpld.core xrpld.perflog
xrpld.perflog ~= xrpld.core
xrpld.perflog == xrpld.core
Loop: xrpld.net xrpld.rpc
xrpld.rpc > xrpld.net
+2 -15
View File
@@ -12,7 +12,6 @@ libxrpl.server > xrpl.basics
libxrpl.server > xrpl.json
libxrpl.server > xrpl.protocol
libxrpl.server > xrpl.server
test.app > test.shamap
test.app > test.toplevel
test.app > test.unit_test
test.app > xrpl.basics
@@ -22,7 +21,6 @@ test.app > xrpld.ledger
test.app > xrpld.nodestore
test.app > xrpld.overlay
test.app > xrpld.rpc
test.app > xrpld.shamap
test.app > xrpl.hook
test.app > xrpl.json
test.app > xrpl.protocol
@@ -34,7 +32,6 @@ test.basics > xrpld.perflog
test.basics > xrpld.rpc
test.basics > xrpl.json
test.basics > xrpl.protocol
test.beast > test.unit_test
test.beast > xrpl.basics
test.conditions > xrpl.basics
test.conditions > xrpld.conditions
@@ -52,6 +49,8 @@ test.core > test.toplevel
test.core > test.unit_test
test.core > xrpl.basics
test.core > xrpld.core
test.core > xrpld.perflog
test.core > xrpl.json
test.core > xrpl.server
test.csf > xrpl.basics
test.csf > xrpld.consensus
@@ -78,11 +77,6 @@ test.ledger > xrpld.app
test.ledger > xrpld.core
test.ledger > xrpld.ledger
test.ledger > xrpl.protocol
test.net > test.toplevel
test.net > xrpl.basics
test.net > xrpld.core
test.net > xrpld.net
test.net > xrpl.json
test.nodestore > test.jtx
test.nodestore > test.toplevel
test.nodestore > test.unit_test
@@ -90,18 +84,15 @@ test.nodestore > xrpl.basics
test.nodestore > xrpld.core
test.nodestore > xrpld.nodestore
test.nodestore > xrpld.unity
test.nodestore > xrpl.protocol
test.overlay > test.jtx
test.overlay > test.toplevel
test.overlay > test.unit_test
test.overlay > xrpl.basics
test.overlay > xrpld.app
test.overlay > xrpld.core
test.overlay > xrpld.overlay
test.overlay > xrpld.peerfinder
test.overlay > xrpld.shamap
test.overlay > xrpl.protocol
test.overlay > xrpl.resource
test.peerfinder > test.beast
test.peerfinder > test.unit_test
test.peerfinder > xrpl.basics
@@ -125,10 +116,8 @@ test.rpc > xrpl.basics
test.rpc > xrpld.app
test.rpc > xrpld.core
test.rpc > xrpld.net
test.rpc > xrpld.nodestore
test.rpc > xrpld.overlay
test.rpc > xrpld.rpc
test.rpc > xrpld.shamap
test.rpc > xrpl.hook
test.rpc > xrpl.json
test.rpc > xrpl.protocol
@@ -194,7 +183,6 @@ xrpld.overlay > xrpl.basics
xrpld.overlay > xrpld.core
xrpld.overlay > xrpld.peerfinder
xrpld.overlay > xrpld.perflog
xrpld.overlay > xrpld.shamap
xrpld.overlay > xrpl.json
xrpld.overlay > xrpl.protocol
xrpld.overlay > xrpl.resource
@@ -210,7 +198,6 @@ xrpld.rpc > xrpld.core
xrpld.rpc > xrpld.ledger
xrpld.rpc > xrpld.nodestore
xrpld.rpc > xrpld.shamap
xrpld.rpc > xrpl.hook
xrpld.rpc > xrpl.json
xrpld.rpc > xrpl.protocol
xrpld.rpc > xrpl.resource
-1
View File
@@ -122,7 +122,6 @@ endif()
find_package(nudb REQUIRED)
find_package(date REQUIRED)
find_package(xxHash REQUIRED)
find_package(magic_enum REQUIRED)
include(deps/WasmEdge)
if(TARGET nudb::core)
+1 -1
View File
@@ -12,7 +12,7 @@ The server software that powers Xahau is called `xahaud` and is available in thi
### Build from Source
* [Read the build instructions in our documentation](https://xahau.network/docs/infrastructure/build-xahaud/)
* [Read the build instructions in our documentation](https://xahau.network/infrastructure/building-xahau)
* If you encounter any issues, please [open an issue](https://github.com/xahau/xahaud/issues)
## Highlights of Xahau
+3 -11
View File
@@ -88,23 +88,15 @@ git remote -v >> release.info &&
echo "Git status:" >> release.info &&
git status -v >> release.info &&
echo "Git log [last 20]:" >> release.info &&
git log -n 20 >> release.info || exit 1
git log -n 20 >> release.info;
if [[ "$4" == "" ]]; then
# Non GH, local building
echo "Non GH, local building, no Action runner magic"
else
# GH Action, runner
if [[ "$(git rev-parse --abbrev-ref HEAD)" == "release" ]]; then
echo "building on the release branch... placing it in builds/candidate"
mkdir -p /data/builds/candidate
cp /io/release-build/xahaud /data/builds/candidate/$(date +%Y).$(date +%-m).$(date +%-d)-$(git rev-parse --abbrev-ref HEAD)+$4
cp /io/release-build/release.info /data/builds/candidate/$(date +%Y).$(date +%-m).$(date +%-d)-$(git rev-parse --abbrev-ref HEAD)+$4.releaseinfo
else
echo "building non-release branch, placing it in builds root"
cp /io/release-build/xahaud /data/builds/$(date +%Y).$(date +%-m).$(date +%-d)-$(git rev-parse --abbrev-ref HEAD)+$4
cp /io/release-build/release.info /data/builds/$(date +%Y).$(date +%-m).$(date +%-d)-$(git rev-parse --abbrev-ref HEAD)+$4.releaseinfo
fi
cp /io/release-build/xahaud /data/builds/$(date +%Y).$(date +%-m).$(date +%-d)-$(git rev-parse --abbrev-ref HEAD)+$4
cp /io/release-build/release.info /data/builds/$(date +%Y).$(date +%-m).$(date +%-d)-$(git rev-parse --abbrev-ref HEAD)+$4.releaseinfo
echo "Published build to: http://build.xahau.tech/"
echo $(date +%Y).$(date +%-m).$(date +%-d)-$(git rev-parse --abbrev-ref HEAD)+$4
fi
+16 -14
View File
@@ -12,16 +12,17 @@ echo "-- GITHUB_REPOSITORY: $1"
echo "-- GITHUB_SHA: $2"
echo "-- GITHUB_RUN_NUMBER: $4"
umask 0000
umask 0000;
####
cd /io
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/^{/{
cd /io;
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());
X509_STORE *cts = SSL_CTX_get_cert_store(ctx.native_handle());
@@ -67,14 +68,15 @@ fi
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++' &&
echo "-- Build Rippled --" &&
pwd &&
echo "MOVING TO [ build-core.sh ]"
export CXX='/usr/lib64/ccache/g++' &&
echo "-- Build Rippled --" &&
pwd &&
printenv >.env.temp
cat .env.temp | grep '=' | sed s/\\\(^[^=]\\+=\\\)/\\1\\\"/g | sed s/\$/\\\"/g >.env
rm .env.temp
echo "MOVING TO [ build-core.sh ]";
printenv > .env.temp;
cat .env.temp | grep '=' | sed s/\\\(^[^=]\\+=\\\)/\\1\\\"/g|sed s/\$/\\\"/g > .env;
rm .env.temp;
echo "Persisting ENV:"
cat .env
+2 -187
View File
@@ -166,13 +166,10 @@
# ws Websockets
# wss Secure Websockets
# peer Peer Protocol
# pwa On-ledger AppLoader documents (featurePWALoader), for a
# reverse proxy only. Read "pwa ports" below first.
#
# Restrictions:
#
# Only one port may be configured to support the peer protocol.
# The pwa protocol cannot be combined with any other protocol.
# A port cannot have websocket and non websocket protocols at the
# same time. It is possible have both Websockets and Secure Websockets
# together in one port.
@@ -267,119 +264,6 @@
# "secure_gateway" connections, then they will be treated as
# "admin" addresses.
#
# pwa ports
#
# A port whose protocol is "pwa" serves accounts' on-ledger AppLoader
# documents (featurePWALoader) as HTML. This makes the node a web host
# for third-party content: anyone can publish a loader to an account
# for about a drop per byte, and nothing in protocol takes one down.
# Hosting, and a hosting provider's obligations, are yours.
#
# One host per account, on a zone used for nothing else:
#
# https://pwa<account-index>.<domain>/<r-address>
# https://<domain>/<r-address> 301 to the above
# https://<custom host>/ see custom_domains
#
# The first label of the Host header is "pwa" followed by the decimal
# AccountIndex of the account (an account created before AccountIndex
# existed has no host); the rest must be one of the port's "domain"
# values; the path must be that account's exact r-address. One
# trailing slash and a query string are ignored; anything else is
# 404. The bare zone never serves a document (every page would share
# one origin): it redirects, keeping :port and query.
# Never set cookies at or above the zone and never serve your own
# site from it. Wildcard DNS and a wildcard certificate cover it.
#
# Rules enforced at startup and on every request:
#
# - "pwa" is the port's only protocol; no admin, user/password or
# ssl_* keys (terminate TLS at the proxy).
# - "domain" is required: the zone(s), comma-separated. The proxy must
# forward the Host header unchanged.
# - "secure_gateway" is required and may not cover every address.
# Every request must come from it carrying X-Forwarded-For, whose
# RIGHTMOST entry (the one the proxy wrote) is the client. The
# "Forwarded" header is ignored.
# - Clients are metered per IPv4 address, per IPv6 /64; a miss costs
# what a hit does; over-use is answered 503 until it decays.
# - GET and HEAD only; every response closes the connection; only
# validated state is served, with an ETag (304 on If-None-Match).
# X-NetworkID, X-LedgerSeq, X-LedgerHash and X-PWASeq name the
# validated ledger and AppLoaderSequence the document came from, so
# a client (a browser extension, say) can vet it against a second
# node with the pwa_validate RPC (account, hash of the bytes, host).
# - Lookups run on at most two job queue threads, below client RPC;
# beyond a bounded backlog they are refused with 503. Put a cache in
# front (the ETag makes revalidation cheap).
# - The admin RPC "pwa_info" reports requests by outcome and bytes
# served; "reset": true zeroes them, "flush_dns": true drops the
# custom domain cache (CLI: xahaud pwa_info [reset] [flush_dns]).
#
# Example (also add port_pwa to the [server] list):
#
# [port_pwa]
# port = 8088
# ip = 127.0.0.1
# protocol = pwa
# secure_gateway = 127.0.0.1
# domain = pwapp.example
#
# with nginx in front, TLS terminated there, Host passed through:
#
# server {
# listen 443 ssl;
# server_name pwapp.example ~^pwa[0-9]+\.pwapp\.example$;
# ssl_certificate /etc/ssl/wildcard.pwapp.example.pem;
# ssl_certificate_key /etc/ssl/wildcard.pwapp.example.key;
# location / {
# proxy_pass http://127.0.0.1:8088;
# proxy_set_header Host $host;
# proxy_set_header X-Forwarded-For $remote_addr;
# }
# }
#
# custom_domains = 0 | 1
#
# Default 0. With 1, a request whose Host is outside every zone is
# served as the account named by DNS, so a domain owner can point
# their own name at your proxy:
#
# app.example.org. CNAME pwa-proxy.your.example.
# _xahau-pwa.app.example.org. TXT "rAbC..."
#
# The record lives on the _xahau-pwa label beneath the host because
# the host is usually a CNAME to your proxy. Exactly one address must
# be present there (other TXT strings are ignored; two addresses count
# as none). The named account must consent: its Domain field must
# equal the host or a parent of it (ignoring case), else 503. Lists
# apply as at the account's own host; only the root path is a
# document. No usable record is 404 (cached 15 minutes), a resolver
# failure 503 (cached 60 s), a record is cached for its TTL (clamped
# to 60..3600 s). Lookups run on their own job queue threads, at most
# four at a time and one per host; a request that misses the cache is
# answered 429 with Retry-After and a refreshing page rather than
# waiting, so a flood of Host headers cannot tie up the node. The
# admin RPC pwa_info with "flush_dns": true drops the cache. Your
# proxy must accept, and hold certificates for, the hosts you will
# serve (e.g. Caddy on-demand TLS); xahaud only sees the Host header.
#
# resolver = <IPv4 address>[:port]
#
# The recursive resolver for custom_domains; default is the system
# resolver. xahaud does not validate DNSSEC, so prefer a validating
# resolver on the same host.
#
# Documents are served with "Content-Security-Policy: sandbox
# allow-scripts ...": an opaque origin that cannot read anything from
# the node but can still send requests anywhere, including the
# visitor's own machine, so keep admin ports behind credentials.
#
# [pwa_allowlist] and [pwa_blocklist], one r-address per line, apply to
# every pwa port: if the allowlist is non-empty only those accounts are
# served; blocklisted accounts are never served (403), whatever the
# allowlist says. An account on both is a startup error.
#
# ssl_key = <filename>
# ssl_cert = <filename>
# ssl_chain = <filename>
@@ -564,30 +448,6 @@
#
#
#
# [udp_highway]
#
# 0 or 1.
#
# 0: Disable the Xahau UDP Superhighway (XUSH). [default]
# 1: Enable the Xahau UDP Superhighway (XUSH).
#
# The UDP Superhighway is a best-effort transport that runs alongside the
# peer protocol. When it is enabled the server also listens for UDP
# datagrams on its peer port number, and every transaction it relays to its
# peers is also sent, over UDP, to a small random set of other servers that
# have the highway enabled. It never replaces the peer protocol: anything
# sent over the highway is also relayed normally.
#
# To receive highway traffic, inbound UDP must be allowed to the peer port
# (in addition to inbound TCP).
#
# A server that keeps its address private (peer_private = 1, or any server
# configured as a validator) only exchanges highway traffic with the peers
# listed in [ips_fixed], and never advertises highway endpoints. Fixed peers
# are never advertised to other servers.
#
#
#
# [peers_max]
#
# The largest number of desired peer connections (incoming or outgoing).
@@ -634,7 +494,7 @@
#
# Configure the maximum number of transactions to have in the job queue
#
# Must be a number between 100 and 1000, defaults to 1000
# Must be a number between 100 and 1000, defaults to 250
#
#
# [overlay]
@@ -733,7 +593,7 @@
# reaches or exceeds this number. After that the limit may still
# change, but will stay above the target. If consensus is not
# healthy, the limit will be clamped to this value or lower.
# Default: 1000.
# Default: 50.
#
# maximum_txn_in_ledger = <number>
#
@@ -814,38 +674,6 @@
#
#
#
# [early_manifest_sync]
#
# Controls whether, while acquiring its first ledger, the server fetches and
# reads the on-ledger validator manifests ahead of the rest of that ledger's
# state. Doing so lets it resolve validators' current signing keys, including
# rotations and revocations published on-ledger, within seconds of starting
# a sync rather than once the whole state has arrived.
#
# The manifests read are those of the master keys on the server's own
# validator lists, fetched by key, and as many more from the on-ledger
# manifest directory as the manifest cache keeps.
#
# The cost is a dozen or so request/response rounds with peers. With more
# than one peer serving the ledger these overlap with fetching the rest of
# its state; with only one, they come first.
#
# It also lets a server that starts with nothing but the master keys of its
# validators and a few peers find its way. Until it has validated a ledger,
# while it holds manifests for too few of its validators to make a quorum,
# it reads them from up to three of the ledgers its peers report, the most
# widely reported first, every 15 seconds. Every manifest read is checked
# against its master key's signature, so a ledger reported by a peer that
# is not on the network can leave something out but cannot add anything.
#
# Legal values are:
# 1 - Fetch the manifests first, and from peers' ledgers if needed
# 0 - Fetch the ledger's state in the usual order, and read the manifests
# from it once it is complete
#
# The default is 1. A ledger without on-ledger manifests costs only the few
# nodes on the paths to where their directory and objects would be.
#
#
#
# [ledger_history]
@@ -1588,19 +1416,6 @@
# contains breaking changes that require a new API version number.
# They are not ready for public consumption.
#
# [hook_validate_rpc]
#
# 0 or 1.
#
# 0: Disable the hook_validate RPC method
# 1: Enable the hook_validate RPC method, which runs the Hook guard
# checker and WASM VM validation against caller-supplied code using
# the current open ledger's rules.
#
# The default is 0 on networked nodes and 1 in standalone mode (-a).
# When enabled the method is available to non-admin (user role) clients,
# so consider the CPU cost before enabling it on a public-facing node.
#
#-------------------------------------------------------------------------------
#
# 10. Example Settings
+3
View File
@@ -146,8 +146,11 @@ D686F2538F410C9D0D856788E98E3579595DAF7B38D38887F81ECAC934B06040 HooksUpdate1
3C43D9A973AA4443EF3FC38E42DD306160FBFFDAB901CD8BAA15D09F2597EB87 NonFungibleTokensV1
0285B7E5E08E1A8E4C15636F0591D87F73CB6A7B6452A932AD72BBC8E5D1CBE3 fixNFTokenDirV1
36799EA497B1369B170805C078AEFE6188345F9B3E324C21E9CA3FF574E3C3D6 fixNFTokenNegOffer
4C499D17719BB365B69010A436B64FD1A82AAB199FC1CEB06962EBD01059FB09 fixXahauV1
215181D23BF5C173314B5FDB9C872C92DE6CC918483727DE037C0C13E7E6EE9D fixXahauV2
0D8BF22FF7570D58598D1EF19EBB6E142AD46E59A223FD3816262FBB69345BEA Remit
7CA0426E7F411D39BB014E57CD9E08F61DE1750F0D41FCD428D9FB80BB7596B0 ZeroB2M
4B8466415FAB32FFA89D9DCBE166A42340115771DF611A7160F8D7439C87ECD8 fixNSDelete
EDB4EE4C524E16BDD91D9A529332DED08DCAAA51CC6DC897ACFA1A0ED131C5B6 fix240819
8063140E9260799D6716756B891CEC3E7006C4E4F277AB84670663A88F94B9C4 fixPageCap
88693F108C3CD8A967F3F4253A32DEF5E35F9406ACD2A11B88B11D90865763A9 fix240911
+4 -18
View File
@@ -95,9 +95,6 @@
# - replace both functions setup_target_for_coverage_gcovr_* with a single setup_target_for_coverage_gcovr
# - add support for all gcovr output formats
#
# 2024-04-03, Bronek Kozicki
# - add support for output formats: jacoco, clover, lcov
#
# USAGE:
#
# 1. Copy this file into your cmake modules path.
@@ -259,10 +256,10 @@ endif()
# BASE_DIRECTORY "../" # Base directory for report
# # (defaults to PROJECT_SOURCE_DIR)
# FORMAT "cobertura" # Output format, one of:
# # xml cobertura sonarqube jacoco clover
# # json-summary json-details coveralls csv
# # txt html-single html-nested html-details
# # lcov (xml is an alias to cobertura;
# # xml cobertura sonarqube json-summary
# # json-details coveralls csv txt
# # html-single html-nested html-details
# # (xml is an alias to cobertura;
# # if no format is set, defaults to xml)
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
# # to BASE_DIRECTORY, with CMake 3.4+)
@@ -311,8 +308,6 @@ function(setup_target_for_coverage_gcovr)
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.txt)
elseif(Coverage_FORMAT STREQUAL "csv")
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.csv)
elseif(Coverage_FORMAT STREQUAL "lcov")
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.lcov)
else()
set(GCOVR_OUTPUT_FILE ${Coverage_NAME}.xml)
endif()
@@ -325,14 +320,6 @@ function(setup_target_for_coverage_gcovr)
set(Coverage_FORMAT cobertura) # overwrite xml
elseif(Coverage_FORMAT STREQUAL "sonarqube")
list(APPEND GCOVR_ADDITIONAL_ARGS --sonarqube "${GCOVR_OUTPUT_FILE}" )
elseif(Coverage_FORMAT STREQUAL "jacoco")
list(APPEND GCOVR_ADDITIONAL_ARGS --jacoco "${GCOVR_OUTPUT_FILE}" )
list(APPEND GCOVR_ADDITIONAL_ARGS --jacoco-pretty )
elseif(Coverage_FORMAT STREQUAL "clover")
list(APPEND GCOVR_ADDITIONAL_ARGS --clover "${GCOVR_OUTPUT_FILE}" )
list(APPEND GCOVR_ADDITIONAL_ARGS --clover-pretty )
elseif(Coverage_FORMAT STREQUAL "lcov")
list(APPEND GCOVR_ADDITIONAL_ARGS --lcov "${GCOVR_OUTPUT_FILE}" )
elseif(Coverage_FORMAT STREQUAL "json-summary")
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary "${GCOVR_OUTPUT_FILE}" )
list(APPEND GCOVR_ADDITIONAL_ARGS --json-summary-pretty)
@@ -393,7 +380,6 @@ function(setup_target_for_coverage_gcovr)
${GCOVR_PATH}
--gcov-executable ${GCOV_TOOL}
--gcov-ignore-parse-errors=negative_hits.warn_once_per_file
--gcov-ignore-parse-errors=suspicious_hits.warn_once_per_file
-r ${BASEDIR}
${GCOVR_ADDITIONAL_ARGS}
${GCOVR_EXCLUDE_ARGS}
-156
View File
@@ -1,156 +0,0 @@
#[===================================================================[
Native LLVM source-based code coverage helper.
Drives the -fprofile-instr-generate / -fcoverage-mapping pipeline:
1. Run instrumented binary with LLVM_PROFILE_FILE=...%m-%p.profraw
2. llvm-profdata merge -sparse -> coverage.profdata
3. llvm-cov export/show/report -> final report
Output filename per coverage_format:
lcov -> coverage.lcov
json -> coverage.json
txt | text -> coverage.txt
html | html-details -> <NAME>/index.html
#]===================================================================]
include(CMakeParseArguments)
# Locate llvm-profdata / llvm-cov, preferring versioned variants matching the
# Clang we're building with so we don't accidentally pair clang-20 with
# llvm-cov-14 (profile format mismatch -> hard failure).
function(_find_llvm_cov_tools)
if(LLVM_PROFDATA_PATH AND LLVM_COV_PATH)
return()
endif()
string(REGEX MATCH "^[0-9]+" _major "${CMAKE_CXX_COMPILER_VERSION}")
set(_pd_names llvm-profdata)
set(_cov_names llvm-cov)
if(_major)
list(PREPEND _pd_names "llvm-profdata-${_major}")
list(PREPEND _cov_names "llvm-cov-${_major}")
endif()
# Only delegate to xcrun when the *compiler* is AppleClang. On macOS with
# Homebrew/system clang-N, xcrun would resolve to Xcode's llvm tools which
# could be a different version - exactly the mismatch we want to avoid.
if(APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
execute_process(COMMAND xcrun -f llvm-profdata
OUTPUT_VARIABLE _pd_xcrun OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET RESULT_VARIABLE _pd_rc)
if(_pd_rc EQUAL 0 AND _pd_xcrun)
set(LLVM_PROFDATA_PATH "${_pd_xcrun}" CACHE FILEPATH "llvm-profdata" FORCE)
endif()
execute_process(COMMAND xcrun -f llvm-cov
OUTPUT_VARIABLE _cov_xcrun OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET RESULT_VARIABLE _cov_rc)
if(_cov_rc EQUAL 0 AND _cov_xcrun)
set(LLVM_COV_PATH "${_cov_xcrun}" CACHE FILEPATH "llvm-cov" FORCE)
endif()
endif()
if(NOT LLVM_PROFDATA_PATH)
find_program(LLVM_PROFDATA_PATH NAMES ${_pd_names})
endif()
if(NOT LLVM_COV_PATH)
find_program(LLVM_COV_PATH NAMES ${_cov_names})
endif()
endfunction()
function(setup_target_for_coverage_llvm)
set(oneValueArgs NAME FORMAT)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
cmake_parse_arguments(Cov "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
_find_llvm_cov_tools()
if(NOT LLVM_PROFDATA_PATH)
message(FATAL_ERROR "llvm-profdata not found (needed for coverage_tool=llvm)")
endif()
if(NOT LLVM_COV_PATH)
message(FATAL_ERROR "llvm-cov not found (needed for coverage_tool=llvm)")
endif()
if(NOT Cov_FORMAT)
set(Cov_FORMAT lcov)
endif()
set(_profraw_dir "${PROJECT_BINARY_DIR}/${Cov_NAME}-profraw")
set(_profdata "${PROJECT_BINARY_DIR}/${Cov_NAME}.profdata")
# Resolve binary path: accept either an absolute path or a bare target name
# (resolved against PROJECT_BINARY_DIR). Splice the resolved path back into
# Cov_EXECUTABLE so the run command invokes it via absolute path - bare
# names aren't on PATH and the build dir isn't `.` either.
list(GET Cov_EXECUTABLE 0 _exec_name)
if(IS_ABSOLUTE "${_exec_name}")
set(_binary "${_exec_name}")
else()
set(_binary "${PROJECT_BINARY_DIR}/${_exec_name}")
list(REMOVE_AT Cov_EXECUTABLE 0)
list(PREPEND Cov_EXECUTABLE "${_binary}")
endif()
# llvm-cov takes a single -ignore-filename-regex; OR our excludes together.
set(_ignore_regex "")
foreach(EXC IN LISTS Cov_EXCLUDE)
if(_ignore_regex)
string(APPEND _ignore_regex "|")
endif()
string(APPEND _ignore_regex "${EXC}")
endforeach()
set(_filter "")
if(_ignore_regex)
set(_filter "-ignore-filename-regex='${_ignore_regex}'")
endif()
# Pick llvm-cov subcommand + output file for the requested format. Each
# branch builds a single shell command string that we'll hand to bash -c.
if(Cov_FORMAT STREQUAL "lcov")
set(_output "${PROJECT_BINARY_DIR}/coverage.lcov")
set(_report_sh "${LLVM_COV_PATH} export -instr-profile='${_profdata}' -format=lcov ${_filter} '${_binary}' > '${_output}'")
elseif(Cov_FORMAT STREQUAL "json")
set(_output "${PROJECT_BINARY_DIR}/coverage.json")
set(_report_sh "${LLVM_COV_PATH} export -instr-profile='${_profdata}' -format=text ${_filter} '${_binary}' > '${_output}'")
elseif(Cov_FORMAT STREQUAL "txt" OR Cov_FORMAT STREQUAL "text")
set(_output "${PROJECT_BINARY_DIR}/coverage.txt")
set(_report_sh "${LLVM_COV_PATH} report -instr-profile='${_profdata}' ${_filter} '${_binary}' > '${_output}'")
elseif(Cov_FORMAT STREQUAL "html" OR Cov_FORMAT STREQUAL "html-details")
set(_output "${PROJECT_BINARY_DIR}/${Cov_NAME}/index.html")
set(_report_sh "${LLVM_COV_PATH} show -instr-profile='${_profdata}' -format=html -output-dir='${PROJECT_BINARY_DIR}/${Cov_NAME}' ${_filter} '${_binary}'")
else()
message(FATAL_ERROR "coverage_tool=llvm: unsupported coverage_format '${Cov_FORMAT}' (use lcov|json|txt|html)")
endif()
set(_merge_sh "${LLVM_PROFDATA_PATH} merge -sparse -o '${_profdata}' '${_profraw_dir}'/*.profraw")
if(CODE_COVERAGE_VERBOSE)
message(STATUS "[coverage:llvm] binary: ${_binary}")
message(STATUS "[coverage:llvm] profraw: ${_profraw_dir}")
message(STATUS "[coverage:llvm] profdata: ${_profdata}")
message(STATUS "[coverage:llvm] format: ${Cov_FORMAT}")
message(STATUS "[coverage:llvm] output: ${_output}")
if(_ignore_regex)
message(STATUS "[coverage:llvm] ignore: ${_ignore_regex}")
endif()
message(STATUS "[coverage:llvm] merge: ${_merge_sh}")
message(STATUS "[coverage:llvm] report: ${_report_sh}")
endif()
# %m: hash of the binary, %p: pid. Wipe the dir up front so stale profraw
# files can't leak into a fresh merge.
add_custom_target(${Cov_NAME}
COMMAND ${CMAKE_COMMAND} -E rm -rf "${_profraw_dir}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${_profraw_dir}"
COMMAND ${CMAKE_COMMAND} -E env
"LLVM_PROFILE_FILE=${_profraw_dir}/rippled-%m-%p.profraw"
${Cov_EXECUTABLE} ${Cov_EXECUTABLE_ARGS}
COMMAND bash -c "${_merge_sh}"
COMMAND bash -c "${_report_sh}"
BYPRODUCTS ${_output}
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Cov_DEPENDENCIES}
VERBATIM
COMMENT "Running llvm-cov (${Cov_FORMAT}) -> ${_output}"
)
endfunction()
-1
View File
@@ -54,7 +54,6 @@ add_library(xrpl.imports.main INTERFACE)
target_link_libraries(xrpl.imports.main
INTERFACE
LibArchive::LibArchive
magic_enum::magic_enum
OpenSSL::Crypto
Ripple::boost
wasmedge::wasmedge
-15
View File
@@ -11,21 +11,6 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
return()
endif()
if(coverage_tool STREQUAL "llvm")
include(CodeCoverageLLVM)
setup_target_for_coverage_llvm(
NAME coverage
FORMAT ${coverage_format}
EXECUTABLE rippled
EXECUTABLE_ARGS --unittest$<$<BOOL:${coverage_test}>:=${coverage_test}> --unittest-jobs ${coverage_test_parallelism} --quiet --unittest-log
EXCLUDE "src/test" "include/xrpl/beast/test" "include/xrpl/beast/unit_test" "${CMAKE_BINARY_DIR}/pb-xrpl.libpb"
DEPENDENCIES rippled
)
return()
endif()
# coverage_tool == "gcov" (default): existing gcovr-driven pipeline.
include(CodeCoverage)
# The instructions for these commands come from the `CodeCoverage` module,
+4 -7
View File
@@ -28,17 +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}>,$<STREQUAL:${coverage_tool},gcov>>:-g --coverage -fprofile-abs-path>
$<$<AND:$<BOOL:${is_clang}>,$<BOOL:${coverage}>,$<STREQUAL:${coverage_tool},gcov>>:-g --coverage>
$<$<AND:$<BOOL:${is_clang}>,$<BOOL:${coverage}>,$<STREQUAL:${coverage_tool},llvm>>:-g -fprofile-instr-generate -fcoverage-mapping>
$<$<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}>,$<STREQUAL:${coverage_tool},gcov>>:-g --coverage -fprofile-abs-path>
$<$<AND:$<BOOL:${is_clang}>,$<BOOL:${coverage}>,$<STREQUAL:${coverage_tool},gcov>>:-g --coverage>
$<$<AND:$<BOOL:${is_clang}>,$<BOOL:${coverage}>,$<STREQUAL:${coverage_tool},llvm>>:-g -fprofile-instr-generate -fcoverage-mapping>
$<$<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>)
@@ -97,7 +95,6 @@ target_link_libraries (ripple_syslibs
crypt32
>
$<$<NOT:$<BOOL:${MSVC}>>:dl>
$<$<NOT:$<BOOL:${MSVC}>>:resolv>
$<$<NOT:$<OR:$<BOOL:${MSVC}>,$<BOOL:${APPLE}>>>:rt>)
if (NOT MSVC)
+2 -14
View File
@@ -29,25 +29,13 @@ if(is_gcc OR is_clang)
"Unit tests parallelism for the purpose of coverage report.")
set(coverage_format "html-details" CACHE STRING
"Output format of the coverage report.")
set(coverage_tool "gcov" CACHE STRING
"Coverage instrumentation tool: 'gcov' (default, gcc/clang via --coverage + gcovr) or 'llvm' (clang only, native source-based coverage via -fprofile-instr-generate).")
set_property(CACHE coverage_tool PROPERTY STRINGS "gcov" "llvm")
if(NOT coverage_tool MATCHES "^(gcov|llvm)$")
message(FATAL_ERROR "coverage_tool must be 'gcov' or 'llvm', got '${coverage_tool}'")
endif()
set(coverage_extra_args "" CACHE STRING
"Additional arguments to pass to gcovr (gcov tool only).")
"Additional arguments to pass to gcovr.")
set(coverage_test "" CACHE STRING
"On gcc & clang, the specific unit test(s) to run for coverage. Default is all tests.")
if(coverage_test AND NOT coverage)
set(coverage ON CACHE BOOL "gcc/clang only" FORCE)
endif()
# Validate after coverage_test may have flipped coverage on, otherwise
# `-Dcoverage_tool=llvm -Dcoverage_test=Foo` on gcc would silently slip
# past the Clang guard and produce a broken instrumentation combo.
if(coverage AND coverage_tool STREQUAL "llvm" AND NOT is_clang)
message(FATAL_ERROR "coverage_tool=llvm requires Clang (got ${CMAKE_CXX_COMPILER_ID})")
endif()
option(wextra "compile with extra gcc/clang warnings enabled" ON)
else()
set(profile OFF CACHE BOOL "gcc/clang only" FORCE)
@@ -124,7 +112,7 @@ option(beast_no_unit_test_inline
"Prevents unit test definitions from being inserted into global table"
OFF)
option(single_io_service_thread
"Restricts the number of threads calling io_context::run to one. \
"Restricts the number of threads calling io_service::run to one. \
This can be useful when debugging."
OFF)
option(boost_show_deprecated
+1 -1
View File
@@ -32,9 +32,9 @@ target_link_libraries(ripple_boost
Boost::date_time
Boost::filesystem
Boost::json
Boost::process
Boost::program_options
Boost::regex
Boost::system
Boost::iostreams
Boost::thread)
if(Boost_COMPILER)
+125 -128
View File
@@ -2,160 +2,157 @@ from conan import ConanFile
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
import re
class Xrpl(ConanFile):
name = "xrpl"
name = 'xrpl'
license = "ISC"
author = "John Freeman <[email protected]>"
url = "https://github.com/xrplf/rippled"
description = "The XRP Ledger"
settings = "os", "compiler", "build_type", "arch"
license = 'ISC'
author = 'John Freeman <[email protected]>'
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 = [
"date/3.0.3",
"grpc/1.50.1",
"libarchive/3.7.6",
"magic_enum/0.9.5",
"nudb/2.0.9",
"openssl/3.6.0",
"soci/4.0.3@xahaud/stable",
"xxhash/0.8.2",
"zlib/1.3.1",
'date/3.0.3',
'grpc/1.50.1',
'libarchive/3.7.6',
'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,
"boost/*:without_cobalt": True,
"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,
'xxhash/*:shared': False,
}
def set_version(self):
path = f"{self.recipe_folder}/src/libxrpl/protocol/BuildInfo.cpp"
regex = r"versionString\s?=\s?\"(.*)\""
with open(path, "r") as file:
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):
# Force sqlite3 version to avoid conflicts with soci
self.requires("sqlite3/3.47.0", 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)
self.requires('snappy/1.1.10@xahaud/stable', override=True)
# Force boost version for all dependencies to avoid conflicts
self.requires("boost/1.91.0", override=True)
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")
self.requires('wasmedge/0.11.2@xahaud/stable')
if self.options.jemalloc:
self.requires("jemalloc/5.3.0")
self.requires('jemalloc/5.3.0')
if self.options.rocksdb:
self.requires("rocksdb/6.29.5")
self.requires('rocksdb/6.29.5')
exports_sources = (
"CMakeLists.txt",
"bin/getRippledInfo",
"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"
generators = "CMakeDeps"
self.folders.generators = 'build/generators'
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):
@@ -170,29 +167,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::boost",
"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')
-1
View File
@@ -47,6 +47,5 @@
#define MEM_OVERLAP -43
#define TOO_MANY_STATE_MODIFICATIONS -44
#define TOO_MANY_NAMESPACES -45
#define TOO_LITTLE_ENTROPY -46
#define HOOK_ERROR_CODES
#endif //HOOK_ERROR_CODES
-12
View File
@@ -2,9 +2,6 @@
// Generated using generate_extern.sh
#include <stdint.h>
#ifndef HOOK_EXTERN
#ifdef __cplusplus
extern "C" {
#endif
extern int32_t __attribute__((noduplicate))
_g(uint32_t guard_id, uint32_t maxiter);
@@ -339,14 +336,5 @@ prepare(
uint32_t read_ptr,
uint32_t read_len);
extern int64_t
dice(uint32_t sides);
extern int64_t
util_random(uint32_t write_ptr, uint32_t write_len);
#ifdef __cplusplus
}
#endif
#define HOOK_EXTERN
#endif // HOOK_EXTERN
+2 -2
View File
@@ -9,7 +9,7 @@ ENUM_FILE="$SCRIPT_DIR/../include/xrpl/hook/Enum.h"
echo '// For documentation please see: https://xrpl-hooks.readme.io/reference/'
echo '// Generated using generate_error.sh'
echo '#ifndef HOOK_ERROR_CODES'
sed -n '/enum class hook_return_code/,/};/p' "$ENUM_FILE" |
sed -n '/enum hook_return_code/,/};/p' "$ENUM_FILE" |
awk '
function ltrim(s) { sub(/^[[:space:]]+/, "", s); return s }
function rtrim(s) { sub(/[[:space:]]+$/, "", s); return s }
@@ -31,7 +31,7 @@ sed -n '/enum class hook_return_code/,/};/p' "$ENUM_FILE" |
{
line = $0
if (line ~ /enum[[:space:]]+class[[:space:]]+hook_return_code/)
if (line ~ /enum[[:space:]]+hook_return_code/)
next
if (line ~ /^[[:space:]]*\{/)
next
+23 -29
View File
@@ -11,9 +11,6 @@ APPLY_HOOK="$SCRIPT_DIR/../include/xrpl/hook/hook_api.macro"
echo '// Generated using generate_extern.sh'
echo '#include <stdint.h>'
echo '#ifndef HOOK_EXTERN'
echo '#ifdef __cplusplus'
echo 'extern "C" {'
echo '#endif'
echo
awk '
function trim(s) {
@@ -22,36 +19,33 @@ APPLY_HOOK="$SCRIPT_DIR/../include/xrpl/hook/hook_api.macro"
return s;
}
# Each entry is HOOK_API_DEFINITION(RET, NAME, (PARAMS), AMENDMENT),
# possibly spread over several lines. Collect until the parentheses
# balance, then split on the first two commas; the parameter tuple
# is the first parenthesised group.
function emit(s, i, ret, name, p, q, params) {
sub(/^[[:space:]]*HOOK_API_DEFINITION[[:space:]]*\(/, "", s);
gsub(/[[:space:]]+/, " ", s);
i = index(s, ","); ret = trim(substr(s, 1, i - 1)); s = substr(s, i + 1);
i = index(s, ","); name = trim(substr(s, 1, i - 1)); s = substr(s, i + 1);
p = index(s, "("); q = index(s, ")");
params = trim(substr(s, p + 1, q - p - 1));
if (name == "_g")
name = "__attribute__((noduplicate)) _g";
printf("extern %s %s(%s);\n\n", ret, name, params);
}
/^[[:space:]]*HOOK_API_DEFINITION[[:space:]]*\(/ { buf = ""; collecting = 1; }
collecting {
buf = buf " " $0;
if (gsub(/\(/, "(", buf) == gsub(/\)/, ")", buf)) {
collecting = 0;
emit(buf);
{
line = $0;
# Skip block comments
if (line ~ /\/\*/) {
next;
}
# Look for comment lines that start with // and contain function signature
if (line ~ /^[[:space:]]*\/\/[[:space:]]*[a-zA-Z_][a-zA-Z0-9_]*[[:space:]]+[a-zA-Z_][a-zA-Z0-9_]*[[:space:]]*\(/) {
# Remove leading // and trim
sub(/^[[:space:]]*\/\/[[:space:]]*/, "", line);
line = trim(line);
# Check if function name is "_g" to add attribute
if (line ~ /[[:space:]]+_g[[:space:]]*\(/) {
# Insert __attribute__((noduplicate)) before _g
sub(/[[:space:]]+_g/, " __attribute__((noduplicate)) _g", line);
}
# printf("\n");
printf("extern %s\n\n", line);
}
}
' "$APPLY_HOOK"
echo '#ifdef __cplusplus'
echo '}'
echo '#endif'
echo '#define HOOK_EXTERN'
echo '#endif // HOOK_EXTERN'
} | (
-82
View File
@@ -1,82 +0,0 @@
#!/bin/bash
set -eu
SCRIPT_DIR=$(dirname "$0")
SCRIPT_DIR=$(cd "$SCRIPT_DIR" && pwd)
RIPPLED_ROOT="$SCRIPT_DIR/../include/xrpl"
LEDGER_FORMATS="$RIPPLED_ROOT/protocol/LedgerFormats.h"
echo '// Generated using generate_lsflags.sh'
echo ''
echo '#ifndef HOOKLSFLAGS_INCLUDED'
echo '#define HOOKLSFLAGS_INCLUDED 1'
echo ''
awk '
function ltrim(s) { sub(/^[[:space:]]+/, "", s); return s }
function rtrim(s) { sub(/[[:space:]]+$/, "", s); return s }
function trim(s) { return rtrim(ltrim(s)) }
function flush_group() {
if (entry_count > 0 && group != "") {
printf "enum %s {\n", group
for (i = 1; i <= entry_count; i++) {
printf " %s,\n", entries[i]
}
printf "};\n"
}
delete entries
entry_count = 0
}
/enum LedgerSpecificFlags \{/ { inside = 1; next }
inside && /^\};/ { inside = 0; flush_group(); next }
!inside { next }
# Group header comments: // ltFOO or // remarks
/^[[:space:]]*\/\/[[:space:]]*(lt[A-Z_]+|remarks)[[:space:]]*$/ {
flush_group()
line = $0
sub(/.*\/\/[[:space:]]*/, "", line)
group = trim(line)
next
}
# Skip pure comment lines (not group headers)
/^[[:space:]]*\/\// { next }
# Skip blank lines
/^[[:space:]]*$/ { next }
# Accumulate flag lines (handle multi-line values)
{
line = $0
# Strip inline comments
sub(/\/\/.*/, "", line)
line = trim(line)
if (line == "") next
if (pending != "") {
pending = pending " " line
} else {
pending = line
}
# If line ends with comma, the entry is complete
if (pending ~ /,$/) {
# Remove trailing comma
sub(/,$/, "", pending)
entries[++entry_count] = pending
pending = ""
}
}
BEGIN {
inside = 0
group = ""
pending = ""
entry_count = 0
}
' "$LEDGER_FORMATS"
echo ''
echo '#endif // HOOKLSFLAGS_INCLUDED'
-25
View File
@@ -1,25 +0,0 @@
#!/bin/bash
set -eu
SCRIPT_DIR=$(dirname "$0")
SCRIPT_DIR=$(cd "$SCRIPT_DIR" && pwd)
RIPPLED_ROOT="$SCRIPT_DIR/../include/xrpl"
TX_FLAGS="$RIPPLED_ROOT/protocol/TxFlags.h"
echo '// Generated using generate_txflags.sh'
echo '#include "ls_flags.h"'
echo '#include <stdint.h>'
echo ''
cat "$TX_FLAGS" |
awk '
/^[[:space:]]*enum / {
if (count > 0) print ""
inside = 1
count++
}
inside {
print
if (/};/) inside = 0
}
'
-203
View File
@@ -1,203 +0,0 @@
#!/bin/bash
# build_xahau_h.sh
# Builds genesis hook WASMs and updates xahau.h with hex arrays
set -euo pipefail
# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Script directory and path constants
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
XAHAU_H="${SCRIPT_DIR}/../../include/xrpl/hook/xahau.h"
TEMP_DIR="${SCRIPT_DIR}/.temp"
# Hook file mappings (space-separated: name:file)
HOOK_FILES=(
"GovernanceHook:govern.wasm"
"RewardHook:reward.wasm"
# "MintHook:mint.wasm"
)
# Cleanup function
cleanup() {
local exit_code=$?
if [ ${exit_code} -eq 0 ] && [ -d "${TEMP_DIR}" ]; then
rm -rf "${TEMP_DIR}"
elif [ ${exit_code} -ne 0 ]; then
echo -e "${RED}Error: Script failed with exit code ${exit_code}${NC}" >&2
if [ -d "${TEMP_DIR}" ]; then
echo -e "${YELLOW}Temp files preserved at: ${TEMP_DIR}${NC}" >&2
fi
fi
exit ${exit_code}
}
trap cleanup EXIT INT TERM
# Tool verification
echo -e "${BLUE}==> Checking required tools...${NC}"
REQUIRED_TOOLS=("make" "xxd" "sed" "clang-format" "wasm-opt")
for tool in "${REQUIRED_TOOLS[@]}"; do
if ! command -v "${tool}" &> /dev/null; then
echo -e "${RED}Error: Required tool '${tool}' not found${NC}" >&2
exit 1
fi
echo -e "${GREEN} ✓ ${tool}${NC}"
done
# Verify wasm-opt version is exactly 100
WASM_OPT_VERSION=$(wasm-opt --version | grep -oE '[0-9]+' | head -1)
if [ "${WASM_OPT_VERSION}" != "100" ]; then
echo -e "${RED}Error: wasm-opt version must be 100, but found ${WASM_OPT_VERSION}${NC}" >&2
exit 1
fi
echo -e "${GREEN} ✓ wasm-opt version 100${NC}"
# Verify xahau.h exists
if [ ! -f "${XAHAU_H}" ]; then
echo -e "${RED}Error: xahau.h not found at ${XAHAU_H}${NC}" >&2
exit 1
fi
# Create temp directory
mkdir -p "${TEMP_DIR}"
# Build all WASM files
echo -e "${BLUE}==> Building WASM files with 'make all'...${NC}"
cd "${SCRIPT_DIR}"
make all
echo -e "${GREEN} Build completed successfully${NC}"
# Function to convert WASM to hex array
wasm_to_hex_array() {
local wasm_file="$1"
local indent=" "
if [ ! -f "${wasm_file}" ]; then
echo -e "${RED}Error: WASM file not found: ${wasm_file}${NC}" >&2
return 1
fi
# Convert to hex with xxd, format with sed
xxd -p -u -c 10 "${wasm_file}" | \
sed 's/../0x&U,/g' | \
sed "s/^/${indent}/g" | \
sed '$ s/,$//'
}
# Function to update hook array in xahau.h
update_hook_array() {
local hook_name="$1"
local hex_array="$2"
local temp_file="${TEMP_DIR}/xahau.h.tmp"
echo -e "${BLUE}==> Updating ${hook_name}...${NC}"
# Check if hook already exists
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 const std::vector<uint8_t> " hook " = {") {
print $0
print hex
in_array=1
next
}
if (in_array && $0 ~ /};/) {
print "};"
in_array=0
next
}
if (!in_array) {
print $0
}
}
' "${XAHAU_H}" > "${temp_file}"
mv "${temp_file}" "${XAHAU_H}"
else
echo -e "${YELLOW} Adding new ${hook_name}${NC}"
# Find the position before #endif and add the new hook
awk -v hook="${hook_name}" -v hex="${hex_array}" '
{
if ($0 ~ /#endif.*XAHAU_GENESIS_HOOKS/) {
print ""
print "static const std::vector<uint8_t> " hook " = {"
print hex
print "};"
print ""
print $0
} else {
print $0
}
}
' "${XAHAU_H}" > "${temp_file}"
mv "${temp_file}" "${XAHAU_H}"
fi
echo -e "${GREEN} ✓ ${hook_name} updated${NC}"
}
# Process each hook
for hook_entry in "${HOOK_FILES[@]}"; do
hook_name="${hook_entry%%:*}"
wasm_file="${SCRIPT_DIR}/${hook_entry##*:}"
echo -e "${BLUE}==> Converting ${wasm_file} to hex array...${NC}"
hex_array=$(wasm_to_hex_array "${wasm_file}")
if [ $? -ne 0 ]; then
echo -e "${RED}Error: Failed to convert ${wasm_file}${NC}" >&2
exit 1
fi
echo -e "${GREEN} Conversion successful ($(echo "${hex_array}" | wc -l) lines)${NC}"
update_hook_array "${hook_name}" "${hex_array}"
done
# Format with clang-format
echo -e "${BLUE}==> Formatting with clang-format...${NC}"
cp "${XAHAU_H}" "${TEMP_DIR}/xahau.h.before_format"
clang-format -i "${XAHAU_H}"
echo -e "${GREEN} Formatting completed${NC}"
# Verification
echo -e "${BLUE}==> Verifying changes...${NC}"
for hook_entry in "${HOOK_FILES[@]}"; do
hook_name="${hook_entry%%:*}"
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
exit 1
fi
done
# Show summary
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}Successfully updated xahau.h${NC}"
echo -e "${GREEN}========================================${NC}"
echo -e "Updated hooks:"
for hook_entry in "${HOOK_FILES[@]}"; do
hook_name="${hook_entry%%:*}"
wasm_file="${SCRIPT_DIR}/${hook_entry##*:}"
size=$(wc -c < "${wasm_file}" | tr -d ' ')
echo -e " - ${hook_name}: ${size} bytes"
done
echo ""
echo -e "File location: ${XAHAU_H}"
echo ""
-46
View File
@@ -1,46 +0,0 @@
// For documentation please see: https://xrpl-hooks.readme.io/reference/
// Generated using generate_error.sh
#ifndef HOOK_ERROR_CODES
#define SUCCESS 0
#define OUT_OF_BOUNDS -1
#define INTERNAL_ERROR -2
#define TOO_BIG -3
#define TOO_SMALL -4
#define DOESNT_EXIST -5
#define NO_FREE_SLOTS -6
#define INVALID_ARGUMENT -7
#define ALREADY_SET -8
#define PREREQUISITE_NOT_MET -9
#define FEE_TOO_LARGE -10
#define EMISSION_FAILURE -11
#define TOO_MANY_NONCES -12
#define TOO_MANY_EMITTED_TXN -13
#define NOT_IMPLEMENTED -14
#define INVALID_ACCOUNT -15
#define GUARD_VIOLATION -16
#define INVALID_FIELD -17
#define PARSE_ERROR -18
#define RC_ROLLBACK -19
#define RC_ACCEPT -20
#define NO_SUCH_KEYLET -21
#define NOT_AN_ARRAY -22
#define NOT_AN_OBJECT -23
#define INVALID_FLOAT -10024
#define DIVISION_BY_ZERO -25
#define MANTISSA_OVERSIZED -26
#define MANTISSA_UNDERSIZED -27
#define EXPONENT_OVERSIZED -28
#define EXPONENT_UNDERSIZED -29
#define OVERFLOW -30
#define NOT_IOU_AMOUNT -31
#define NOT_AN_AMOUNT -32
#define CANT_RETURN_NEGATIVE -33
#define NOT_AUTHORIZED -34
#define PREVIOUS_FAILURE_PREVENTS_RETRY -35
#define TOO_MANY_PARAMS -36
#define INVALID_TXN -37
#define RESERVE_INSUFFICIENT -38
#define COMPLEX_NOT_SUPPORTED -39
#define DOES_NOT_MATCH -40
#define HOOK_ERROR_CODES
#endif //HOOK_ERROR_CODES
-352
View File
@@ -1,352 +0,0 @@
// For documentation please see: https://xrpl-hooks.readme.io/reference/
// Generated using generate_extern.sh
#include <stdint.h>
#ifndef HOOK_EXTERN
extern int32_t __attribute__((noduplicate))
_g(uint32_t guard_id, uint32_t maxiter);
extern int64_t
accept(uint32_t read_ptr, uint32_t read_len, int64_t error_code);
extern int64_t
emit(
uint32_t write_ptr,
uint32_t write_len,
uint32_t read_ptr,
uint32_t read_len);
extern int64_t
etxn_burden(void);
extern int64_t
etxn_details(uint32_t write_ptr, uint32_t write_len);
extern int64_t
etxn_fee_base(uint32_t read_ptr, uint32_t read_len);
extern int64_t
etxn_generation(void);
extern int64_t
etxn_nonce(uint32_t write_ptr, uint32_t write_len);
extern int64_t
etxn_reserve(uint32_t count);
extern int64_t
fee_base(void);
extern int64_t
float_compare(int64_t float1, int64_t float2, uint32_t mode);
extern int64_t
float_divide(int64_t float1, int64_t float2);
extern int64_t
float_exponent(int64_t float1);
extern int64_t
float_exponent_set(int64_t float1, int32_t exponent);
extern int64_t
float_int(int64_t float1, uint32_t decimal_places, uint32_t abs);
extern int64_t
float_invert(int64_t float1);
extern int64_t
float_log(int64_t float1);
extern int64_t
float_mantissa(int64_t float1);
extern int64_t
float_mantissa_set(int64_t float1, int64_t mantissa);
extern int64_t
float_mulratio(
int64_t float1,
uint32_t round_up,
uint32_t numerator,
uint32_t denominator);
extern int64_t
float_multiply(int64_t float1, int64_t float2);
extern int64_t
float_negate(int64_t float1);
extern int64_t
float_one(void);
extern int64_t
float_root(int64_t float1, uint32_t n);
extern int64_t
float_set(int32_t exponent, int64_t mantissa);
extern int64_t
float_sign(int64_t float1);
extern int64_t
float_sign_set(int64_t float1, uint32_t negative);
extern int64_t
float_sto(
uint32_t write_ptr,
uint32_t write_len,
uint32_t cread_ptr,
uint32_t cread_len,
uint32_t iread_ptr,
uint32_t iread_len,
int64_t float1,
uint32_t field_code);
extern int64_t
float_sto_set(uint32_t read_ptr, uint32_t read_len);
extern int64_t
float_sum(int64_t float1, int64_t float2);
extern int64_t
hook_account(uint32_t write_ptr, uint32_t write_len);
extern int64_t
hook_again(void);
extern int64_t
hook_hash(uint32_t write_ptr, uint32_t write_len, int32_t hook_no);
extern int64_t
hook_param(
uint32_t write_ptr,
uint32_t write_len,
uint32_t read_ptr,
uint32_t read_len);
extern int64_t
otxn_param(
uint32_t write_ptr,
uint32_t write_len,
uint32_t read_ptr,
uint32_t read_len);
extern int64_t
hook_param_set(
uint32_t read_ptr,
uint32_t read_len,
uint32_t kread_ptr,
uint32_t kread_len,
uint32_t hread_ptr,
uint32_t hread_len);
extern int64_t
hook_pos(void);
extern int64_t
hook_skip(uint32_t read_ptr, uint32_t read_len, uint32_t flags);
extern int64_t
ledger_keylet(
uint32_t write_ptr,
uint32_t write_len,
uint32_t lread_ptr,
uint32_t lread_len,
uint32_t hread_ptr,
uint32_t hread_len);
extern int64_t
ledger_last_hash(uint32_t write_ptr, uint32_t write_len);
extern int64_t
ledger_last_time(void);
extern int64_t
ledger_nonce(uint32_t write_ptr, uint32_t write_len);
extern int64_t
ledger_seq(void);
extern int64_t
meta_slot(uint32_t slot_no);
extern int64_t
otxn_burden(void);
extern int64_t
otxn_field(uint32_t write_ptr, uint32_t write_len, uint32_t field_id);
extern int64_t
otxn_field_txt(uint32_t write_ptr, uint32_t write_len, uint32_t field_id);
extern int64_t
otxn_generation(void);
extern int64_t
otxn_id(uint32_t write_ptr, uint32_t write_len, uint32_t flags);
extern int64_t
otxn_slot(uint32_t slot_no);
extern int64_t
otxn_type(void);
extern int64_t
rollback(uint32_t read_ptr, uint32_t read_len, int64_t error_code);
extern int64_t
slot(uint32_t write_ptr, uint32_t write_len, uint32_t slot);
extern int64_t
slot_clear(uint32_t slot);
extern int64_t
slot_count(uint32_t slot);
extern int64_t
slot_float(uint32_t slot_no);
extern int64_t
slot_id(uint32_t write_ptr, uint32_t write_len, uint32_t slot);
extern int64_t
slot_set(uint32_t read_ptr, uint32_t read_len, uint32_t slot);
extern int64_t
slot_size(uint32_t slot);
extern int64_t
slot_subarray(uint32_t parent_slot, uint32_t array_id, uint32_t new_slot);
extern int64_t
slot_subfield(uint32_t parent_slot, uint32_t field_id, uint32_t new_slot);
extern int64_t
slot_type(uint32_t slot_no, uint32_t flags);
extern int64_t
state(
uint32_t write_ptr,
uint32_t write_len,
uint32_t kread_ptr,
uint32_t kread_len);
extern int64_t
state_foreign(
uint32_t write_ptr,
uint32_t write_len,
uint32_t kread_ptr,
uint32_t kread_len,
uint32_t nread_ptr,
uint32_t nread_len,
uint32_t aread_ptr,
uint32_t aread_len);
extern int64_t
state_foreign_set(
uint32_t read_ptr,
uint32_t read_len,
uint32_t kread_ptr,
uint32_t kread_len,
uint32_t nread_ptr,
uint32_t nread_len,
uint32_t aread_ptr,
uint32_t aread_len);
extern int64_t
state_set(
uint32_t read_ptr,
uint32_t read_len,
uint32_t kread_ptr,
uint32_t kread_len);
extern int64_t
sto_emplace(
uint32_t write_ptr,
uint32_t write_len,
uint32_t sread_ptr,
uint32_t sread_len,
uint32_t fread_ptr,
uint32_t fread_len,
uint32_t field_id);
extern int64_t
sto_erase(
uint32_t write_ptr,
uint32_t write_len,
uint32_t read_ptr,
uint32_t read_len,
uint32_t field_id);
extern int64_t
sto_subarray(uint32_t read_ptr, uint32_t read_len, uint32_t array_id);
extern int64_t
sto_subfield(uint32_t read_ptr, uint32_t read_len, uint32_t field_id);
extern int64_t
sto_validate(uint32_t tread_ptr, uint32_t tread_len);
extern int64_t
trace(
uint32_t mread_ptr,
uint32_t mread_len,
uint32_t dread_ptr,
uint32_t dread_len,
uint32_t as_hex);
extern int64_t
trace_float(uint32_t read_ptr, uint32_t read_len, int64_t float1);
extern int64_t
trace_num(uint32_t read_ptr, uint32_t read_len, int64_t number);
extern int64_t
trace_slot(uint32_t read_ptr, uint32_t read_len, uint32_t slot);
extern int64_t
util_accid(
uint32_t write_ptr,
uint32_t write_len,
uint32_t read_ptr,
uint32_t read_len);
extern int64_t
util_keylet(
uint32_t write_ptr,
uint32_t write_len,
uint32_t keylet_type,
uint32_t a,
uint32_t b,
uint32_t c,
uint32_t d,
uint32_t e,
uint32_t f);
extern int64_t
util_raddr(
uint32_t write_ptr,
uint32_t write_len,
uint32_t read_ptr,
uint32_t read_len);
extern int64_t
util_sha512h(
uint32_t write_ptr,
uint32_t write_len,
uint32_t read_ptr,
uint32_t read_len);
extern int64_t
util_verify(
uint32_t dread_ptr,
uint32_t dread_len,
uint32_t sread_ptr,
uint32_t sread_len,
uint32_t kread_ptr,
uint32_t kread_len);
extern int64_t xpop_slot(uint32_t, uint32_t);
#define HOOK_EXTERN
#endif // HOOK_EXTERN
-50
View File
@@ -1,50 +0,0 @@
/**
* Hook API include file
*
* Note to the reader:
* This include defines two types of things: external functions and macros
* Functions are used sparingly because a non-inlining compiler may produce
* undesirable output.
*
* Find documentation here: https://xrpl-hooks.readme.io/reference/
*/
#ifndef HOOKAPI_INCLUDED
#define HOOKAPI_INCLUDED 1
#define KEYLET_HOOK 1
#define KEYLET_HOOK_STATE 2
#define KEYLET_ACCOUNT 3
#define KEYLET_AMENDMENTS 4
#define KEYLET_CHILD 5
#define KEYLET_SKIP 6
#define KEYLET_FEES 7
#define KEYLET_NEGATIVE_UNL 8
#define KEYLET_LINE 9
#define KEYLET_OFFER 10
#define KEYLET_QUALITY 11
#define KEYLET_EMITTED_DIR 12
#define KEYLET_TICKET 13
#define KEYLET_SIGNERS 14
#define KEYLET_CHECK 15
#define KEYLET_DEPOSIT_PREAUTH 16
#define KEYLET_UNCHECKED 17
#define KEYLET_OWNER_DIR 18
#define KEYLET_PAGE 19
#define KEYLET_ESCROW 20
#define KEYLET_PAYCHAN 21
#define KEYLET_EMITTED 22
#define KEYLET_NFT_OFFER 23
#define KEYLET_HOOK_DEFINITION 24
#define COMPARE_EQUAL 1U
#define COMPARE_LESS 2U
#define COMPARE_GREATER 4U
#include "error.h"
#include "extern.h"
#include "sfcodes.h"
#include "macro.h"
#include "types.h"
#endif
-671
View File
@@ -1,671 +0,0 @@
/**
* These are helper macros for writing hooks, all of them are optional as is including hookmacro.h at all
*/
#include <stdint.h>
#include "hookapi.h"
#include "sfcodes.h"
#ifndef HOOKMACROS_INCLUDED
#define HOOKMACROS_INCLUDED 1
#ifdef NDEBUG
#define DEBUG 0
#else
#define DEBUG 1
#endif
#define TRACEVAR(v) if (DEBUG) trace_num((uint32_t)(#v), (uint32_t)(sizeof(#v) - 1), (int64_t)v);
#define TRACEHEX(v) if (DEBUG) trace((uint32_t)(#v), (uint32_t)(sizeof(#v) - 1), (uint32_t)(v), (uint32_t)(sizeof(v)), 1);
#define TRACEXFL(v) if (DEBUG) trace_float((uint32_t)(#v), (uint32_t)(sizeof(#v) - 1), (int64_t)v);
#define TRACESTR(v) if (DEBUG) trace((uint32_t)(#v), (uint32_t)(sizeof(#v) - 1), (uint32_t)(v), sizeof(v), 0);
// hook developers should use this guard macro, simply GUARD(<maximum iterations>)
#define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1)
#define GUARDM(maxiter, n) _g(( (1ULL << 31U) + (__LINE__ << 16) + n), (maxiter)+1)
#define SBUF(str) (uint32_t)(str), sizeof(str)
#define REQUIRE(cond, str)\
{\
if (!(cond))\
rollback(SBUF(str), __LINE__);\
}
// make a report buffer as a c-string
// provide a name for a buffer to declare (buf)
// provide a static string
// provide an integer to print after the string
#define RBUF(buf, out_len, str, num)\
unsigned char buf[sizeof(str) + 21];\
int out_len = 0;\
{\
int i = 0;\
for (; GUARDM(sizeof(str),1),i < sizeof(str); ++i)\
(buf)[i] = str[i];\
if ((buf)[sizeof(str)-1] == 0) i--;\
if ((num) < 0) (buf)[i++] = '-';\
uint64_t unsigned_num = (uint64_t)( (num) < 0 ? (num) * -1 : (num) );\
uint64_t j = 10000000000000000000ULL;\
int start = 1;\
for (; GUARDM(20,2), unsigned_num > 0 && j > 0; j /= 10)\
{\
unsigned char digit = ( unsigned_num / j ) % 10;\
if (digit == 0 && start)\
continue;\
start = 0;\
(buf)[i++] = '0' + digit;\
}\
(buf)[i] = '\0';\
out_len = i;\
}
#define RBUF2(buff, out_len, str, num, str2, num2)\
unsigned char buff[sizeof(str) + sizeof(str2) + 42];\
int out_len = 0;\
{\
unsigned char* buf = buff;\
int i = 0;\
for (; GUARDM(sizeof(str),1),i < sizeof(str); ++i)\
(buf)[i] = str[i];\
if ((buf)[sizeof(str)-1] == 0) i--;\
if ((num) < 0) (buf)[i++] = '-';\
uint64_t unsigned_num = (uint64_t)( (num) < 0 ? (num) * -1 : (num) );\
uint64_t j = 10000000000000000000ULL;\
int start = 1;\
for (; GUARDM(20,2), unsigned_num > 0 && j > 0; j /= 10)\
{\
unsigned char digit = ( unsigned_num / j ) % 10;\
if (digit == 0 && start)\
continue;\
start = 0;\
(buf)[i++] = '0' + digit;\
}\
buf += i;\
out_len += i;\
i = 0;\
for (; GUARDM(sizeof(str2),3),i < sizeof(str2); ++i)\
(buf)[i] = str2[i];\
if ((buf)[sizeof(str2)-1] == 0) i--;\
if ((num2) < 0) (buf)[i++] = '-';\
unsigned_num = (uint64_t)( (num2) < 0 ? (num2) * -1 : (num2) );\
j = 10000000000000000000ULL;\
start = 1;\
for (; GUARDM(20,4), unsigned_num > 0 && j > 0; j /= 10)\
{\
unsigned char digit = ( unsigned_num / j ) % 10;\
if (digit == 0 && start)\
continue;\
start = 0;\
(buf)[i++] = '0' + digit;\
}\
(buf)[i] = '\0';\
out_len += i;\
}
#define CLEARBUF(b)\
{\
for (int x = 0; GUARD(sizeof(b)), x < sizeof(b); ++x)\
b[x] = 0;\
}
// returns an in64_t, negative if error, non-negative if valid drops
#define AMOUNT_TO_DROPS(amount_buffer)\
(((amount_buffer)[0] >> 7) ? -2 : (\
((((uint64_t)((amount_buffer)[0])) & 0xb00111111) << 56) +\
(((uint64_t)((amount_buffer)[1])) << 48) +\
(((uint64_t)((amount_buffer)[2])) << 40) +\
(((uint64_t)((amount_buffer)[3])) << 32) +\
(((uint64_t)((amount_buffer)[4])) << 24) +\
(((uint64_t)((amount_buffer)[5])) << 16) +\
(((uint64_t)((amount_buffer)[6])) << 8) +\
(((uint64_t)((amount_buffer)[7])))))
#define SUB_OFFSET(x) ((int32_t)(x >> 32))
#define SUB_LENGTH(x) ((int32_t)(x & 0xFFFFFFFFULL))
#define BUFFER_EQUAL_20(buf1, buf2)\
(\
*(((uint64_t*)(buf1)) + 0) == *(((uint64_t*)(buf2)) + 0) &&\
*(((uint64_t*)(buf1)) + 1) == *(((uint64_t*)(buf2)) + 1) &&\
*(((uint32_t*)(buf1)) + 4) == *(((uint32_t*)(buf2)) + 4))
#define BUFFER_EQUAL_32(buf1, buf2)\
(\
*(((uint64_t*)(buf1)) + 0) == *(((uint64_t*)(buf2)) + 0) &&\
*(((uint64_t*)(buf1)) + 1) == *(((uint64_t*)(buf2)) + 1) &&\
*(((uint64_t*)(buf1)) + 2) == *(((uint64_t*)(buf2)) + 2) &&\
*(((uint64_t*)(buf1)) + 3) == *(((uint64_t*)(buf2)) + 3))
// when using this macro buf1len may be dynamic but buf2len must be static
// provide n >= 1 to indicate how many times the macro will be hit on the line of code
// e.g. if it is in a loop that loops 10 times n = 10
#define BUFFER_EQUAL_GUARD(output, buf1, buf1len, buf2, buf2len, n)\
{\
output = ((buf1len) == (buf2len) ? 1 : 0);\
for (int x = 0; GUARDM( (buf2len) * (n), 1 ), output && x < (buf2len);\
++x)\
output = *(((uint8_t*)(buf1)) + x) == *(((uint8_t*)(buf2)) + x);\
}
#define BUFFER_SWAP(x,y)\
{\
uint8_t* z = x;\
x = y;\
y = z;\
}
#define ACCOUNT_COMPARE(compare_result, buf1, buf2)\
{\
compare_result = 0;\
for (int i = 0; GUARD(20), i < 20; ++i)\
{\
if (buf1[i] > buf2[i])\
{\
compare_result = 1;\
break;\
}\
else if (buf1[i] < buf2[i])\
{\
compare_result = -1;\
break;\
}\
}\
}
#define BUFFER_EQUAL_STR_GUARD(output, buf1, buf1len, str, n)\
BUFFER_EQUAL_GUARD(output, buf1, buf1len, str, (sizeof(str)-1), n)
#define BUFFER_EQUAL_STR(output, buf1, buf1len, str)\
BUFFER_EQUAL_GUARD(output, buf1, buf1len, str, (sizeof(str)-1), 1)
#define BUFFER_EQUAL(output, buf1, buf2, compare_len)\
BUFFER_EQUAL_GUARD(output, buf1, compare_len, buf2, compare_len, 1)
#define UINT16_TO_BUF(buf_raw, i)\
{\
unsigned char* buf = (unsigned char*)buf_raw;\
buf[0] = (((uint64_t)i) >> 8) & 0xFFUL;\
buf[1] = (((uint64_t)i) >> 0) & 0xFFUL;\
}
#define UINT16_FROM_BUF(buf)\
(((uint64_t)((buf)[0]) << 8) +\
((uint64_t)((buf)[1]) << 0))
#define UINT32_TO_BUF(buf_raw, i)\
{\
unsigned char* buf = (unsigned char*)buf_raw;\
buf[0] = (((uint64_t)i) >> 24) & 0xFFUL;\
buf[1] = (((uint64_t)i) >> 16) & 0xFFUL;\
buf[2] = (((uint64_t)i) >> 8) & 0xFFUL;\
buf[3] = (((uint64_t)i) >> 0) & 0xFFUL;\
}
#define UINT32_FROM_BUF(buf)\
(((uint64_t)((buf)[0]) << 24) +\
((uint64_t)((buf)[1]) << 16) +\
((uint64_t)((buf)[2]) << 8) +\
((uint64_t)((buf)[3]) << 0))
#define UINT64_TO_BUF(buf_raw, i)\
{\
unsigned char* buf = (unsigned char*)buf_raw;\
buf[0] = (((uint64_t)i) >> 56) & 0xFFUL;\
buf[1] = (((uint64_t)i) >> 48) & 0xFFUL;\
buf[2] = (((uint64_t)i) >> 40) & 0xFFUL;\
buf[3] = (((uint64_t)i) >> 32) & 0xFFUL;\
buf[4] = (((uint64_t)i) >> 24) & 0xFFUL;\
buf[5] = (((uint64_t)i) >> 16) & 0xFFUL;\
buf[6] = (((uint64_t)i) >> 8) & 0xFFUL;\
buf[7] = (((uint64_t)i) >> 0) & 0xFFUL;\
}
#define UINT64_FROM_BUF(buf)\
(((uint64_t)((buf)[0]) << 56) +\
((uint64_t)((buf)[1]) << 48) +\
((uint64_t)((buf)[2]) << 40) +\
((uint64_t)((buf)[3]) << 32) +\
((uint64_t)((buf)[4]) << 24) +\
((uint64_t)((buf)[5]) << 16) +\
((uint64_t)((buf)[6]) << 8) +\
((uint64_t)((buf)[7]) << 0))
#define INT64_FROM_BUF(buf)\
((((uint64_t)((buf)[0] & 0x7FU) << 56) +\
((uint64_t)((buf)[1]) << 48) +\
((uint64_t)((buf)[2]) << 40) +\
((uint64_t)((buf)[3]) << 32) +\
((uint64_t)((buf)[4]) << 24) +\
((uint64_t)((buf)[5]) << 16) +\
((uint64_t)((buf)[6]) << 8) +\
((uint64_t)((buf)[7]) << 0)) * (buf[0] & 0x80U ? -1 : 1))
#define INT64_TO_BUF(buf_raw, i)\
{\
unsigned char* buf = (unsigned char*)buf_raw;\
buf[0] = (((uint64_t)i) >> 56) & 0x7FUL;\
buf[1] = (((uint64_t)i) >> 48) & 0xFFUL;\
buf[2] = (((uint64_t)i) >> 40) & 0xFFUL;\
buf[3] = (((uint64_t)i) >> 32) & 0xFFUL;\
buf[4] = (((uint64_t)i) >> 24) & 0xFFUL;\
buf[5] = (((uint64_t)i) >> 16) & 0xFFUL;\
buf[6] = (((uint64_t)i) >> 8) & 0xFFUL;\
buf[7] = (((uint64_t)i) >> 0) & 0xFFUL;\
if (i < 0) buf[0] |= 0x80U;\
}
#define ttPAYMENT 0
#define ttESCROW_CREATE 1
#define ttESCROW_FINISH 2
#define ttACCOUNT_SET 3
#define ttESCROW_CANCEL 4
#define ttREGULAR_KEY_SET 5
#define ttOFFER_CREATE 7
#define ttOFFER_CANCEL 8
#define ttTICKET_CREATE 10
#define ttSIGNER_LIST_SET 12
#define ttPAYCHAN_CREATE 13
#define ttPAYCHAN_FUND 14
#define ttPAYCHAN_CLAIM 15
#define ttCHECK_CREATE 16
#define ttCHECK_CASH 17
#define ttCHECK_CANCEL 18
#define ttDEPOSIT_PREAUTH 19
#define ttTRUST_SET 20
#define ttACCOUNT_DELETE 21
#define ttHOOK_SET 22
#define ttNFTOKEN_MINT 25
#define ttNFTOKEN_BURN 26
#define ttNFTOKEN_CREATE_OFFER 27
#define ttNFTOKEN_CANCEL_OFFER 28
#define ttNFTOKEN_ACCEPT_OFFER 29
#define ttURITOKEN_MINT 45
#define ttURITOKEN_BURN 46
#define ttURITOKEN_BUY 47
#define ttURITOKEN_CREATE_SELL_OFFER 48
#define ttURITOKEN_CANCEL_SELL_OFFER 49
#define ttCLAIM_REWARD 98
#define ttINVOKE 99
#define ttAMENDMENT 100
#define ttFEE 101
#define ttUNL_MODIFY 102
#define ttEMIT_FAILURE 103
#define tfCANONICAL 0x80000000UL
#define atACCOUNT 1U
#define atOWNER 2U
#define atDESTINATION 3U
#define atISSUER 4U
#define atAUTHORIZE 5U
#define atUNAUTHORIZE 6U
#define atTARGET 7U
#define atREGULARKEY 8U
#define atPSEUDOCALLBACK 9U
#define amAMOUNT 1U
#define amBALANCE 2U
#define amLIMITAMOUNT 3U
#define amTAKERPAYS 4U
#define amTAKERGETS 5U
#define amLOWLIMIT 6U
#define amHIGHLIMIT 7U
#define amFEE 8U
#define amSENDMAX 9U
#define amDELIVERMIN 10U
#define amMINIMUMOFFER 16U
#define amRIPPLEESCROW 17U
#define amDELIVEREDAMOUNT 18U
/**
* RH NOTE -- PAY ATTENTION
*
* ALL 'ENCODE' MACROS INCREMENT BUF_OUT
* THIS IS TO MAKE CHAINING EASY
* BUF_OUT IS A SACRIFICIAL POINTER
*
* 'ENCODE' MACROS WITH CONSTANTS HAVE
* ALIASING TO ASSIST YOU WITH ORDER
* _TYPECODE_FIELDCODE_ENCODE_MACRO
* TO PRODUCE A SERIALIZED OBJECT
* IN CANONICAL FORMAT YOU MUST ORDER
* FIRST BY TYPE CODE THEN BY FIELD CODE
*
* ALL 'PREPARE' MACROS PRESERVE POINTERS
*
**/
#define ENCODE_TL_SIZE 49
#define ENCODE_TL(buf_out, tlamt, amount_type)\
{\
uint8_t uat = amount_type; \
buf_out[0] = 0x60U +(uat & 0x0FU ); \
for (int i = 1; GUARDM(48, 1), i < 49; ++i)\
buf_out[i] = tlamt[i-1];\
buf_out += ENCODE_TL_SIZE;\
}
#define _06_XX_ENCODE_TL(buf_out, drops, amount_type )\
ENCODE_TL(buf_out, drops, amount_type );
#define ENCODE_TL_AMOUNT(buf_out, drops )\
ENCODE_TL(buf_out, drops, amAMOUNT );
#define _06_01_ENCODE_TL_AMOUNT(buf_out, drops )\
ENCODE_TL_AMOUNT(buf_out, drops );
// Encode drops to serialization format
// consumes 9 bytes
#define ENCODE_DROPS_SIZE 9
#define ENCODE_DROPS(buf_out, drops, amount_type ) \
{\
uint8_t uat = amount_type; \
uint64_t udrops = drops; \
buf_out[0] = 0x60U +(uat & 0x0FU ); \
buf_out[1] = 0b01000000 + (( udrops >> 56 ) & 0b00111111 ); \
buf_out[2] = (udrops >> 48) & 0xFFU; \
buf_out[3] = (udrops >> 40) & 0xFFU; \
buf_out[4] = (udrops >> 32) & 0xFFU; \
buf_out[5] = (udrops >> 24) & 0xFFU; \
buf_out[6] = (udrops >> 16) & 0xFFU; \
buf_out[7] = (udrops >> 8) & 0xFFU; \
buf_out[8] = (udrops >> 0) & 0xFFU; \
buf_out += ENCODE_DROPS_SIZE; \
}
#define _06_XX_ENCODE_DROPS(buf_out, drops, amount_type )\
ENCODE_DROPS(buf_out, drops, amount_type );
#define ENCODE_DROPS_AMOUNT(buf_out, drops )\
ENCODE_DROPS(buf_out, drops, amAMOUNT );
#define _06_01_ENCODE_DROPS_AMOUNT(buf_out, drops )\
ENCODE_DROPS_AMOUNT(buf_out, drops );
#define ENCODE_DROPS_FEE(buf_out, drops )\
ENCODE_DROPS(buf_out, drops, amFEE );
#define _06_08_ENCODE_DROPS_FEE(buf_out, drops )\
ENCODE_DROPS_FEE(buf_out, drops );
#define ENCODE_TT_SIZE 3
#define ENCODE_TT(buf_out, tt )\
{\
uint8_t utt = tt;\
buf_out[0] = 0x12U;\
buf_out[1] =(utt >> 8 ) & 0xFFU;\
buf_out[2] =(utt >> 0 ) & 0xFFU;\
buf_out += ENCODE_TT_SIZE; \
}
#define _01_02_ENCODE_TT(buf_out, tt)\
ENCODE_TT(buf_out, tt);
#define ENCODE_ACCOUNT_SIZE 22
#define ENCODE_ACCOUNT(buf_out, account_id, account_type)\
{\
uint8_t uat = account_type;\
buf_out[0] = 0x80U + uat;\
buf_out[1] = 0x14U;\
*(uint64_t*)(buf_out + 2) = *(uint64_t*)(account_id + 0);\
*(uint64_t*)(buf_out + 10) = *(uint64_t*)(account_id + 8);\
*(uint32_t*)(buf_out + 18) = *(uint32_t*)(account_id + 16);\
buf_out += ENCODE_ACCOUNT_SIZE;\
}
#define _08_XX_ENCODE_ACCOUNT(buf_out, account_id, account_type)\
ENCODE_ACCOUNT(buf_out, account_id, account_type);
#define ENCODE_ACCOUNT_SRC_SIZE 22
#define ENCODE_ACCOUNT_SRC(buf_out, account_id)\
ENCODE_ACCOUNT(buf_out, account_id, atACCOUNT);
#define _08_01_ENCODE_ACCOUNT_SRC(buf_out, account_id)\
ENCODE_ACCOUNT_SRC(buf_out, account_id);
#define ENCODE_ACCOUNT_DST_SIZE 22
#define ENCODE_ACCOUNT_DST(buf_out, account_id)\
ENCODE_ACCOUNT(buf_out, account_id, atDESTINATION);
#define _08_03_ENCODE_ACCOUNT_DST(buf_out, account_id)\
ENCODE_ACCOUNT_DST(buf_out, account_id);
#define ENCODE_ACCOUNT_OWNER_SIZE 22
#define ENCODE_ACCOUNT_OWNER(buf_out, account_id) \
ENCODE_ACCOUNT(buf_out, account_id, atOWNER);
#define _08_02_ENCODE_ACCOUNT_OWNER(buf_out, account_id) \
ENCODE_ACCOUNT_OWNER(buf_out, account_id);
#define ENCODE_UINT32_COMMON_SIZE 5U
#define ENCODE_UINT32_COMMON(buf_out, i, field)\
{\
uint32_t ui = i; \
uint8_t uf = field; \
buf_out[0] = 0x20U +(uf & 0x0FU); \
buf_out[1] =(ui >> 24 ) & 0xFFU; \
buf_out[2] =(ui >> 16 ) & 0xFFU; \
buf_out[3] =(ui >> 8 ) & 0xFFU; \
buf_out[4] =(ui >> 0 ) & 0xFFU; \
buf_out += ENCODE_UINT32_COMMON_SIZE; \
}
#define _02_XX_ENCODE_UINT32_COMMON(buf_out, i, field)\
ENCODE_UINT32_COMMON(buf_out, i, field)\
#define ENCODE_UINT32_UNCOMMON_SIZE 6U
#define ENCODE_UINT32_UNCOMMON(buf_out, i, field)\
{\
uint32_t ui = i; \
uint8_t uf = field; \
buf_out[0] = 0x20U; \
buf_out[1] = uf; \
buf_out[2] =(ui >> 24 ) & 0xFFU; \
buf_out[3] =(ui >> 16 ) & 0xFFU; \
buf_out[4] =(ui >> 8 ) & 0xFFU; \
buf_out[5] =(ui >> 0 ) & 0xFFU; \
buf_out += ENCODE_UINT32_UNCOMMON_SIZE; \
}
#define _02_XX_ENCODE_UINT32_UNCOMMON(buf_out, i, field)\
ENCODE_UINT32_UNCOMMON(buf_out, i, field)\
#define ENCODE_LLS_SIZE 6U
#define ENCODE_LLS(buf_out, lls )\
ENCODE_UINT32_UNCOMMON(buf_out, lls, 0x1B );
#define _02_27_ENCODE_LLS(buf_out, lls )\
ENCODE_LLS(buf_out, lls );
#define ENCODE_FLS_SIZE 6U
#define ENCODE_FLS(buf_out, fls )\
ENCODE_UINT32_UNCOMMON(buf_out, fls, 0x1A );
#define _02_26_ENCODE_FLS(buf_out, fls )\
ENCODE_FLS(buf_out, fls );
#define ENCODE_TAG_SRC_SIZE 5
#define ENCODE_TAG_SRC(buf_out, tag )\
ENCODE_UINT32_COMMON(buf_out, tag, 0x3U );
#define _02_03_ENCODE_TAG_SRC(buf_out, tag )\
ENCODE_TAG_SRC(buf_out, tag );
#define ENCODE_TAG_DST_SIZE 5
#define ENCODE_TAG_DST(buf_out, tag )\
ENCODE_UINT32_COMMON(buf_out, tag, 0xEU );
#define _02_14_ENCODE_TAG_DST(buf_out, tag )\
ENCODE_TAG_DST(buf_out, tag );
#define ENCODE_SEQUENCE_SIZE 5
#define ENCODE_SEQUENCE(buf_out, sequence )\
ENCODE_UINT32_COMMON(buf_out, sequence, 0x4U );
#define _02_04_ENCODE_SEQUENCE(buf_out, sequence )\
ENCODE_SEQUENCE(buf_out, sequence );
#define ENCODE_FLAGS_SIZE 5
#define ENCODE_FLAGS(buf_out, tag )\
ENCODE_UINT32_COMMON(buf_out, tag, 0x2U );
#define _02_02_ENCODE_FLAGS(buf_out, tag )\
ENCODE_FLAGS(buf_out, tag );
#define ENCODE_SIGNING_PUBKEY_SIZE 35
#define ENCODE_SIGNING_PUBKEY(buf_out, pkey )\
{\
buf_out[0] = 0x73U;\
buf_out[1] = 0x21U;\
*(uint64_t*)(buf_out + 2) = *(uint64_t*)(pkey + 0);\
*(uint64_t*)(buf_out + 10) = *(uint64_t*)(pkey + 8);\
*(uint64_t*)(buf_out + 18) = *(uint64_t*)(pkey + 16);\
*(uint64_t*)(buf_out + 26) = *(uint64_t*)(pkey + 24);\
buf[34] = pkey[32];\
buf_out += ENCODE_SIGNING_PUBKEY_SIZE;\
}
#define _07_03_ENCODE_SIGNING_PUBKEY(buf_out, pkey )\
ENCODE_SIGNING_PUBKEY(buf_out, pkey );
#define ENCODE_SIGNING_PUBKEY_NULL_SIZE 2
#define ENCODE_SIGNING_PUBKEY_NULL(buf_out )\
{\
*buf_out++ = 0x73U;\
*buf_out++ = 0x00U;\
}
#define _07_03_ENCODE_SIGNING_PUBKEY_NULL(buf_out )\
ENCODE_SIGNING_PUBKEY_NULL(buf_out );
#define _0E_0E_ENCODE_HOOKOBJ(buf_out, hhash)\
{\
uint8_t* hook0 = (hhash);\
*buf_out++ = 0xEEU; /* hook obj start */ \
if (hook0 == 0) /* noop */\
{\
/* do nothing */ \
}\
else\
{\
*buf_out++ = 0x22U; /* flags = override */\
*buf_out++ = 0x00U;\
*buf_out++ = 0x00U;\
*buf_out++ = 0x00U;\
*buf_out++ = 0x01U;\
if (hook0 == 0xFFFFFFFFUL) /* delete operation */ \
{\
*buf_out++ = 0x7BU; /* empty createcode */ \
*buf_out++ = 0x00U;\
}\
else\
{\
*buf_out++ = 0x50U; /* HookHash */\
*buf_out++ = 0x1FU;\
uint64_t* d = (uint64_t*)buf_out;\
uint64_t* s = (uint64_t*)hook0;\
*d++ = *s++;\
*d++ = *s++;\
*d++ = *s++;\
*d++ = *s++;\
buf_out+=32;\
}\
}\
*buf_out++ = 0xE1U;\
}
#define PREPARE_HOOKSET(buf_out_master, maxlen, h, sizeout)\
{\
uint8_t* buf_out = (buf_out_master); \
uint8_t acc[20]; \
uint32_t cls = (uint32_t)ledger_seq(); \
hook_account(SBUF(acc)); \
_01_02_ENCODE_TT (buf_out, ttHOOK_SET ); \
_02_02_ENCODE_FLAGS (buf_out, tfCANONICAL ); \
_02_04_ENCODE_SEQUENCE (buf_out, 0 ); \
_02_26_ENCODE_FLS (buf_out, cls + 1 ); \
_02_27_ENCODE_LLS (buf_out, cls + 5 ); \
uint8_t* fee_ptr = buf_out; \
_06_08_ENCODE_DROPS_FEE (buf_out, 0 ); \
_07_03_ENCODE_SIGNING_PUBKEY_NULL (buf_out ); \
_08_01_ENCODE_ACCOUNT_SRC (buf_out, acc ); \
uint32_t remaining_size = (maxlen) - (buf_out - (buf_out_master)); \
int64_t edlen = etxn_details((uint32_t)buf_out, remaining_size); \
buf_out += edlen; \
*buf_out++ = 0xFBU; /* hook array start */ \
_0E_0E_ENCODE_HOOKOBJ (buf_out, h[0]); \
_0E_0E_ENCODE_HOOKOBJ (buf_out, h[1]); \
_0E_0E_ENCODE_HOOKOBJ (buf_out, h[2]); \
_0E_0E_ENCODE_HOOKOBJ (buf_out, h[3]); \
_0E_0E_ENCODE_HOOKOBJ (buf_out, h[4]); \
_0E_0E_ENCODE_HOOKOBJ (buf_out, h[5]); \
_0E_0E_ENCODE_HOOKOBJ (buf_out, h[6]); \
_0E_0E_ENCODE_HOOKOBJ (buf_out, h[7]); \
_0E_0E_ENCODE_HOOKOBJ (buf_out, h[8]); \
_0E_0E_ENCODE_HOOKOBJ (buf_out, h[9]); \
*buf_out++ = 0xF1U; /* hook array end */ \
sizeout = (buf_out - (buf_out_master)); \
int64_t fee = etxn_fee_base(buf_out_master, sizeout); \
_06_08_ENCODE_DROPS_FEE (fee_ptr, fee ); \
}
#ifdef HAS_CALLBACK
#define PREPARE_PAYMENT_SIMPLE_SIZE 270U
#else
#define PREPARE_PAYMENT_SIMPLE_SIZE 248U
#endif
#define PREPARE_PAYMENT_SIMPLE(buf_out_master, drops_amount_raw, to_address, dest_tag_raw, src_tag_raw)\
{\
uint8_t* buf_out = buf_out_master;\
uint8_t acc[20];\
uint64_t drops_amount = (drops_amount_raw);\
uint32_t dest_tag = (dest_tag_raw);\
uint32_t src_tag = (src_tag_raw);\
uint32_t cls = (uint32_t)ledger_seq();\
hook_account(SBUF(acc));\
_01_02_ENCODE_TT (buf_out, ttPAYMENT ); /* uint16 | size 3 */ \
_02_02_ENCODE_FLAGS (buf_out, tfCANONICAL ); /* uint32 | size 5 */ \
_02_03_ENCODE_TAG_SRC (buf_out, src_tag ); /* uint32 | size 5 */ \
_02_04_ENCODE_SEQUENCE (buf_out, 0 ); /* uint32 | size 5 */ \
_02_14_ENCODE_TAG_DST (buf_out, dest_tag ); /* uint32 | size 5 */ \
_02_26_ENCODE_FLS (buf_out, cls + 1 ); /* uint32 | size 6 */ \
_02_27_ENCODE_LLS (buf_out, cls + 5 ); /* uint32 | size 6 */ \
_06_01_ENCODE_DROPS_AMOUNT (buf_out, drops_amount ); /* amount | size 9 */ \
uint8_t* fee_ptr = buf_out;\
_06_08_ENCODE_DROPS_FEE (buf_out, 0 ); /* amount | size 9 */ \
_07_03_ENCODE_SIGNING_PUBKEY_NULL (buf_out ); /* pk | size 35 */ \
_08_01_ENCODE_ACCOUNT_SRC (buf_out, acc ); /* account | size 22 */ \
_08_03_ENCODE_ACCOUNT_DST (buf_out, to_address ); /* account | size 22 */ \
int64_t edlen = etxn_details((uint32_t)buf_out, PREPARE_PAYMENT_SIMPLE_SIZE); /* emitdet | size 1?? */ \
int64_t fee = etxn_fee_base(buf_out_master, PREPARE_PAYMENT_SIMPLE_SIZE); \
_06_08_ENCODE_DROPS_FEE (fee_ptr, fee ); \
}
#ifdef HAS_CALLBACK
#define PREPARE_PAYMENT_SIMPLE_TRUSTLINE_SIZE 309
#else
#define PREPARE_PAYMENT_SIMPLE_TRUSTLINE_SIZE 287
#endif
#define PREPARE_PAYMENT_SIMPLE_TRUSTLINE(buf_out_master, tlamt, to_address, dest_tag_raw, src_tag_raw)\
{\
uint8_t* buf_out = buf_out_master;\
uint8_t acc[20];\
uint32_t dest_tag = (dest_tag_raw);\
uint32_t src_tag = (src_tag_raw);\
uint32_t cls = (uint32_t)ledger_seq();\
hook_account(SBUF(acc));\
_01_02_ENCODE_TT (buf_out, ttPAYMENT ); /* uint16 | size 3 */ \
_02_02_ENCODE_FLAGS (buf_out, tfCANONICAL ); /* uint32 | size 5 */ \
_02_03_ENCODE_TAG_SRC (buf_out, src_tag ); /* uint32 | size 5 */ \
_02_04_ENCODE_SEQUENCE (buf_out, 0 ); /* uint32 | size 5 */ \
_02_14_ENCODE_TAG_DST (buf_out, dest_tag ); /* uint32 | size 5 */ \
_02_26_ENCODE_FLS (buf_out, cls + 1 ); /* uint32 | size 6 */ \
_02_27_ENCODE_LLS (buf_out, cls + 5 ); /* uint32 | size 6 */ \
_06_01_ENCODE_TL_AMOUNT (buf_out, tlamt ); /* amount | size 48 */ \
uint8_t* fee_ptr = buf_out;\
_06_08_ENCODE_DROPS_FEE (buf_out, 0 ); /* amount | size 9 */ \
_07_03_ENCODE_SIGNING_PUBKEY_NULL (buf_out ); /* pk | size 35 */ \
_08_01_ENCODE_ACCOUNT_SRC (buf_out, acc ); /* account | size 22 */ \
_08_03_ENCODE_ACCOUNT_DST (buf_out, to_address ); /* account | size 22 */ \
etxn_details((uint32_t)buf_out, PREPARE_PAYMENT_SIMPLE_TRUSTLINE_SIZE); /* emitdet | size 1?? */ \
int64_t fee = etxn_fee_base(buf_out_master, PREPARE_PAYMENT_SIMPLE_TRUSTLINE_SIZE); \
_06_08_ENCODE_DROPS_FEE (fee_ptr, fee ); \
}
#endif
-215
View File
@@ -1,215 +0,0 @@
// For documentation please see: https://xrpl-hooks.readme.io/reference/
// Generated using generate_sfcodes.sh
#define sfCloseResolution ((16U << 16U) + 1U)
#define sfMethod ((16U << 16U) + 2U)
#define sfTransactionResult ((16U << 16U) + 3U)
#define sfTickSize ((16U << 16U) + 16U)
#define sfUNLModifyDisabling ((16U << 16U) + 17U)
#define sfHookResult ((16U << 16U) + 18U)
#define sfLedgerEntryType ((1U << 16U) + 1U)
#define sfTransactionType ((1U << 16U) + 2U)
#define sfSignerWeight ((1U << 16U) + 3U)
#define sfTransferFee ((1U << 16U) + 4U)
#define sfVersion ((1U << 16U) + 16U)
#define sfHookStateChangeCount ((1U << 16U) + 17U)
#define sfHookEmitCount ((1U << 16U) + 18U)
#define sfHookExecutionIndex ((1U << 16U) + 19U)
#define sfHookApiVersion ((1U << 16U) + 20U)
#define sfNetworkID ((2U << 16U) + 1U)
#define sfFlags ((2U << 16U) + 2U)
#define sfSourceTag ((2U << 16U) + 3U)
#define sfSequence ((2U << 16U) + 4U)
#define sfPreviousTxnLgrSeq ((2U << 16U) + 5U)
#define sfLedgerSequence ((2U << 16U) + 6U)
#define sfCloseTime ((2U << 16U) + 7U)
#define sfParentCloseTime ((2U << 16U) + 8U)
#define sfSigningTime ((2U << 16U) + 9U)
#define sfExpiration ((2U << 16U) + 10U)
#define sfTransferRate ((2U << 16U) + 11U)
#define sfWalletSize ((2U << 16U) + 12U)
#define sfOwnerCount ((2U << 16U) + 13U)
#define sfDestinationTag ((2U << 16U) + 14U)
#define sfHighQualityIn ((2U << 16U) + 16U)
#define sfHighQualityOut ((2U << 16U) + 17U)
#define sfLowQualityIn ((2U << 16U) + 18U)
#define sfLowQualityOut ((2U << 16U) + 19U)
#define sfQualityIn ((2U << 16U) + 20U)
#define sfQualityOut ((2U << 16U) + 21U)
#define sfStampEscrow ((2U << 16U) + 22U)
#define sfBondAmount ((2U << 16U) + 23U)
#define sfLoadFee ((2U << 16U) + 24U)
#define sfOfferSequence ((2U << 16U) + 25U)
#define sfFirstLedgerSequence ((2U << 16U) + 26U)
#define sfLastLedgerSequence ((2U << 16U) + 27U)
#define sfTransactionIndex ((2U << 16U) + 28U)
#define sfOperationLimit ((2U << 16U) + 29U)
#define sfReferenceFeeUnits ((2U << 16U) + 30U)
#define sfReserveBase ((2U << 16U) + 31U)
#define sfReserveIncrement ((2U << 16U) + 32U)
#define sfSetFlag ((2U << 16U) + 33U)
#define sfClearFlag ((2U << 16U) + 34U)
#define sfSignerQuorum ((2U << 16U) + 35U)
#define sfCancelAfter ((2U << 16U) + 36U)
#define sfFinishAfter ((2U << 16U) + 37U)
#define sfSignerListID ((2U << 16U) + 38U)
#define sfSettleDelay ((2U << 16U) + 39U)
#define sfTicketCount ((2U << 16U) + 40U)
#define sfTicketSequence ((2U << 16U) + 41U)
#define sfNFTokenTaxon ((2U << 16U) + 42U)
#define sfMintedNFTokens ((2U << 16U) + 43U)
#define sfBurnedNFTokens ((2U << 16U) + 44U)
#define sfHookStateCount ((2U << 16U) + 45U)
#define sfEmitGeneration ((2U << 16U) + 46U)
#define sfLockCount ((2U << 16U) + 47U)
#define sfRewardTime ((2U << 16U) + 98U)
#define sfRewardLgrFirst ((2U << 16U) + 99U)
#define sfRewardLgrLast ((2U << 16U) + 100U)
#define sfIndexNext ((3U << 16U) + 1U)
#define sfIndexPrevious ((3U << 16U) + 2U)
#define sfBookNode ((3U << 16U) + 3U)
#define sfOwnerNode ((3U << 16U) + 4U)
#define sfBaseFee ((3U << 16U) + 5U)
#define sfExchangeRate ((3U << 16U) + 6U)
#define sfLowNode ((3U << 16U) + 7U)
#define sfHighNode ((3U << 16U) + 8U)
#define sfDestinationNode ((3U << 16U) + 9U)
#define sfCookie ((3U << 16U) + 10U)
#define sfServerVersion ((3U << 16U) + 11U)
#define sfNFTokenOfferNode ((3U << 16U) + 12U)
#define sfEmitBurden ((3U << 16U) + 13U)
#define sfHookInstructionCount ((3U << 16U) + 17U)
#define sfHookReturnCode ((3U << 16U) + 18U)
#define sfReferenceCount ((3U << 16U) + 19U)
#define sfRewardAccumulator ((3U << 16U) + 100U)
#define sfEmailHash ((4U << 16U) + 1U)
#define sfTakerPaysCurrency ((10U << 16U) + 1U)
#define sfTakerPaysIssuer ((10U << 16U) + 2U)
#define sfTakerGetsCurrency ((10U << 16U) + 3U)
#define sfTakerGetsIssuer ((10U << 16U) + 4U)
#define sfLedgerHash ((5U << 16U) + 1U)
#define sfParentHash ((5U << 16U) + 2U)
#define sfTransactionHash ((5U << 16U) + 3U)
#define sfAccountHash ((5U << 16U) + 4U)
#define sfPreviousTxnID ((5U << 16U) + 5U)
#define sfLedgerIndex ((5U << 16U) + 6U)
#define sfWalletLocator ((5U << 16U) + 7U)
#define sfRootIndex ((5U << 16U) + 8U)
#define sfAccountTxnID ((5U << 16U) + 9U)
#define sfNFTokenID ((5U << 16U) + 10U)
#define sfEmitParentTxnID ((5U << 16U) + 11U)
#define sfEmitNonce ((5U << 16U) + 12U)
#define sfEmitHookHash ((5U << 16U) + 13U)
#define sfBookDirectory ((5U << 16U) + 16U)
#define sfInvoiceID ((5U << 16U) + 17U)
#define sfNickname ((5U << 16U) + 18U)
#define sfAmendment ((5U << 16U) + 19U)
#define sfHookOn ((5U << 16U) + 20U)
#define sfDigest ((5U << 16U) + 21U)
#define sfChannel ((5U << 16U) + 22U)
#define sfConsensusHash ((5U << 16U) + 23U)
#define sfCheckID ((5U << 16U) + 24U)
#define sfValidatedHash ((5U << 16U) + 25U)
#define sfPreviousPageMin ((5U << 16U) + 26U)
#define sfNextPageMin ((5U << 16U) + 27U)
#define sfNFTokenBuyOffer ((5U << 16U) + 28U)
#define sfNFTokenSellOffer ((5U << 16U) + 29U)
#define sfHookStateKey ((5U << 16U) + 30U)
#define sfHookHash ((5U << 16U) + 31U)
#define sfHookNamespace ((5U << 16U) + 32U)
#define sfHookSetTxnID ((5U << 16U) + 33U)
#define sfOfferID ((5U << 16U) + 34U)
#define sfEscrowID ((5U << 16U) + 35U)
#define sfURITokenID ((5U << 16U) + 36U)
#define sfAmount ((6U << 16U) + 1U)
#define sfBalance ((6U << 16U) + 2U)
#define sfLimitAmount ((6U << 16U) + 3U)
#define sfTakerPays ((6U << 16U) + 4U)
#define sfTakerGets ((6U << 16U) + 5U)
#define sfLowLimit ((6U << 16U) + 6U)
#define sfHighLimit ((6U << 16U) + 7U)
#define sfFee ((6U << 16U) + 8U)
#define sfSendMax ((6U << 16U) + 9U)
#define sfDeliverMin ((6U << 16U) + 10U)
#define sfMinimumOffer ((6U << 16U) + 16U)
#define sfRippleEscrow ((6U << 16U) + 17U)
#define sfDeliveredAmount ((6U << 16U) + 18U)
#define sfNFTokenBrokerFee ((6U << 16U) + 19U)
#define sfHookCallbackFee ((6U << 16U) + 20U)
#define sfLockedBalance ((6U << 16U) + 21U)
#define sfPublicKey ((7U << 16U) + 1U)
#define sfMessageKey ((7U << 16U) + 2U)
#define sfSigningPubKey ((7U << 16U) + 3U)
#define sfTxnSignature ((7U << 16U) + 4U)
#define sfURI ((7U << 16U) + 5U)
#define sfSignature ((7U << 16U) + 6U)
#define sfDomain ((7U << 16U) + 7U)
#define sfFundCode ((7U << 16U) + 8U)
#define sfRemoveCode ((7U << 16U) + 9U)
#define sfExpireCode ((7U << 16U) + 10U)
#define sfCreateCode ((7U << 16U) + 11U)
#define sfMemoType ((7U << 16U) + 12U)
#define sfMemoData ((7U << 16U) + 13U)
#define sfMemoFormat ((7U << 16U) + 14U)
#define sfFulfillment ((7U << 16U) + 16U)
#define sfCondition ((7U << 16U) + 17U)
#define sfMasterSignature ((7U << 16U) + 18U)
#define sfUNLModifyValidator ((7U << 16U) + 19U)
#define sfValidatorToDisable ((7U << 16U) + 20U)
#define sfValidatorToReEnable ((7U << 16U) + 21U)
#define sfHookStateData ((7U << 16U) + 22U)
#define sfHookReturnString ((7U << 16U) + 23U)
#define sfHookParameterName ((7U << 16U) + 24U)
#define sfHookParameterValue ((7U << 16U) + 25U)
#define sfBlob ((7U << 16U) + 26U)
#define sfAccount ((8U << 16U) + 1U)
#define sfOwner ((8U << 16U) + 2U)
#define sfDestination ((8U << 16U) + 3U)
#define sfIssuer ((8U << 16U) + 4U)
#define sfAuthorize ((8U << 16U) + 5U)
#define sfUnauthorize ((8U << 16U) + 6U)
#define sfRegularKey ((8U << 16U) + 8U)
#define sfNFTokenMinter ((8U << 16U) + 9U)
#define sfEmitCallback ((8U << 16U) + 10U)
#define sfHookAccount ((8U << 16U) + 16U)
#define sfIndexes ((19U << 16U) + 1U)
#define sfHashes ((19U << 16U) + 2U)
#define sfAmendments ((19U << 16U) + 3U)
#define sfNFTokenOffers ((19U << 16U) + 4U)
#define sfHookNamespaces ((19U << 16U) + 5U)
#define sfPaths ((18U << 16U) + 1U)
#define sfTransactionMetaData ((14U << 16U) + 2U)
#define sfCreatedNode ((14U << 16U) + 3U)
#define sfDeletedNode ((14U << 16U) + 4U)
#define sfModifiedNode ((14U << 16U) + 5U)
#define sfPreviousFields ((14U << 16U) + 6U)
#define sfFinalFields ((14U << 16U) + 7U)
#define sfNewFields ((14U << 16U) + 8U)
#define sfTemplateEntry ((14U << 16U) + 9U)
#define sfMemo ((14U << 16U) + 10U)
#define sfSignerEntry ((14U << 16U) + 11U)
#define sfNFToken ((14U << 16U) + 12U)
#define sfEmitDetails ((14U << 16U) + 13U)
#define sfHook ((14U << 16U) + 14U)
#define sfSigner ((14U << 16U) + 16U)
#define sfMajority ((14U << 16U) + 18U)
#define sfDisabledValidator ((14U << 16U) + 19U)
#define sfEmittedTxn ((14U << 16U) + 20U)
#define sfHookExecution ((14U << 16U) + 21U)
#define sfHookDefinition ((14U << 16U) + 22U)
#define sfHookParameter ((14U << 16U) + 23U)
#define sfHookGrant ((14U << 16U) + 24U)
#define sfSigners ((15U << 16U) + 3U)
#define sfSignerEntries ((15U << 16U) + 4U)
#define sfTemplate ((15U << 16U) + 5U)
#define sfNecessary ((15U << 16U) + 6U)
#define sfSufficient ((15U << 16U) + 7U)
#define sfAffectedNodes ((15U << 16U) + 8U)
#define sfMemos ((15U << 16U) + 9U)
#define sfNFTokens ((15U << 16U) + 10U)
#define sfHooks ((15U << 16U) + 11U)
#define sfMajorities ((15U << 16U) + 16U)
#define sfDisabledValidators ((15U << 16U) + 17U)
#define sfHookExecutions ((15U << 16U) + 18U)
#define sfHookParameters ((15U << 16U) + 19U)
#define sfHookGrants ((15U << 16U) + 20U)
#define sfActiveValidators ((15U << 16U) + 95U)
-239
View File
@@ -1,239 +0,0 @@
#include <stdint.h>
// 8 byte-int = 1 bytes
#define SFL_CLOSERESOLUTION 1
#define SFL_METHOD 1
#define SFL_TRANSACTIONRESULT 1
#define SFL_TICKSIZE 1
#define SFL_UNLMODIFYDISABLING 1
#define SFL_HOOKRESULT 1
// 16 byte-int = 2 bytes
#define SFL_LEDGERENTRYTYPE 2
#define SFL_TRANSACTIONTYPE 2
#define SFL_SIGNERWEIGHT 2
#define SFL_TRANSFERFEE 2
#define SFL_VERSION 2
#define SFL_HOOKSTATECHANGECOUNT 2
#define SFL_HOOKEMITCOUNT 2
#define SFL_HOOKEXECUTIONINDEX 2
#define SFL_HOOKAPIVERSION 2
// 32 byte-int = 4 bytes
#define SFL_NETWORKID 4
#define SFL_FLAGS 4
#define SFL_SOURCETAG 4
#define SFL_SEQUENCE 4
#define SFL_PREVIOUSTXNLGRSEQ 4
#define SFL_LEDGERSEQUENCE 4
#define SFL_CLOSETIME 4
#define SFL_PARENTCLOSETIME 4
#define SFL_SIGNINGTIME 4
#define SFL_EXPIRATION 4
#define SFL_TRANSFERRATE 4
#define SFL_WALLETSIZE 4
#define SFL_OWNERCOUNT 4
#define SFL_DESTINATIONTAG 4
#define SFL_HIGHQUALITYIN 4
#define SFL_HIGHQUALITYOUT 4
#define SFL_LOWQUALITYIN 4
#define SFL_LOWQUALITYOUT 4
#define SFL_QUALITYIN 4
#define SFL_QUALITYOUT 4
#define SFL_STAMPESCROW 4
#define SFL_BONDAMOUNT 4
#define SFL_LOADFEE 4
#define SFL_OFFERSEQUENCE 4
#define SFL_FIRSTLEDGERSEQUENCE 4
#define SFL_LASTLEDGERSEQUENCE 4
#define SFL_TRANSACTIONINDEX 4
#define SFL_OPERATIONLIMIT 4
#define SFL_REFERENCEFEEUNITS 4
#define SFL_RESERVEBASE 4
#define SFL_RESERVEINCREMENT 4
#define SFL_SETFLAG 4
#define SFL_CLEARFLAG 4
#define SFL_SIGNERQUORUM 4
#define SFL_CANCELAFTER 4
#define SFL_FINISHAFTER 4
#define SFL_SIGNERLISTID 4
#define SFL_SETTLEDELAY 4
#define SFL_TICKETCOUNT 4
#define SFL_TICKETSEQUENCE 4
#define SFL_NFTOKENTAXON 4
#define SFL_MINTEDNFTOKENS 4
#define SFL_BURNEDNFTOKENS 4
#define SFL_HOOKSTATECOUNT 4
#define SFL_EMITGENERATION 4
#define SFL_LOCKCOUNT 4
#define SFL_REWARDTIME 4
#define SFL_REWARDLGRFIRST 4
#define SFL_REWARDLGRLAST 4
#define SFL_FIRSTNFTOKENSEQUENCE 4
// 64 byte-int = 8 bytes
#define SFL_INDEX_NEXT 8
#define SFL_INDEX_PREVIOUS 8
#define SFL_BOOK_NODE 8
#define SFL_OWNER_NODE 8
#define SFL_BASE_FEE 8
#define SFL_EXCHANGE_RATE 8
#define SFL_LOW_NODE 8
#define SFL_HIGH_NODE 8
#define SFL_DESTINATION_NODE 8
#define SFL_COOKIE 8
#define SFL_SERVER_VERSION 8
#define SFL_EMIT_BURDEN 8
#define SFL_NFTOKEN_OFFER_NODE 8
#define SFL_HOOK_INSTRUCTION_COUNT 8
#define SFL_HOOK_RETURN_CODE 8
#define SFL_REFERENCE_COUNT 8
#define SFL_REWARD_ACCUMULATOR 8
// 128 byte-int = 4 bytes
#define SFL_EMAIL_HASH 128
// 160 byte-int = 4 bytes
#define SFL_TAKER_PAYS_CURRENCY 160
#define SFL_TAKER_PAYS_ISSUER 160
#define SFL_TAKER_GETS_CURRENCY 160
#define SFL_TAKER_GETS_ISSUER 160
// 256 byte-int = ??? bytes
#define SFL_LEDGER_HASH 256
#define SFL_PARENT_HASH 256
#define SFL_TRANSACTION_HASH 256
#define SFL_ACCOUNT_HASH 256
#define SFL_HOOK_ON 256
#define SFL_PREVIOUS_TXN_ID 256
#define SFL_LEDGER_INDEX 256
#define SFL_WALLET_LOCATOR 256
#define SFL_ROOT_INDEX 256
#define SFL_ACCOUNT_TXN_ID 256
#define SFL_NFTOKEN_ID 256
#define SFL_EMIT_PARENT_TXN_ID 256
#define SFL_EMIT_NONCE 256
#define SFL_EMIT_HOOK_HASH 256
// 256 byte-int = ??? bytes
#define SFL_BOOK_DIRECTORY 256
#define SFL_INVOICE_ID 256
#define SFL_NICKNAME 256
#define SFL_AMENDMENT 256
#define SFL_DIGEST 256
#define SFL_CHANNEL 256
#define SFL_CONSENSUS_HASH 256
#define SFL_CHECK_ID 256
#define SFL_VALIDATED_HASH 256
#define SFL_PREVIOUS_PAGE_MIN 256
#define SFL_NEXT_PAGE_MIN 256
#define SFL_NFTOKEN_BUY_OFFER 256
#define SFL_NFTOKEN_SELL_OFFER 256
#define SFL_HOOK_STATE_KEY 256
#define SFL_HOOK_HASH 256
#define SFL_HOOK_NAMESPACE 256
#define SFL_HOOK_SET_TXN_ID 256
#define SFL_OFFER_ID 256
#define SFL_ESCROW_ID 256
#define SFL_URITOKEN_ID 256
// 20 bytes
#define SFL_AMOUNT 20
#define SFL_BALANCE 20
#define SFL_LIMIT_AMOUNT 20
#define SFL_TAKER_PAYS 20
#define SFL_TAKER_GETS 20
#define SFL_LOW_LIMIT 20
#define SFL_HIGH_LIMIT 20
#define SFL_FEE 20
#define SFL_SEND_MAX 20
#define SFL_DELIVER_MIN 20
#define SFL_LOCKED_BALANCE 20
// Unimplemented
#define SFL_AMOUNT_MINIMUM_OFFER 8
#define SFL_AMOUNT_RIPPLE_ESCROW 8
#define SFL_AMOUNT_DELIVERED_AMOUNT 8
#define SFL_AMOUNT_NFTOKEN_BROKER_FEE 8
#define SFL_AMOUNT_HOOK_CALLBACK_FEE 8
#define SFL_AMOUNT_BASE_FEE_DROPS 8
#define SFL_AMOUNT_RESERVE_BASE_DROPS 8
#define SFL_AMOUNT_RESERVE_INCREMENT_DROPS 8
// Unimplemented
#define SFL_VL_PUBLIC_KEY 64
#define SFL_VL_MESSAGE_KEY 64
#define SFL_VL_SIGNING_PUB_KEY 64
// Unimplemented
#define SFL_VL_TXN_SIGNATURE 96
// Unimplemented
#define SFL_VL_URI 256
// Unimplemented
#define SFL_VL_SIGNATURE 96
// Unimplemented
#define SFL_VL_DOMAIN 256
#define SFL_VL_FUND_CODE 256
#define SFL_VL_REMOVE_CODE 256
#define SFL_VL_EXPIRE_CODE 256
#define SFL_VL_CREATE_CODE 256
#define SFL_VL_MEMO_TYPE 256
#define SFL_VL_MEMO_DATA 256
#define SFL_VL_MEMO_FORMAT 256
#define SFL_VL_FULFILLMENT 256
#define SFL_VL_CONDITION 256
// Unimplemented
#define SFL_VL_MASTER_SIGNATURE 96
// Unimplemented
#define SFL_VL_UNL_MODIFY_VALIDATOR 256
#define SFL_VL_VALIDATOR_TO_DISABLE 256
#define SFL_VL_VALIDATOR_TO_RE_ENABLE 256
#define SFL_VL_HOOK_STATE_DATA 256
#define SFL_VL_HOOK_RETURN_STRING 256
#define SFL_VL_HOOK_PARAMETER_NAME 256
#define SFL_VL_HOOK_PARAMETER_VALUE 256
#define SFL_VL_BLOB 256
// 20 bytes
#define SFL_ACCOUNT 20
#define SFL_OWNER 20
#define SFL_DESTINATION 20
#define SFL_ISSUER 20
#define SFL_AUTHORIZE 20
#define SFL_UNAUTHORIZE 20
#define SFL_REGULAR_KEY 20
#define SFL_NFTOKEN_MINTER 20
#define SFL_EMIT_CALLBACK 20
#define SFL_HOOK_ACCOUNT 20
#define SFL_NFTOKEN_MINTER 20
// Unimplemented
#define SFL_PATHS 1
// Unimplemented
#define SFL_VECTOR256_INDEXES 32
#define SFL_VECTOR256_HASHES 32
#define SFL_VECTOR256_AMENDMENTS 32
#define SFL_VECTOR256_NFTOKEN_OFFERS 32
#define SFL_VECTOR256_HOOK_NAMESPACES 32
// Unimplemented
#define SFL_TRANSACTION_META_DATA 1
#define SFL_CREATED_NODE 1
#define SFL_DELETED_NODE 1
#define SFL_MODIFIED_NODE 1
#define SFL_PREVIOUS_FIELDS 1
#define SFL_FINAL_FIELDS 1
#define SFL_NEW_FIELDS 1
#define SFL_TEMPLATE_ENTRY 1
#define SFL_MEMO 1
#define SFL_SIGNER_ENTRY 1
#define SFL_NFTOKEN 1
#define SFL_EMIT_DETAILS 1
#define SFL_HOOK 1
#define SFL_SIGNER 1
#define SFL_MAJORITY 1
#define SFL_DISABLED_VALIDATOR 1
#define SFL_EMITTED_TXN 1
#define SFL_HOOK_EXECUTION 1
#define SFL_HOOK_DEFINITION 1
#define SFL_HOOK_PARAMETER 1
#define SFL_HOOK_GRANT 1
#define SFL_SIGNERS 1
#define SFL_SIGNER_ENTRIES 1
#define SFL_TEMPLATE 1
#define SFL_NECESSARY 1
#define SFL_SUFFICIENT 1
#define SFL_AFFECTED_NODES 1
#define SFL_MEMOS 1
#define SFL_NFTOKENS 1
#define SFL_HOOKS 1
#define SFL_MAJORITIES 1
#define SFL_DISABLED_VALIDATORS 1
#define SFL_HOOK_EXECUTIONS 1
#define SFL_HOOK_EXECUTION 1
+5 -5
View File
@@ -1,9 +1,9 @@
all: reward govern mint
accept:
wasmcc accept.c -o accept.wasm -Oz -Wl,--allow-undefined -I./headers
wasmcc accept.c -o accept.wasm -Oz -Wl,--allow-undefined -I../
hook-cleaner accept.wasm
reward:
wasmcc reward.c -o reward.wasm -Oz -Wl,--allow-undefined -I./headers
wasmcc reward.c -o reward.wasm -Oz -Wl,--allow-undefined -I../
wasm-opt reward.wasm -o reward.wasm \
--shrink-level=100000000 \
--coalesce-locals-learning \
@@ -58,7 +58,7 @@ reward:
hook-cleaner reward.wasm
guard_checker reward.wasm
govern:
wasmcc govern.c -o govern.wasm -Oz -Wl,--allow-undefined -I./headers
wasmcc govern.c -o govern.wasm -Oz -Wl,--allow-undefined -I../
wasm-opt govern.wasm -o govern.wasm \
--shrink-level=100000000 \
--coalesce-locals-learning \
@@ -113,7 +113,7 @@ govern:
hook-cleaner govern.wasm
guard_checker govern.wasm
mint:
wasmcc mint.c -o mint.wasm -Oz -Wl,--allow-undefined -I./headers
wasmcc mint.c -o mint.wasm -Oz -Wl,--allow-undefined -I../
wasm-opt mint.wasm -o mint.wasm \
--shrink-level=100000000 \
--coalesce-locals-learning \
@@ -142,5 +142,5 @@ mint:
hook-cleaner mint.wasm
guard_checker mint.wasm
nftoken:
wasmcc nftoken.c -o nftoken.wasm -Oz -Wl,--allow-undefined -I./headers
wasmcc nftoken.c -o nftoken.wasm -Oz -Wl,--allow-undefined -I../
hook-cleaner nftoken.wasm
+1 -5
View File
@@ -38,7 +38,6 @@
#define KEYLET_HOOK_DEFINITION 24
#define KEYLET_HOOK_STATE_DIR 25
#define KEYLET_CRON 26
#define KEYLET_MANIFEST 37
#define COMPARE_EQUAL 1U
#define COMPARE_LESS 2U
@@ -46,11 +45,8 @@
#include "error.h"
#include "extern.h"
#include "macro.h"
#include "sfcodes.h"
#include "macro.h"
#include "tts.h"
#include "ls_flags.h"
#include "tx_flags.h"
#endif
-75
View File
@@ -1,75 +0,0 @@
// Generated using generate_lsflags.sh
#ifndef HOOKLSFLAGS_INCLUDED
#define HOOKLSFLAGS_INCLUDED 1
enum ltACCOUNT_ROOT {
lsfPasswordSpent = 0x00010000,
lsfRequireDestTag = 0x00020000,
lsfRequireAuth = 0x00040000,
lsfDisallowXRP = 0x00080000,
lsfDisableMaster = 0x00100000,
lsfNoFreeze = 0x00200000,
lsfGlobalFreeze = 0x00400000,
lsfDefaultRipple = 0x00800000,
lsfDepositAuth = 0x01000000,
lsfTshCollect = 0x02000000,
lsfDisallowIncomingNFTokenOffer = 0x04000000,
lsfDisallowIncomingCheck = 0x08000000,
lsfDisallowIncomingPayChan = 0x10000000,
lsfDisallowIncomingTrustline = 0x20000000,
lsfURITokenIssuer = 0x40000000,
lsfDisallowIncomingRemit = 0x80000000,
lsfAllowTrustLineClawback = 0x00001000,
};
enum ltOFFER {
lsfPassive = 0x00010000,
lsfSell = 0x00020000,
};
enum ltRIPPLE_STATE {
lsfLowReserve = 0x00010000,
lsfHighReserve = 0x00020000,
lsfLowAuth = 0x00040000,
lsfHighAuth = 0x00080000,
lsfLowNoRipple = 0x00100000,
lsfHighNoRipple = 0x00200000,
lsfLowFreeze = 0x00400000,
lsfHighFreeze = 0x00800000,
lsfLowDeepFreeze = 0x02000000,
lsfHighDeepFreeze = 0x04000000,
lsfAMMNode = 0x01000000,
};
enum ltSIGNER_LIST {
lsfOneOwnerCount = 0x00010000,
};
enum ltDIR_NODE {
lsfNFTokenBuyOffers = 0x00000001,
lsfNFTokenSellOffers = 0x00000002,
lsfEmittedDir = 0x00000004,
};
enum ltNFTOKEN_OFFER {
lsfSellNFToken = 0x00000001,
};
enum ltURI_TOKEN {
lsfBurnable = 0x00000001,
};
enum remarks {
lsfImmutable = 1,
};
enum ltMPTOKEN_ISSUANCE {
lsfMPTLocked = 0x00000001,
lsfMPTCanLock = 0x00000002,
lsfMPTRequireAuth = 0x00000004,
lsfMPTCanEscrow = 0x00000008,
lsfMPTCanTrade = 0x00000010,
lsfMPTCanTransfer = 0x00000020,
lsfMPTCanClawback = 0x00000040,
};
enum ltMPTOKEN {
lsfMPTAuthorized = 0x00000002,
};
enum ltCREDENTIAL {
lsfAccepted = 0x00010000,
};
#endif // HOOKLSFLAGS_INCLUDED
+1 -15
View File
@@ -22,8 +22,6 @@
#define sfHookApiVersion ((1U << 16U) + 20U)
#define sfHookStateScale ((1U << 16U) + 21U)
#define sfLedgerFixType ((1U << 16U) + 22U)
#define sfEntropyCount ((1U << 16U) + 99U)
#define sfEntropyDenominator ((1U << 16U) + 100U)
#define sfNetworkID ((2U << 16U) + 1U)
#define sfFlags ((2U << 16U) + 2U)
#define sfSourceTag ((2U << 16U) + 3U)
@@ -82,7 +80,6 @@
#define sfRewardTime ((2U << 16U) + 98U)
#define sfRewardLgrFirst ((2U << 16U) + 99U)
#define sfRewardLgrLast ((2U << 16U) + 100U)
#define sfAppLoaderSequence ((2U << 16U) + 101U)
#define sfIndexNext ((3U << 16U) + 1U)
#define sfIndexPrevious ((3U << 16U) + 2U)
#define sfBookNode ((3U << 16U) + 3U)
@@ -155,9 +152,6 @@
#define sfEscrowID ((5U << 16U) + 35U)
#define sfURITokenID ((5U << 16U) + 36U)
#define sfDomainID ((5U << 16U) + 37U)
#define sfNextRandomDigest ((5U << 16U) + 89U)
#define sfRandomData ((5U << 16U) + 90U)
#define sfManifestID ((5U << 16U) + 91U)
#define sfHookOnOutgoing ((5U << 16U) + 93U)
#define sfHookOnIncoming ((5U << 16U) + 94U)
#define sfCron ((5U << 16U) + 95U)
@@ -195,7 +189,6 @@
#define sfSignatureReward ((6U << 16U) + 29U)
#define sfMinAccountCreateAmount ((6U << 16U) + 30U)
#define sfLPTokenBalance ((6U << 16U) + 31U)
#define sfTrustLineRewardAccumulator ((6U << 16U) + 99U)
#define sfPublicKey ((7U << 16U) + 1U)
#define sfMessageKey ((7U << 16U) + 2U)
#define sfSigningPubKey ((7U << 16U) + 3U)
@@ -227,8 +220,6 @@
#define sfProvider ((7U << 16U) + 30U)
#define sfMPTokenMetadata ((7U << 16U) + 31U)
#define sfCredentialType ((7U << 16U) + 32U)
#define sfAppLoader ((7U << 16U) + 96U)
#define sfHookName ((7U << 16U) + 97U)
#define sfRemarkValue ((7U << 16U) + 98U)
#define sfRemarkName ((7U << 16U) + 99U)
#define sfAccount ((8U << 16U) + 1U)
@@ -264,7 +255,6 @@
#define sfIssuingChainIssue ((24U << 16U) + 2U)
#define sfAsset ((24U << 16U) + 3U)
#define sfAsset2 ((24U << 16U) + 4U)
#define sfClaimCurrency ((24U << 16U) + 5U)
#define sfXChainBridge ((25U << 16U) + 1U)
#define sfTransactionMetaData ((14U << 16U) + 2U)
#define sfCreatedNode ((14U << 16U) + 3U)
@@ -284,6 +274,7 @@
#define sfDisabledValidator ((14U << 16U) + 19U)
#define sfEmittedTxn ((14U << 16U) + 20U)
#define sfHookExecution ((14U << 16U) + 21U)
#define sfHookDefinition ((14U << 16U) + 22U)
#define sfHookParameter ((14U << 16U) + 23U)
#define sfHookGrant ((14U << 16U) + 24U)
#define sfVoteEntry ((14U << 16U) + 25U)
@@ -295,8 +286,6 @@
#define sfXChainCreateAccountAttestationCollectionElement ((14U << 16U) + 31U)
#define sfPriceData ((14U << 16U) + 32U)
#define sfCredential ((14U << 16U) + 33U)
#define sfRandomDigestEntry ((14U << 16U) + 88U)
#define sfManifest ((14U << 16U) + 90U)
#define sfAmountEntry ((14U << 16U) + 91U)
#define sfMintURIToken ((14U << 16U) + 92U)
#define sfHookEmission ((14U << 16U) + 93U)
@@ -304,8 +293,6 @@
#define sfActiveValidator ((14U << 16U) + 95U)
#define sfGenesisMint ((14U << 16U) + 96U)
#define sfRemark ((14U << 16U) + 97U)
#define sfHighReward ((14U << 16U) + 98U)
#define sfLowReward ((14U << 16U) + 99U)
#define sfSigners ((15U << 16U) + 3U)
#define sfSignerEntries ((15U << 16U) + 4U)
#define sfTemplate ((15U << 16U) + 5U)
@@ -328,7 +315,6 @@
#define sfAuthorizeCredentials ((15U << 16U) + 26U)
#define sfUnauthorizeCredentials ((15U << 16U) + 27U)
#define sfAcceptedCredentials ((15U << 16U) + 28U)
#define sfRandomDigests ((15U << 16U) + 91U)
#define sfAmounts ((15U << 16U) + 92U)
#define sfHookEmissions ((15U << 16U) + 93U)
#define sfImportVLKeys ((15U << 16U) + 94U)
-2
View File
@@ -61,8 +61,6 @@
#define ttNFTOKEN_MODIFY 70
#define ttPERMISSIONED_DOMAIN_SET 71
#define ttPERMISSIONED_DOMAIN_DELETE 72
#define ttENTROPY 89
#define ttMANIFEST_SET 91
#define ttCRON 92
#define ttCRON_SET 93
#define ttREMARKS_SET 94
-117
View File
@@ -1,117 +0,0 @@
// Generated using generate_txflags.sh
#include "ls_flags.h"
#include <stdint.h>
enum UniversalFlags : uint32_t {
tfFullyCanonicalSig = 0x80000000,
};
enum AccountSetFlags : uint32_t {
tfRequireDestTag = 0x00010000,
tfOptionalDestTag = 0x00020000,
tfRequireAuth = 0x00040000,
tfOptionalAuth = 0x00080000,
tfDisallowXRP = 0x00100000,
tfAllowXRP = 0x00200000,
};
enum AccountFlags : uint32_t {
asfRequireDest = 1,
asfRequireAuth = 2,
asfDisallowXRP = 3,
asfDisableMaster = 4,
asfAccountTxnID = 5,
asfNoFreeze = 6,
asfGlobalFreeze = 7,
asfDefaultRipple = 8,
asfDepositAuth = 9,
asfAuthorizedNFTokenMinter = 10,
asfTshCollect = 11,
asfDisallowIncomingNFTokenOffer = 12,
asfDisallowIncomingCheck = 13,
asfDisallowIncomingPayChan = 14,
asfDisallowIncomingTrustline = 15,
asfDisallowIncomingRemit = 16,
asfAllowTrustLineClawback = 17,
};
enum OfferCreateFlags : uint32_t {
tfPassive = 0x00010000,
tfImmediateOrCancel = 0x00020000,
tfFillOrKill = 0x00040000,
tfSell = 0x00080000,
};
enum PaymentFlags : uint32_t {
tfNoRippleDirect = 0x00010000,
tfPartialPayment = 0x00020000,
tfLimitQuality = 0x00040000,
};
enum TrustSetFlags : uint32_t {
tfSetfAuth = 0x00010000,
tfSetNoRipple = 0x00020000,
tfClearNoRipple = 0x00040000,
tfSetFreeze = 0x00100000,
tfClearFreeze = 0x00200000,
tfSetDeepFreeze = 0x00400000,
tfClearDeepFreeze = 0x00800000
};
enum EnableAmendmentFlags : uint32_t {
tfGotMajority = 0x00010000,
tfLostMajority = 0x00020000,
tfTestSuite = 0x80000000,
};
enum PaymentChannelClaimFlags : uint32_t {
tfRenew = 0x00010000,
tfClose = 0x00020000,
};
enum NFTokenMintFlags : uint32_t {
tfBurnable = 0x00000001,
tfOnlyXRP = 0x00000002,
tfTrustLine = 0x00000004,
tfTransferable = 0x00000008,
tfMutable = 0x00000010,
tfStrongTSH = 0x00008000,
};
enum MPTokenIssuanceCreateFlags : uint32_t {
tfMPTCanLock = lsfMPTCanLock,
tfMPTRequireAuth = lsfMPTRequireAuth,
tfMPTCanEscrow = lsfMPTCanEscrow,
tfMPTCanTrade = lsfMPTCanTrade,
tfMPTCanTransfer = lsfMPTCanTransfer,
tfMPTCanClawback = lsfMPTCanClawback,
};
enum MPTokenAuthorizeFlags : uint32_t {
tfMPTUnauthorize = 0x00000001,
};
enum MPTokenIssuanceSetFlags : uint32_t {
tfMPTLock = 0x00000001,
tfMPTUnlock = 0x00000002,
};
enum NFTokenCreateOfferFlags : uint32_t {
tfSellNFToken = 0x00000001,
};
enum ClaimRewardFlags : uint32_t {
tfOptOut = 0x00000001,
};
enum CronSetFlags : uint32_t {
tfCronUnset = 0x00000001,
};
enum AMMClawbackFlags : uint32_t {
tfClawTwoAssets = 0x00000001,
};
enum BridgeModifyFlags : uint32_t {
tfClearAccountCreateAmount = 0x00010000,
};
+83 -124
View File
@@ -1,33 +1,75 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 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_COUNTEDOBJECT_H_INCLUDED
#define RIPPLE_BASICS_COUNTEDOBJECT_H_INCLUDED
#include <xrpl/beast/type_name.h>
#include <atomic>
#include <cstddef>
#include <iterator>
#include <string>
#include <utility>
#include <vector>
namespace ripple {
/** Manages all counted object types. */
class CountedObjects
{
public:
static CountedObjects&
getInstance() noexcept;
using Entry = std::pair<std::string, int>;
using List = std::vector<Entry>;
List
getCounts(int minimumThreshold) const;
public:
/** Implementation for @ref CountedObject.
@internal
*/
class Counter
{
public:
Counter(std::string name) noexcept;
Counter(std::string name) noexcept : name_(std::move(name)), count_(0)
{
// Insert ourselves at the front of the lock-free linked list
CountedObjects& instance = CountedObjects::getInstance();
Counter* head;
do
{
head = instance.m_head.load();
next_ = head;
} while (instance.m_head.exchange(this) != head);
++instance.m_count;
}
~Counter() noexcept = default;
int
increment() noexcept
{
auto const newCount = ++count_;
if (auto maxCount = maxCount_.load(); newCount > maxCount)
maxCount_.compare_exchange_strong(maxCount, newCount);
return newCount;
return ++count_;
}
int
@@ -37,161 +79,78 @@ public:
}
int
count() const noexcept
getCount() const noexcept
{
return count_.load();
}
int
max() const noexcept
Counter*
getNext() const noexcept
{
return std::max(count_.load(), maxCount_.load());
return next_;
}
std::string const&
name() const noexcept
getName() const noexcept
{
return name_;
}
private:
friend class CountedObjects;
Counter* next_;
std::atomic<std::uint32_t> count_ = 0;
std::atomic<std::uint32_t> maxCount_ = 0;
std::string const name_;
std::atomic<int> count_;
Counter* next_;
};
class Iterator
{
public:
using value_type = Counter const;
using reference = value_type&;
using pointer = value_type*;
using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag;
explicit Iterator(Counter* c = nullptr) noexcept : current_(c)
{
}
reference
operator*() const noexcept
{
return *current_;
}
pointer
operator->() const noexcept
{
return current_;
}
Iterator&
operator++() noexcept
{
current_ = current_->next_;
return *this;
}
Iterator
operator++(int) noexcept
{
auto tmp = *this;
++*this;
return tmp;
}
bool
operator==(Iterator const&) const noexcept = default;
private:
Counter* current_;
};
using List = std::vector<std::pair<std::string, int>>;
constexpr CountedObjects() noexcept = default;
static CountedObjects&
getInstance() noexcept;
/** Returns the name and count of every counter with at least
`minimumThreshold` live instances. */
List
getCounts(int minimumThreshold) const
{
List ret;
for (auto c = head_.load(); c != nullptr; c = c->next_)
if (c->count() >= minimumThreshold)
ret.emplace_back(c->name(), c->count());
return ret;
}
auto
begin() const noexcept
{
return Iterator{head_.load()};
}
auto
end() const noexcept
{
return Iterator{};
}
private:
friend class Counter;
CountedObjects() noexcept;
~CountedObjects() noexcept = default;
std::atomic<Counter*> head_ = nullptr;
private:
std::atomic<int> m_count;
std::atomic<Counter*> m_head;
};
inline constinit CountedObjects countedObjects;
inline CountedObjects&
CountedObjects::getInstance() noexcept
{
return countedObjects;
}
inline CountedObjects::Counter::Counter(std::string name) noexcept
: name_(std::move(name))
{
do
next_ = countedObjects.head_.load();
while (!countedObjects.head_.compare_exchange_weak(next_, this));
}
//------------------------------------------------------------------------------
/** Tracks the number of instances of an object.
Derived classes have their instances counted automatically. This is used
for reporting purposes.
@ingroup ripple_basics
*/
template <class Object>
class CountedObject
{
static CountedObjects::Counter counter_;
private:
static auto&
getCounter() noexcept
{
static CountedObjects::Counter c{beast::type_name<Object>()};
return c;
}
public:
CountedObject() noexcept
{
counter_.increment();
getCounter().increment();
}
CountedObject(CountedObject const&) noexcept
{
counter_.increment();
getCounter().increment();
}
CountedObject&
operator=(CountedObject const&) noexcept = default;
~CountedObject() noexcept
{
counter_.decrement();
getCounter().decrement();
}
};
// Instantiation of the static CountedObject<T>::counter_
template <class Object>
CountedObjects::Counter CountedObject<Object>::counter_{
beast::type_name<Object>()};
} // namespace ripple
#endif
-57
View File
@@ -23,66 +23,9 @@
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <optional>
namespace ripple {
/** Add two signed 64-bit integers, returning std::nullopt when the exact
* mathematical sum is not representable in std::int64_t.
*/
[[nodiscard]] constexpr std::optional<std::int64_t>
checkedAdd(std::int64_t a, std::int64_t b) noexcept
{
using L = std::numeric_limits<std::int64_t>;
if ((b > 0 && a > L::max() - b) || (b < 0 && a < L::min() - b))
return std::nullopt;
return a + b;
}
/** Subtract two signed 64-bit integers, returning std::nullopt when the exact
* mathematical difference is not representable in std::int64_t.
*/
[[nodiscard]] constexpr std::optional<std::int64_t>
checkedSub(std::int64_t a, std::int64_t b) noexcept
{
using L = std::numeric_limits<std::int64_t>;
if ((b > 0 && a < L::min() + b) || (b < 0 && a > L::max() + b))
return std::nullopt;
return a - b;
}
namespace detail {
using i64_limits = std::numeric_limits<std::int64_t>;
static_assert(checkedAdd(0, 0) == 0);
static_assert(checkedAdd(1, -1) == 0);
static_assert(checkedAdd(-5, 2) == -3);
static_assert(!checkedAdd(i64_limits::max(), 1).has_value());
static_assert(!checkedAdd(i64_limits::min(), -1).has_value());
static_assert(checkedAdd(i64_limits::max() - 1, 1) == i64_limits::max());
static_assert(checkedAdd(i64_limits::min(), i64_limits::max()) == -1);
static_assert(checkedAdd(i64_limits::max(), i64_limits::min()) == -1);
static_assert(!checkedAdd(i64_limits::max(), i64_limits::max()).has_value());
static_assert(!checkedAdd(i64_limits::min(), i64_limits::min()).has_value());
static_assert(checkedSub(0, 0) == 0);
static_assert(checkedSub(1, 1) == 0);
static_assert(checkedSub(-5, 2) == -7);
static_assert(checkedSub(-5, -2) == -3);
static_assert(!checkedSub(i64_limits::min(), 1).has_value());
static_assert(!checkedSub(i64_limits::max(), -1).has_value());
static_assert(checkedSub(i64_limits::min() + 1, 1) == i64_limits::min());
static_assert(checkedSub(-1, i64_limits::max()) == i64_limits::min());
static_assert(!checkedSub(i64_limits::max(), i64_limits::min()).has_value());
static_assert(!checkedSub(i64_limits::min(), i64_limits::max()).has_value());
} // namespace detail
/** Calculate one number divided by another number in percentage.
* The result is rounded up to the next integer, and capped in the range [0,100]
* E.g. calculatePercent(1, 100) = 1 because 1/100 = 0.010000
@@ -1,105 +0,0 @@
#pragma once
#include <shared_mutex>
// On Linux (glibc), std::shared_mutex wraps pthread_rwlock_t initialised
// with PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP. This means a
// pending exclusive lock() blocks new shared (reader) acquisitions,
// causing reader starvation when writers contend frequently.
//
// On macOS / ARM (libc++), std::shared_mutex is already reader-preferring,
// so the same code behaves differently across platforms.
//
// This header provides ReaderPreferringSharedMutex:
// - On Linux it wraps pthread_rwlock_t initialised with
// PTHREAD_RWLOCK_PREFER_READER_NP, matching macOS semantics.
// - On all other platforms it is a type alias for std::shared_mutex.
//
// The interface is identical to std::shared_mutex, so it works with
// std::shared_lock and std::unique_lock.
#if defined(__linux__)
#include <cerrno>
#include <pthread.h>
#include <system_error>
namespace ripple {
class ReaderPreferringSharedMutex
{
pthread_rwlock_t rwlock_;
public:
ReaderPreferringSharedMutex()
{
pthread_rwlockattr_t attr;
pthread_rwlockattr_init(&attr);
pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_READER_NP);
int rc = pthread_rwlock_init(&rwlock_, &attr);
pthread_rwlockattr_destroy(&attr);
if (rc != 0)
throw std::system_error(
rc, std::system_category(), "pthread_rwlock_init");
}
~ReaderPreferringSharedMutex()
{
pthread_rwlock_destroy(&rwlock_);
}
ReaderPreferringSharedMutex(ReaderPreferringSharedMutex const&) = delete;
ReaderPreferringSharedMutex&
operator=(ReaderPreferringSharedMutex const&) = delete;
// Exclusive (writer) locking
void
lock()
{
pthread_rwlock_wrlock(&rwlock_);
}
bool
try_lock()
{
return pthread_rwlock_trywrlock(&rwlock_) == 0;
}
void
unlock()
{
pthread_rwlock_unlock(&rwlock_);
}
// Shared (reader) locking
void
lock_shared()
{
pthread_rwlock_rdlock(&rwlock_);
}
bool
try_lock_shared()
{
return pthread_rwlock_tryrdlock(&rwlock_) == 0;
}
void
unlock_shared()
{
pthread_rwlock_unlock(&rwlock_);
}
};
} // namespace ripple
#else // !__linux__
namespace ripple {
// macOS, Windows, etc. — std::shared_mutex is already reader-preferring.
using ReaderPreferringSharedMutex = std::shared_mutex;
} // namespace ripple
#endif
+2 -3
View File
@@ -22,8 +22,7 @@
#include <xrpl/basics/Resolver.h>
#include <xrpl/beast/utility/Journal.h>
#include <boost/asio/io_context.hpp>
#include <boost/asio/io_service.hpp>
namespace ripple {
@@ -33,7 +32,7 @@ public:
explicit ResolverAsio() = default;
static std::unique_ptr<ResolverAsio>
New(boost::asio::io_context&, beast::Journal);
New(boost::asio::io_service&, beast::Journal);
};
} // namespace ripple
+1 -1
View File
@@ -113,7 +113,7 @@ template <>
inline std::size_t
extract(SHAMapHash const& key)
{
return extract(key.as_uint256());
return *reinterpret_cast<std::size_t const*>(key.as_uint256().data());
}
} // namespace ripple
+300 -523
View File
@@ -21,443 +21,195 @@
#define RIPPLE_BASICS_SLABALLOCATOR_H_INCLUDED
#include <xrpl/basics/ByteUtilities.h>
#include <xrpl/basics/spinlock.h>
#include <xrpl/beast/type_name.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <boost/align.hpp>
#include <boost/predef/os.h>
#include <boost/container/static_vector.hpp>
#include <boost/predef.h>
#include <array>
#include <algorithm>
#include <atomic>
#include <bit>
#include <cstdint>
#include <cstring>
#include <mutex>
#include <vector>
#include <limits>
#include <new>
#ifdef BOOST_OS_LINUX
#if BOOST_OS_LINUX
#include <sys/mman.h>
#endif
namespace ripple {
namespace slab {
namespace detail {
/// Alignment for hugepage support.
inline constexpr std::size_t pageSize = megabytes(std::size_t(2));
/** Allocate a new 2MB-aligned data buffer.
@param size Size of the buffer to allocate in bytes.
@return Pointer to allocated memory, or nullptr on failure.
@note On Linux, advises the kernel to back the allocation with
transparent huge pages if available.
*/
[[nodiscard, gnu::malloc]] inline std::uint8_t*
allocateBuffer(std::size_t size) noexcept
template <typename Type>
class SlabAllocator
{
auto ptr = reinterpret_cast<std::uint8_t*>(
boost::alignment::aligned_alloc(pageSize, size));
static_assert(
sizeof(Type) >= sizeof(std::uint8_t*),
"SlabAllocator: the requested object must be larger than a pointer.");
#if BOOST_OS_LINUX
if (ptr != nullptr) [[likely]]
madvise(ptr, size, MADV_HUGEPAGE);
#endif
static_assert(alignof(Type) == 8 || alignof(Type) == 4);
return ptr;
}
/** Deallocate a buffer previously allocated by allocateBuffer.
@param ptr Pointer to buffer, or nullptr (no-op).
*/
inline void
deallocateBuffer(std::uint8_t* ptr) noexcept
{
boost::alignment::aligned_free(ptr);
}
//------------------------------------------------------------------------------
/** A block of memory metadata for slab allocators.
Each block manages a single slab buffer and its associated free list.
Blocks are linked together to form a list of slabs per allocator.
@note slab_t instances are intentionally never destroyed or reclaimed
once allocated, to support lock-free iteration of lists of slabs
without introducing ABA hazards. The data buffer the class holds
can be released independently.
*/
struct slab_t
{
/** A node in the intrusive free list.
Constructed in-place within free memory blocks. The next pointer
is const because nodes are never modified after construction;
they are simply constructed anew when reused.
*/
struct item_t
/** A block of memory that is owned by a slab allocator */
struct SlabBlock
{
item_t* const next;
// A mutex to protect the freelist for this block:
std::mutex m_;
constexpr explicit item_t(item_t* n) noexcept : next(n)
// A linked list of appropriately sized free buffers:
std::uint8_t* l_ = nullptr;
// The next memory block
SlabBlock* next_;
// The underlying memory block:
std::uint8_t const* const p_ = nullptr;
// The extent of the underlying memory block:
std::size_t const size_;
SlabBlock(
SlabBlock* next,
std::uint8_t* data,
std::size_t size,
std::size_t item)
: next_(next), p_(data), size_(size)
{
}
};
// We don't need to grab the mutex here, since we're the only
// ones with access at this moment.
// We need this to be trivially destructible so that we do not
// have to explicitly invoke the destructor when popping items
// from the free list or when deallocating the slab buffer.
static_assert(std::is_trivially_destructible_v<item_t>);
item_t* head_ = nullptr;
slab_t* const next_ = nullptr;
std::atomic<std::uint8_t*> data_{nullptr};
std::atomic<std::uint8_t> lock_{0};
std::uint16_t cycles_ = 0;
std::uint32_t outstanding_ = 0;
/** Construct a block that is unlinked. */
constexpr slab_t() noexcept = default;
/** Construct a block with a link to the next block in the chain.
@param next Pointer to the next block, or nullptr for the tail.
*/
constexpr explicit slab_t(slab_t* next) noexcept : next_(next)
{
}
~slab_t() = default;
slab_t(slab_t const&) = delete;
slab_t&
operator=(slab_t const&) = delete;
slab_t(slab_t&&) = delete;
slab_t&
operator=(slab_t&&) = delete;
/** Attempt to acquire the block's spinlock.
@return true if lock was acquired, false if already held.
*/
[[nodiscard]] bool
try_lock() noexcept
{
return spin_try_lock(lock_);
}
/** Acquire the block's spinlock, blocking until available. */
void
lock() noexcept
{
spin_lock(lock_);
}
/** Release the block's spinlock. */
void
unlock() noexcept
{
spin_unlock(lock_);
}
/** Attempt to assign a buffer to this block.
If the block has no buffer, takes ownership and initializes
the free list.
@param buffer Pointer to the buffer to assign.
@param slabSize Size of the buffer in bytes.
@param itemSize Size of each item in bytes.
@return Pointer to first item if assigned, nullptr if block already
has a buffer.
*/
[[nodiscard]] std::uint8_t*
try_assign(
std::uint8_t* buffer,
std::size_t slabSize,
std::size_t itemSize) noexcept
{
std::uint8_t* expected = nullptr;
if (!data_.compare_exchange_strong(
expected, buffer, std::memory_order::acquire))
return nullptr;
spin_lock(lock_);
head_ = nullptr;
outstanding_ = 1;
auto p = buffer;
for (std::size_t n = (slabSize / itemSize) - 1; n--; p += itemSize)
head_ = std::construct_at(reinterpret_cast<item_t*>(p), head_);
spin_unlock(lock_);
return p;
}
/** Attempt to allocate from this block.
@return Pointer to allocated memory, or nullptr if block is empty.
*/
[[nodiscard]] std::uint8_t*
try_allocate() noexcept
{
spin_lock(lock_);
auto ret = head_;
if (ret)
{
head_ = ret->next;
++outstanding_;
}
spin_unlock(lock_);
return reinterpret_cast<std::uint8_t*>(ret);
}
/** Attempt to return a pointer to this block.
@param ptr Pointer to memory block.
@param slabSize Size of the slab's data buffer.
@param releaseBuffer Callback invoked with a pointer to the block's
buffer so that it can be released.
@return true if ptr belonged to this block and was freed,
false otherwise.
*/
template <typename ReleaseFunc>
[[nodiscard]] bool
try_deallocate(
std::uint8_t* ptr,
std::size_t slabSize,
ReleaseFunc&& releaseBuffer) noexcept
{
auto data = data_.load(std::memory_order::acquire);
if (!data || ptr < data || ptr >= data + slabSize)
return false;
std::uint8_t* buf = nullptr;
spin_lock(lock_);
assert(ptr != nullptr);
assert(outstanding_ > 0);
head_ = std::construct_at(reinterpret_cast<item_t*>(ptr), head_);
// If this block became empty and it is not the first block, we
// release its buffer. The first block (at the tail of the list
// with next_ == nullptr) is exempt to keep one block ready.
if (--outstanding_ == 0 && next_ != nullptr)
{
head_ = nullptr;
buf = data_.exchange(buf, std::memory_order::relaxed);
cycles_ += (cycles_ < std::numeric_limits<std::uint16_t>::max());
}
spin_unlock(lock_);
if (buf != nullptr)
releaseBuffer(buf);
return true;
}
};
//------------------------------------------------------------------------------
/** Global pool of slab_t objects shared by all slab allocators.
Provides a fixed-size array of pre-allocated slabs with fallback
to heap allocation if exhausted.
*/
class slab_pool_t
{
std::array<slab_t, 32768> blocks_{};
std::atomic<std::size_t> count_{0};
public:
constexpr slab_pool_t() = default;
slab_pool_t(slab_pool_t const&) = delete;
slab_pool_t&
operator=(slab_pool_t const&) = delete;
slab_pool_t(slab_pool_t&&) = delete;
slab_pool_t&
operator=(slab_pool_t&&) = delete;
/** Acquire a slab from the pool.
@param next Pointer to link as the slab's next pointer.
@return Pointer to acquired block, or nullptr if allocation failed.
*/
[[nodiscard]] slab_t*
acquire(slab_t* next) noexcept
{
auto idx = count_.load(std::memory_order::relaxed);
while (idx < blocks_.size())
{
if (count_.compare_exchange_weak(
idx, idx + 1, std::memory_order::relaxed))
while (data + item <= p_ + size_)
{
return std::construct_at(&blocks_[idx], next);
// Use memcpy to avoid unaligned UB
// (will optimize to equivalent code)
std::memcpy(data, &l_, sizeof(std::uint8_t*));
l_ = data;
data += item;
}
}
// Pool exhausted (unlikely!) so fall back to heap
return new (std::nothrow) slab_t(next);
}
};
/// Single global block pool for all slab allocators.
inline constinit slab_pool_t globalSlabPool;
} // namespace detail
//------------------------------------------------------------------------------
/** A slab allocator for fixed-size memory blocks.
Allocates memory in large slabs (multiples of 2MB) and sub-allocates
fixed-size blocks from them. Provides fast allocation with minimal
fragmentation for objects of uniform size.
@tparam Type The type used to determine minimum block size and alignment.
@tparam Align Alignment for allocated blocks (must be >= alignof(Type)).
*/
template <typename Type, std::size_t Align = alignof(Type)>
requires(
sizeof(Type) >= sizeof(void*) && Align >= alignof(Type) &&
std::has_single_bit(Align))
class sized_allocator_t
{
/// Linked list of slabs for this allocator.
std::atomic<detail::slab_t*> slabs_{nullptr};
/// Cached buffer to avoid thrashing when oscillating around block
/// boundaries.
std::atomic<std::uint8_t*> cachedBuffer_{nullptr};
/// Spinlock to serialize the slow allocation path.
std::atomic<std::uint8_t> blockLock_{0};
/// Item size (sizeof(Type) + extra, rounded up for alignment).
std::size_t itemSize_;
/// Size of each slab's data buffer (multiple of 2 MB).
std::size_t slabSize_;
/** Allocate a memory block from the existing slabs.
Fast path allocation that doesn't acquire the global lock.
@return Pointer to allocated memory, or nullptr if all slabs are full.
*/
[[nodiscard]] std::uint8_t*
fast_allocate() noexcept
{
for (auto slab = slabs_.load(std::memory_order::acquire); slab;
slab = slab->next_)
~SlabBlock()
{
if (auto ret = slab->try_allocate())
return ret;
// Calling this destructor will release the allocated memory but
// will not properly destroy any objects that are constructed in
// the block itself.
}
return nullptr;
}
SlabBlock(SlabBlock const& other) = delete;
SlabBlock&
operator=(SlabBlock const& other) = delete;
/** Allocate a memory block, potentially creating new capacity.
SlabBlock(SlabBlock&& other) = delete;
SlabBlock&
operator=(SlabBlock&& other) = delete;
Slow path allocation that may allocate a new buffer or slab.
Must be called with blockLock_ held.
/** Determines whether the given pointer belongs to this allocator */
bool
own(std::uint8_t const* p) const noexcept
{
return (p >= p_) && (p < p_ + size_);
}
std::uint8_t*
allocate() noexcept
{
std::uint8_t* ret;
{
std::lock_guard l(m_);
ret = l_;
if (ret)
{
// Use memcpy to avoid unaligned UB
// (will optimize to equivalent code)
std::memcpy(&l_, ret, sizeof(std::uint8_t*));
}
}
@return Pointer to allocated memory, or nullptr on failure.
*/
[[nodiscard]] std::uint8_t*
slow_allocate() noexcept
{
if (auto ret = fast_allocate())
return ret;
// Use a cached buffer first, if we have one, or allocate memory
// from the operating system.
auto buf = cachedBuffer_.exchange(nullptr, std::memory_order::acquire);
if (!buf)
buf = detail::allocateBuffer(slabSize_);
if (!buf) [[unlikely]]
return nullptr;
// Try to give buffer to an existing empty slab
for (auto slab = slabs_.load(std::memory_order::acquire); slab;
slab = slab->next_)
{
if (auto ret = slab->try_assign(buf, slabSize_, itemSize_))
return ret;
}
// Create new slab from global pool
auto* slab = detail::globalSlabPool.acquire(
slabs_.load(std::memory_order::relaxed));
/** Return an item to this allocator's freelist.
if (!slab) [[unlikely]]
@param ptr The pointer to the chunk of memory being deallocated.
@note This is a dangerous, private interface; the item being
returned should belong to this allocator. Debug builds
will check and assert if this is not the case. Release
builds will not.
*/
void
deallocate(std::uint8_t* ptr) noexcept
{
detail::deallocateBuffer(buf);
return nullptr;
XRPL_ASSERT(
own(ptr),
"ripple::SlabAllocator::SlabBlock::deallocate : own input");
std::lock_guard l(m_);
// Use memcpy to avoid unaligned UB
// (will optimize to equivalent code)
std::memcpy(ptr, &l_, sizeof(std::uint8_t*));
l_ = ptr;
}
};
auto ret = slab->try_assign(buf, slabSize_, itemSize_);
assert(ret);
private:
// A linked list of slabs
std::atomic<SlabBlock*> slabs_ = nullptr;
// Link the new slab. Since we hold the lock, we can just do a
// direct assignment here.
slabs_.store(slab, std::memory_order::release);
// The alignment requirements of the item we're allocating:
std::size_t const itemAlignment_;
return ret;
}
// The size of an item, including the extra bytes requested and
// any padding needed for alignment purposes:
std::size_t const itemSize_;
// The size of each individual slab:
std::size_t const slabSize_;
public:
/** Constructs a slab allocator able to allocate objects of a fixed size
@param extra Extra bytes per item beyond sizeof(Type).
@param minItems Minimum number of items per slab (rounded up to 2MB).
@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 mimimal memory usage is needed) and
allows for graceful failure.
*/
constexpr explicit sized_allocator_t(
constexpr explicit SlabAllocator(
std::size_t extra,
std::size_t minItems)
: itemSize_(boost::alignment::align_up(sizeof(Type) + extra, Align))
, slabSize_(boost::alignment::align_up(
itemSize_ * minItems,
detail::pageSize))
std::size_t alloc = 0,
std::size_t align = 0)
: itemAlignment_(align ? align : alignof(Type))
, itemSize_(
boost::alignment::align_up(sizeof(Type) + extra, itemAlignment_))
, slabSize_(alloc)
{
XRPL_ASSERT(
(itemAlignment_ & (itemAlignment_ - 1)) == 0,
"ripple::SlabAllocator::SlabAllocator : valid alignment");
}
// Data buffers are intentionally not released. C++ destruction order
// does not guarantee that all items allocated from this allocator
// have been freed by the time this destructor runs.
~sized_allocator_t() = default;
SlabAllocator(SlabAllocator const& other) = delete;
SlabAllocator&
operator=(SlabAllocator const& other) = delete;
sized_allocator_t(sized_allocator_t const&) = delete;
sized_allocator_t&
operator=(sized_allocator_t const&) = delete;
sized_allocator_t(sized_allocator_t&&) = delete;
sized_allocator_t&
operator=(sized_allocator_t&&) = delete;
SlabAllocator(SlabAllocator&& other) = delete;
SlabAllocator&
operator=(SlabAllocator&& other) = delete;
/** Returns the size of memory blocks returned by this allocator.
~SlabAllocator()
{
// FIXME: We can't destroy the memory blocks we've allocated, because
// we can't be sure that they are not being used. Cleaning the
// shutdown process up could make this possible.
}
@return Size of each allocated block in bytes.
*/
[[nodiscard]] constexpr std::size_t
/** Returns the size of the memory block this allocator returns. */
constexpr std::size_t
size() const noexcept
{
return itemSize_;
@@ -465,36 +217,87 @@ public:
/** Returns a suitably aligned pointer, if one is available.
@return Pointer to allocated memory, or nullptr on failure.
@note The gnu::malloc attribute is an optimization hint that can
be leveraged by GCC and Clang.
@return a pointer to a block of memory from the allocator, or
nullptr if the allocator can't satisfy this request.
*/
[[nodiscard, gnu::malloc]] std::uint8_t*
std::uint8_t*
allocate() noexcept
{
// Fast path: try existing slabs
auto ret = fast_allocate();
auto slab = slabs_.load();
if (ret == nullptr)
while (slab != nullptr)
{
// Slow path: need new capacity. Grab the lock to serialize access
// to this code path because it is expensive. Then re-check in case
// another thread added capacity while we waited.
spin_lock(blockLock_);
ret = slow_allocate();
spin_unlock(blockLock_);
if (auto ret = slab->allocate())
return ret;
slab = slab->next_;
}
return ret;
// No slab can satisfy our request, so we attempt to allocate a new
// one here:
std::size_t size = slabSize_;
// We want to allocate the memory at a 2 MiB boundary, to make it
// possible to use hugepage mappings on Linux:
auto buf =
boost::alignment::aligned_alloc(megabytes(std::size_t(2)), size);
// clang-format off
if (!buf) [[unlikely]]
return nullptr;
// clang-format on
#if BOOST_OS_LINUX
// When allocating large blocks, attempt to leverage Linux's
// transparent hugepage support. It is unclear and difficult
// to accurately determine if doing this impacts performance
// enough to justify using platform-specific tricks.
if (size >= megabytes(std::size_t(4)))
madvise(buf, size, MADV_HUGEPAGE);
#endif
// We need to carve out a bit of memory for the slab header
// and then align the rest appropriately:
auto slabData = reinterpret_cast<void*>(
reinterpret_cast<std::uint8_t*>(buf) + sizeof(SlabBlock));
auto slabSize = size - sizeof(SlabBlock);
// This operation is essentially guaranteed not to fail but
// let's be careful anyways.
if (!boost::alignment::align(
itemAlignment_, itemSize_, slabData, slabSize))
{
boost::alignment::aligned_free(buf);
return nullptr;
}
slab = new (buf) SlabBlock(
slabs_.load(),
reinterpret_cast<std::uint8_t*>(slabData),
slabSize,
itemSize_);
// Link the new slab
while (!slabs_.compare_exchange_weak(
slab->next_,
slab,
std::memory_order_release,
std::memory_order_relaxed))
{
; // Nothing to do
}
return slab->allocate();
}
/** Returns the memory block to the allocator.
@param ptr Pointer to memory block.
@return true if the block belonged to this allocator and was freed.
@param ptr A pointer to a memory block.
@param size If non-zero, a hint as to the size of the block.
@return true if this memory block belonged to the allocator and has
been released; false otherwise.
*/
[[nodiscard]] bool
bool
deallocate(std::uint8_t* ptr) noexcept
{
XRPL_ASSERT(
@@ -502,135 +305,112 @@ public:
"ripple::SlabAllocator::SlabAllocator::deallocate : non-null "
"input");
auto release = [this](std::uint8_t* buf) {
std::uint8_t* expected = nullptr;
if (buf != nullptr &&
!cachedBuffer_.compare_exchange_strong(
expected, buf, std::memory_order::release))
detail::deallocateBuffer(buf);
};
for (auto slab = slabs_.load(std::memory_order::acquire); slab;
slab = slab->next_)
for (auto slab = slabs_.load(); slab != nullptr; slab = slab->next_)
{
if (slab->try_deallocate(ptr, slabSize_, release))
if (slab->own(ptr))
{
slab->deallocate(ptr);
return true;
}
}
return false;
}
};
//------------------------------------------------------------------------------
/** Configuration for a single slab allocator.
@tparam MinItems Minimum number of items per slab (must be > 0).
@tparam Extra Extra bytes per item beyond sizeof(Type).
*/
template <std::size_t MinItems, std::size_t Extra = 0>
requires(MinItems > 0)
struct config
/** A collection of slab allocators of various sizes for a given type. */
template <typename Type>
class SlabAllocatorSet
{
static constexpr std::size_t minItems = MinItems;
static constexpr std::size_t extra = Extra;
};
private:
// The list of allocators that belong to this set
boost::container::static_vector<SlabAllocator<Type>, 64> allocators_;
/** Concept for valid slab configuration types. */
template <typename T>
concept SlabConfig = requires {
{ T::minItems } -> std::convertible_to<std::size_t>;
{ T::extra } -> std::convertible_to<std::size_t>;
requires T::minItems > 0;
};
/** Validate slab configurations at compile time.
Checks that configurations produce strictly increasing sizes after
alignment. This catches both unsorted configs and configs that
collapse to the same size after alignment.
@tparam Type The type used to determine base size.
@tparam Align Alignment for allocated blocks.
@tparam Configs Configuration types to validate.
@return true if configurations are valid, false otherwise.
*/
template <typename Type, std::size_t Align, SlabConfig... Configs>
consteval bool
validate_slab_config()
{
constexpr auto align_up = [](std::size_t n, std::size_t a) {
return (n + a - 1) & ~(a - 1);
};
constexpr std::array<std::size_t, sizeof...(Configs)> sizes{
align_up(sizeof(Type) + Configs::extra, Align)...};
for (std::size_t i = 1; i < sizes.size(); ++i)
if (sizes[i - 1] >= sizes[i])
return false;
return true;
}
//------------------------------------------------------------------------------
/** A collection of slab allocators for different sizes.
Manages multiple sized_allocator_t instances, each configured for a
different block size. Allocations are routed to the smallest allocator
that can satisfy the request.
@tparam Type The type used to determine minimum block size and alignment.
@tparam Align Alignment for allocated blocks (must be >= alignof(Type)).
@tparam Configs Configuration types specifying each size class.
*/
template <typename Type, std::size_t Align, SlabConfig... Configs>
requires(
sizeof(Type) >= sizeof(void*) && Align >= alignof(Type) &&
std::has_single_bit(Align) && sizeof...(Configs) > 0 &&
validate_slab_config<Type, Align, Configs...>())
class aligned_allocator_t
{
std::array<sized_allocator_t<Type, Align>, sizeof...(Configs)> allocators_;
std::size_t maxSize_ = 0;
public:
/** Construct an allocator set. */
constexpr aligned_allocator_t()
: allocators_{sized_allocator_t<Type, Align>(
Configs::extra,
Configs::minItems)...}
class SlabConfig
{
friend class SlabAllocatorSet;
private:
std::size_t extra;
std::size_t alloc;
std::size_t align;
public:
constexpr SlabConfig(
std::size_t extra_,
std::size_t alloc_ = 0,
std::size_t align_ = alignof(Type))
: extra(extra_), alloc(alloc_), align(align_)
{
}
};
constexpr SlabAllocatorSet(std::vector<SlabConfig> cfg)
{
// Ensure that the specified allocators are sorted from smallest to
// largest by size:
std::sort(
std::begin(cfg),
std::end(cfg),
[](SlabConfig const& a, SlabConfig const& b) {
return a.extra < b.extra;
});
// We should never have two slabs of the same size
if (std::adjacent_find(
std::begin(cfg),
std::end(cfg),
[](SlabConfig const& a, SlabConfig const& b) {
return a.extra == b.extra;
}) != cfg.end())
{
throw std::runtime_error(
"SlabAllocatorSet<" + beast::type_name<Type>() +
">: duplicate slab size");
}
for (auto const& c : cfg)
{
auto& a = allocators_.emplace_back(c.extra, c.alloc, c.align);
if (a.size() > maxSize_)
maxSize_ = a.size();
}
}
SlabAllocatorSet(SlabAllocatorSet const& other) = delete;
SlabAllocatorSet&
operator=(SlabAllocatorSet const& other) = delete;
SlabAllocatorSet(SlabAllocatorSet&& other) = delete;
SlabAllocatorSet&
operator=(SlabAllocatorSet&& other) = delete;
~SlabAllocatorSet()
{
}
~aligned_allocator_t() = default;
/** Returns a suitably aligned pointer, if one is available.
aligned_allocator_t(aligned_allocator_t const&) = delete;
aligned_allocator_t&
operator=(aligned_allocator_t const&) = delete;
aligned_allocator_t(aligned_allocator_t&&) = delete;
aligned_allocator_t&
operator=(aligned_allocator_t&&) = delete;
@param extra The number of extra bytes, above and beyond the size of
the object, that should be returned by the allocator.
/** Allocate memory for an object with extra bytes.
@param extra Extra bytes needed beyond sizeof(Type).
@return Pointer to memory, or nullptr if no suitable allocator
or allocation failed.
@note The gnu::malloc attribute is an optimization hint that can
be leveraged by GCC and Clang.
@return a pointer to a block of memory, or nullptr if the allocator
can't satisfy this request.
*/
[[nodiscard, gnu::malloc]] std::uint8_t*
std::uint8_t*
allocate(std::size_t extra) noexcept
{
auto const size = sizeof(Type) + extra;
for (auto& a : allocators_)
if (auto const size = sizeof(Type) + extra; size <= maxSize_)
{
if (a.size() >= size)
return a.allocate();
for (auto& a : allocators_)
{
if (a.size() >= size)
return a.allocate();
}
}
return nullptr;
@@ -638,10 +418,12 @@ public:
/** Returns the memory block to the allocator.
@param ptr Pointer to memory block.
@return true if memory belonged to this set and was freed.
@param ptr A pointer to a memory block.
@return true if this memory block belonged to one of the allocators
in this set and has been released; false otherwise.
*/
[[nodiscard]] bool
bool
deallocate(std::uint8_t* ptr) noexcept
{
for (auto& a : allocators_)
@@ -649,16 +431,11 @@ public:
if (a.deallocate(ptr))
return true;
}
return false;
}
};
/** Alias for aligned_allocator_t with default alignment. */
template <typename Type, SlabConfig... Configs>
using allocator_t = aligned_allocator_t<Type, alignof(Type), Configs...>;
} // namespace slab
} // namespace ripple
#endif // RIPPLE_BASICS_SLABALLOCATOR_H_INCLUDED
+3 -3
View File
@@ -77,7 +77,7 @@ strUnHex(std::size_t strSize, Iterator begin, Iterator end)
if (strSize & 1)
{
int c = unxtab[static_cast<unsigned char>(*iter++)];
int c = unxtab[*iter++];
if (c < 0)
return {};
@@ -87,12 +87,12 @@ strUnHex(std::size_t strSize, Iterator begin, Iterator end)
while (iter != end)
{
int cHigh = unxtab[static_cast<unsigned char>(*iter++)];
int cHigh = unxtab[*iter++];
if (cHigh < 0)
return {};
int cLow = unxtab[static_cast<unsigned char>(*iter++)];
int cLow = unxtab[*iter++];
if (cLow < 0)
return {};
-60
View File
@@ -1,60 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2025 XRPL Labs
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_UTF8_H_INCLUDED
#define RIPPLE_BASICS_UTF8_H_INCLUDED
#include <xrpl/basics/Slice.h>
namespace ripple {
/** Check that a byte sequence is well-formed UTF-8, excluding the two
noncharacters U+FFFE and U+FFFF.
Rejects:
- overlong encodings;
- UTF-16 surrogate halves (U+D800..U+DFFF);
- scalar values above U+10FFFF, and 0xF5..0xFF lead bytes;
- stray continuation bytes;
- multi-byte sequences truncated by the end of the buffer;
- U+FFFE and U+FFFF (EF BF BE, EF BF BF).
U+FFFE and U+FFFF are well-formed, but have no use in a URI or a name
and exist to be misread: U+FFFE is a byte-swapped BOM, so a client that
transcodes to UTF-16/32 and sniffs the byte order can be pushed into
decoding the rest of the string with the wrong endianness, and both are
commonly used as in-band sentinels. They have always been rejected by
URIToken and HookName validation, and this function preserves that.
This is consensus-critical. For every input the previous decoder could
evaluate without reading past the end of the buffer, the result is
identical to it. The only difference is that truncated trailing
sequences, where the previous decoder read out of bounds, are now always
rejected. Any further change to what this accepts needs an amendment.
@param s The bytes to check.
@note Total: every byte read is within s.
*/
bool
isValidUTF8(Slice const& s) noexcept;
} // namespace ripple
#endif
File diff suppressed because it is too large. Load diff
+5 -11
View File
@@ -23,7 +23,6 @@
#include <xrpl/beast/type_name.h>
#include <exception>
#include <string>
#include <type_traits>
#include <typeinfo>
#include <utility>
@@ -53,7 +52,7 @@ Rethrow()
}
template <class E, class... Args>
[[noreturn]] constexpr void
[[noreturn]] inline void
Throw(Args&&... args)
{
static_assert(
@@ -61,15 +60,10 @@ Throw(Args&&... args)
"Exception must derive from std::exception.");
E e(std::forward<Args>(args)...);
// Skip logging when evaluated at compile time, so that `Throw` can be
// called from constexpr/consteval functions.
if (!std::is_constant_evaluated())
LogThrow(
std::string(
"Throwing exception of type " + beast::type_name<E>() + ": ") +
e.what());
LogThrow(
std::string(
"Throwing exception of type " + beast::type_name<E>() + ": ") +
e.what());
throw e;
}
+96 -139
View File
@@ -20,7 +20,6 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <atomic>
#include <concepts>
#include <limits>
#include <type_traits>
@@ -31,7 +30,6 @@
namespace ripple {
namespace detail {
/** Inform the processor that we are in a tight spin-wait loop.
Spinlocks caught in tight loops can result in the processor's pipeline
@@ -54,130 +52,11 @@ spin_pause() noexcept
} // namespace detail
/** Attempt to acquire a spinlock without blocking.
/** @{ */
/** Classes to handle arrays of spinlocks packed into a single atomic integer:
@tparam T An unsigned integral type.
@param lock The atomic variable used as the lock.
@return true if the lock was acquired, false if it was already held.
*/
template <typename T>
requires(std::is_unsigned_v<T> && std::atomic<T>::is_always_lock_free)
[[nodiscard]] bool
spin_try_lock(std::atomic<T>& lock) noexcept
{
T expected = 0;
return lock.compare_exchange_strong(
expected,
std::numeric_limits<T>::max(),
std::memory_order::acquire,
std::memory_order::relaxed);
}
/** Acquire a spinlock, blocking until available.
Uses a TTAS (test-and-test-and-set) pattern to reduce cache coherency
traffic during contention.
@tparam T An unsigned integral type.
@param lock The atomic variable used as the lock.
*/
template <typename T>
requires(std::is_unsigned_v<T> && std::atomic<T>::is_always_lock_free)
void
spin_lock(std::atomic<T>& lock) noexcept
{
T expected = 0;
while (!lock.compare_exchange_weak(
expected,
std::numeric_limits<T>::max(),
std::memory_order::acquire,
std::memory_order::relaxed))
{
expected = 0;
while (lock.load(std::memory_order::relaxed) != 0)
detail::spin_pause();
}
}
/** Release a spinlock.
@tparam T An unsigned integral type.
@param lock The atomic variable used as the lock.
*/
template <typename T>
requires(std::is_unsigned_v<T> && std::atomic<T>::is_always_lock_free)
void
spin_unlock(std::atomic<T>& lock) noexcept
{
lock.store(0, std::memory_order::release);
}
//------------------------------------------------------------------------------
/** A Lockable interface to a spinlock implemented on top of an atomic.
@tparam T An unsigned integral type.
@note Using `packed_spinlock` and `spinlock` against the same underlying
atomic integer can result in `spinlock` not being able to actually
acquire the lock during periods of high contention, because of how
the two locks operate: `spinlock` will spin trying to grab all the
bits at once, whereas any given `packed_spinlock` will only try to
grab one bit at a time. Caveat emptor.
This class meets the requirements of Lockable:
https://en.cppreference.com/w/cpp/named_req/Lockable
*/
template <typename T>
requires(std::is_unsigned_v<T> && std::atomic<T>::is_always_lock_free)
class spinlock
{
std::atomic<T>& lock_;
public:
spinlock(spinlock const&) = delete;
spinlock&
operator=(spinlock const&) = delete;
/** Construct a spinlock handle.
@param lock The atomic integer to spin against.
@note For performance reasons, you should strive to have `lock` be
on a cacheline by itself.
*/
explicit spinlock(std::atomic<T>& lock) noexcept : lock_(lock)
{
}
[[nodiscard]] bool
try_lock() noexcept
{
return spin_try_lock(lock_);
}
void
lock() noexcept
{
spin_lock(lock_);
}
void
unlock() noexcept
{
spin_unlock(lock_);
}
};
//------------------------------------------------------------------------------
/** A Lockable interface to a packed spinlock implemented on top of an atomic.
Packed spinlocks offer tremendous space-efficient lock-sharding but
they come at a cost.
Packed spinlocks allow for tremendously space-efficient lock-sharding
but they come at a cost.
First, the implementation is necessarily low-level and uses advanced
features like memory ordering and highly platform-specific tricks to
@@ -199,19 +78,26 @@ public:
that it can, usually, outperform spinlocks.
@tparam T An unsigned integral type (e.g. std::uint16_t)
*/
/** A class that grabs a single packed spinlock from an atomic integer.
This class meets the requirements of Lockable:
https://en.cppreference.com/w/cpp/named_req/Lockable
*/
template <typename T>
requires(
std::is_unsigned_v<T> && std::atomic<T>::is_always_lock_free &&
requires(std::atomic<T>& a, T v) {
{ a.fetch_or(v) } -> std::same_as<T>;
{ a.fetch_and(v) } -> std::same_as<T>;
})
template <class T>
class packed_spinlock
{
// clang-format off
static_assert(std::is_unsigned_v<T>);
static_assert(std::atomic<T>::is_always_lock_free);
static_assert(
std::is_same_v<decltype(std::declval<std::atomic<T>&>().fetch_or(0)), T> &&
std::is_same_v<decltype(std::declval<std::atomic<T>&>().fetch_and(0)), T>,
"std::atomic<T>::fetch_and(T) and std::atomic<T>::fetch_and(T) are required by packed_spinlock");
// clang-format on
private:
std::atomic<T>& bits_;
T const mask_;
@@ -228,7 +114,7 @@ public:
@note For performance reasons, you should strive to have `lock` be
on a cacheline by itself.
*/
packed_spinlock(std::atomic<T>& lock, int index) noexcept
packed_spinlock(std::atomic<T>& lock, int index)
: bits_(lock), mask_(static_cast<T>(1) << index)
{
XRPL_ASSERT(
@@ -237,13 +123,13 @@ public:
}
[[nodiscard]] bool
try_lock() noexcept
try_lock()
{
return (bits_.fetch_or(mask_, std::memory_order::acquire) & mask_) == 0;
return (bits_.fetch_or(mask_, std::memory_order_acquire) & mask_) == 0;
}
void
lock() noexcept
lock()
{
while (!try_lock())
{
@@ -251,18 +137,89 @@ public:
// serves to help reduce cache coherency traffic during times
// of contention by avoiding writes that would definitely not
// result in the lock being acquired.
while ((bits_.load(std::memory_order::relaxed) & mask_) != 0)
while ((bits_.load(std::memory_order_relaxed) & mask_) != 0)
detail::spin_pause();
}
}
void
unlock() noexcept
unlock()
{
bits_.fetch_and(~mask_, std::memory_order::release);
bits_.fetch_and(~mask_, std::memory_order_release);
}
};
/** A spinlock implemented on top of an atomic integer.
@note Using `packed_spinlock` and `spinlock` against the same underlying
atomic integer can result in `spinlock` not being able to actually
acquire the lock during periods of high contention, because of how
the two locks operate: `spinlock` will spin trying to grab all the
bits at once, whereas any given `packed_spinlock` will only try to
grab one bit at a time. Caveat emptor.
This class meets the requirements of Lockable:
https://en.cppreference.com/w/cpp/named_req/Lockable
*/
template <class T>
class spinlock
{
static_assert(std::is_unsigned_v<T>);
static_assert(std::atomic<T>::is_always_lock_free);
private:
std::atomic<T>& lock_;
public:
spinlock(spinlock const&) = delete;
spinlock&
operator=(spinlock const&) = delete;
/** Grabs the
@param lock The atomic integer to spin against.
@note For performance reasons, you should strive to have `lock` be
on a cacheline by itself.
*/
spinlock(std::atomic<T>& lock) : lock_(lock)
{
}
[[nodiscard]] bool
try_lock()
{
T expected = 0;
return lock_.compare_exchange_weak(
expected,
std::numeric_limits<T>::max(),
std::memory_order_acquire,
std::memory_order_relaxed);
}
void
lock()
{
while (!try_lock())
{
// The use of relaxed memory ordering here is intentional and
// serves to help reduce cache coherency traffic during times
// of contention by avoiding writes that would definitely not
// result in the lock being acquired.
while (lock_.load(std::memory_order_relaxed) != 0)
detail::spin_pause();
}
}
void
unlock()
{
lock_.store(0, std::memory_order_release);
}
};
/** @} */
} // namespace ripple
#endif
+16 -23
View File
@@ -22,8 +22,7 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <boost/asio/basic_waitable_timer.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/io_service.hpp>
#include <chrono>
#include <condition_variable>
@@ -32,7 +31,7 @@
namespace beast {
/** Measures handler latency on an io_context queue. */
/** Measures handler latency on an io_service queue. */
template <class Clock>
class io_latency_probe
{
@@ -44,12 +43,12 @@ private:
std::condition_variable_any m_cond;
std::size_t m_count;
duration const m_period;
boost::asio::io_context& m_ios;
boost::asio::io_service& m_ios;
boost::asio::basic_waitable_timer<std::chrono::steady_clock> m_timer;
bool m_cancel;
public:
io_latency_probe(duration const& period, boost::asio::io_context& ios)
io_latency_probe(duration const& period, boost::asio::io_service& ios)
: m_count(1)
, m_period(period)
, m_ios(ios)
@@ -64,16 +63,16 @@ public:
cancel(lock, true);
}
/** Return the io_context associated with the latency probe. */
/** Return the io_service associated with the latency probe. */
/** @{ */
boost::asio::io_context&
get_io_context()
boost::asio::io_service&
get_io_service()
{
return m_ios;
}
boost::asio::io_context const&
get_io_context() const
boost::asio::io_service const&
get_io_service() const
{
return m_ios;
}
@@ -109,10 +108,8 @@ public:
std::lock_guard lock(m_mutex);
if (m_cancel)
throw std::logic_error("io_latency_probe is canceled");
boost::asio::post(
m_ios,
sample_op<Handler>(
std::forward<Handler>(handler), Clock::now(), false, this));
m_ios.post(sample_op<Handler>(
std::forward<Handler>(handler), Clock::now(), false, this));
}
/** Initiate continuous i/o latency sampling.
@@ -126,10 +123,8 @@ public:
std::lock_guard lock(m_mutex);
if (m_cancel)
throw std::logic_error("io_latency_probe is canceled");
boost::asio::post(
m_ios,
sample_op<Handler>(
std::forward<Handler>(handler), Clock::now(), true, this));
m_ios.post(sample_op<Handler>(
std::forward<Handler>(handler), Clock::now(), true, this));
}
private:
@@ -240,13 +235,12 @@ private:
// The latency is too high to maintain the desired
// period so don't bother with a timer.
//
boost::asio::post(
m_probe->m_ios,
m_probe->m_ios.post(
sample_op<Handler>(m_handler, now, m_repeat, m_probe));
}
else
{
m_probe->m_timer.expires_after(when - now);
m_probe->m_timer.expires_from_now(when - now);
m_probe->m_timer.async_wait(
sample_op<Handler>(m_handler, now, m_repeat, m_probe));
}
@@ -259,8 +253,7 @@ private:
if (!m_probe)
return;
typename Clock::time_point const now(Clock::now());
boost::asio::post(
m_probe->m_ios,
m_probe->m_ios.post(
sample_op<Handler>(m_handler, now, m_repeat, m_probe));
}
};
+307
View File
@@ -0,0 +1,307 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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 BEAST_INTRUSIVE_LOCKFREESTACK_H_INCLUDED
#define BEAST_INTRUSIVE_LOCKFREESTACK_H_INCLUDED
#include <atomic>
#include <iterator>
#include <type_traits>
namespace beast {
//------------------------------------------------------------------------------
template <class Container, bool IsConst>
class LockFreeStackIterator
{
protected:
using Node = typename Container::Node;
using NodePtr =
typename std::conditional<IsConst, Node const*, Node*>::type;
public:
using iterator_category = std::forward_iterator_tag;
using value_type = typename Container::value_type;
using difference_type = typename Container::difference_type;
using pointer = typename std::conditional<
IsConst,
typename Container::const_pointer,
typename Container::pointer>::type;
using reference = typename std::conditional<
IsConst,
typename Container::const_reference,
typename Container::reference>::type;
LockFreeStackIterator() : m_node()
{
}
LockFreeStackIterator(NodePtr node) : m_node(node)
{
}
template <bool OtherIsConst>
explicit LockFreeStackIterator(
LockFreeStackIterator<Container, OtherIsConst> const& other)
: m_node(other.m_node)
{
}
LockFreeStackIterator&
operator=(NodePtr node)
{
m_node = node;
return static_cast<LockFreeStackIterator&>(*this);
}
LockFreeStackIterator&
operator++()
{
m_node = m_node->m_next.load();
return static_cast<LockFreeStackIterator&>(*this);
}
LockFreeStackIterator
operator++(int)
{
LockFreeStackIterator result(*this);
m_node = m_node->m_next;
return result;
}
NodePtr
node() const
{
return m_node;
}
reference
operator*() const
{
return *this->operator->();
}
pointer
operator->() const
{
return static_cast<pointer>(m_node);
}
private:
NodePtr m_node;
};
//------------------------------------------------------------------------------
template <class Container, bool LhsIsConst, bool RhsIsConst>
bool
operator==(
LockFreeStackIterator<Container, LhsIsConst> const& lhs,
LockFreeStackIterator<Container, RhsIsConst> const& rhs)
{
return lhs.node() == rhs.node();
}
template <class Container, bool LhsIsConst, bool RhsIsConst>
bool
operator!=(
LockFreeStackIterator<Container, LhsIsConst> const& lhs,
LockFreeStackIterator<Container, RhsIsConst> const& rhs)
{
return lhs.node() != rhs.node();
}
//------------------------------------------------------------------------------
/** Multiple Producer, Multiple Consumer (MPMC) intrusive stack.
This stack is implemented using the same intrusive interface as List.
All mutations are lock-free.
The caller is responsible for preventing the "ABA" problem:
http://en.wikipedia.org/wiki/ABA_problem
@param Tag A type name used to distinguish lists and nodes, for
putting objects in multiple lists. If this parameter is
omitted, the default tag is used.
*/
template <class Element, class Tag = void>
class LockFreeStack
{
public:
class Node
{
public:
Node() : m_next(nullptr)
{
}
explicit Node(Node* next) : m_next(next)
{
}
Node(Node const&) = delete;
Node&
operator=(Node const&) = delete;
private:
friend class LockFreeStack;
template <class Container, bool IsConst>
friend class LockFreeStackIterator;
std::atomic<Node*> m_next;
};
public:
using value_type = Element;
using pointer = Element*;
using reference = Element&;
using const_pointer = Element const*;
using const_reference = Element const&;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using iterator = LockFreeStackIterator<LockFreeStack<Element, Tag>, false>;
using const_iterator =
LockFreeStackIterator<LockFreeStack<Element, Tag>, true>;
LockFreeStack() : m_end(nullptr), m_head(&m_end)
{
}
LockFreeStack(LockFreeStack const&) = delete;
LockFreeStack&
operator=(LockFreeStack const&) = delete;
/** Returns true if the stack is empty. */
bool
empty() const
{
return m_head.load() == &m_end;
}
/** Push a node onto the stack.
The caller is responsible for preventing the ABA problem.
This operation is lock-free.
Thread safety:
Safe to call from any thread.
@param node The node to push.
@return `true` if the stack was previously empty. If multiple threads
are attempting to push, only one will receive `true`.
*/
// VFALCO NOTE Fix this, shouldn't it be a reference like intrusive list?
bool
push_front(Node* node)
{
bool first;
Node* old_head = m_head.load(std::memory_order_relaxed);
do
{
first = (old_head == &m_end);
node->m_next = old_head;
} while (!m_head.compare_exchange_strong(
old_head,
node,
std::memory_order_release,
std::memory_order_relaxed));
return first;
}
/** Pop an element off the stack.
The caller is responsible for preventing the ABA problem.
This operation is lock-free.
Thread safety:
Safe to call from any thread.
@return The element that was popped, or `nullptr` if the stack
was empty.
*/
Element*
pop_front()
{
Node* node = m_head.load();
Node* new_head;
do
{
if (node == &m_end)
return nullptr;
new_head = node->m_next.load();
} while (!m_head.compare_exchange_strong(
node,
new_head,
std::memory_order_release,
std::memory_order_relaxed));
return static_cast<Element*>(node);
}
/** Return a forward iterator to the beginning or end of the stack.
Undefined behavior results if push_front or pop_front is called
while an iteration is in progress.
Thread safety:
Caller is responsible for synchronization.
*/
/** @{ */
iterator
begin()
{
return iterator(m_head.load());
}
iterator
end()
{
return iterator(&m_end);
}
const_iterator
begin() const
{
return const_iterator(m_head.load());
}
const_iterator
end() const
{
return const_iterator(&m_end);
}
const_iterator
cbegin() const
{
return const_iterator(m_head.load());
}
const_iterator
cend() const
{
return const_iterator(&m_end);
}
/** @} */
private:
Node m_end;
std::atomic<Node*> m_head;
};
} // namespace beast
#endif
+8 -19
View File
@@ -8,12 +8,9 @@
#ifndef BEAST_TEST_YIELD_TO_HPP
#define BEAST_TEST_YIELD_TO_HPP
#include <boost/asio/executor_work_guard.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/optional.hpp>
#include <boost/thread/csbl/memory/allocator_arg.hpp>
#include <condition_variable>
#include <functional>
#include <mutex>
@@ -32,12 +29,10 @@ namespace test {
class enable_yield_to
{
protected:
boost::asio::io_context ios_;
boost::asio::io_service ios_;
private:
boost::optional<boost::asio::executor_work_guard<
boost::asio::io_context::executor_type>>
work_;
boost::optional<boost::asio::io_service::work> work_;
std::vector<std::thread> threads_;
std::mutex m_;
std::condition_variable cv_;
@@ -47,8 +42,7 @@ public:
/// The type of yield context passed to functions.
using yield_context = boost::asio::yield_context;
explicit enable_yield_to(std::size_t concurrency = 1)
: work_(boost::asio::make_work_guard(ios_))
explicit enable_yield_to(std::size_t concurrency = 1) : work_(ios_)
{
threads_.reserve(concurrency);
while (concurrency--)
@@ -62,9 +56,9 @@ public:
t.join();
}
/// Return the `io_context` associated with the object
boost::asio::io_context&
get_io_context()
/// Return the `io_service` associated with the object
boost::asio::io_service&
get_io_service()
{
return ios_;
}
@@ -117,18 +111,13 @@ enable_yield_to::spawn(F0&& f, FN&&... fn)
{
boost::asio::spawn(
ios_,
boost::allocator_arg,
boost::context::fixedsize_stack(2 * 1024 * 1024),
[&](yield_context yield) {
f(yield);
std::lock_guard lock{m_};
if (--running_ == 0)
cv_.notify_all();
},
[](std::exception_ptr e) {
if (e)
std::rethrow_exception(e);
});
boost::coroutines::attributes(2 * 1024 * 1024));
spawn(fn...);
}
+16 -27
View File
@@ -15,9 +15,7 @@
#define uint256 std::string
#define featureHooksUpdate1 "1"
#define featureHooksUpdate2 "1"
#define featureRNG "1"
#define fix20250131 "1"
#define fixGuardDepth32 "1"
namespace hook_api {
struct Rules
{
@@ -314,7 +312,6 @@ enum keylet_code : uint32_t {
MPTOKEN = 34,
CREDENTIAL = 35,
PERMISSIONED_DOMAIN = 36,
MANIFEST = 37,
};
}
@@ -322,7 +319,7 @@ namespace compare_mode {
enum compare_mode : uint32_t { EQUAL = 1, LESS = 2, GREATER = 4 };
}
enum class hook_return_code : int64_t {
enum hook_return_code : int64_t {
SUCCESS =
0, // return codes > 0 are reserved for hook apis to return "success"
OUT_OF_BOUNDS =
@@ -384,14 +381,12 @@ enum class hook_return_code : int64_t {
INVALID_KEY = -41, // user supplied key was not valid
NOT_A_STRING = -42, // nul terminator missing from a string argument
MEM_OVERLAP = -43, // one or more specified buffers are the same memory
TOO_MANY_STATE_MODIFICATIONS = -44, // more than 256 modified state
TOO_MANY_STATE_MODIFICATIONS = -44, // more than 5000 modified state
// entires in the combined hook chains
TOO_MANY_NAMESPACES = -45,
TOO_LITTLE_ENTROPY = -46 // featureRNG: no seed for this ledger, or too few
// validators contributed to it
TOO_MANY_NAMESPACES = -45
};
enum class ExitType : uint8_t {
enum ExitType : uint8_t {
UNSET = 0,
WASM_ERROR = 1,
ROLLBACK = 2,
@@ -401,25 +396,12 @@ enum class ExitType : uint8_t {
const uint16_t max_state_modifications = 256;
const uint8_t max_slots = 255;
const uint8_t max_nonce = 255;
const uint16_t max_rng_draws = 256; // featureRNG, per Hook execution
const uint8_t max_emit = 255;
const uint8_t max_params = 16;
const double fee_base_multiplier = 1.1f;
using APIWhitelist = std::map<std::string, std::vector<uint8_t>>;
namespace detail {
template <class T>
constexpr uint8_t wasmTypeCode = sizeof(T) == 8 ? 0x7EU : 0x7FU;
template <class R, class... Args>
std::vector<uint8_t>
wasmSignature(R (*)(Args...))
{
return {wasmTypeCode<R>, wasmTypeCode<Args>...};
}
} // namespace detail
// RH NOTE: Find descriptions of api functions in ./impl/applyHook.cpp and
// hookapi.h (include for hooks) this is a map of the api name to its return
// code (vec[0] and its parameters vec[>0]) as wasm type codes
@@ -431,15 +413,25 @@ getImportWhitelist(Rules const& rules)
#pragma push_macro("HOOK_API_DEFINITION")
#undef HOOK_API_DEFINITION
#define int64_t 0x7EU
#define int32_t 0x7FU
#define uint32_t 0x7FU
#define HOOK_WRAP_PARAMS(...) __VA_ARGS__
#define HOOK_API_DEFINITION( \
RETURN_TYPE, FUNCTION_NAME, PARAMS_TUPLE, AMENDMENT) \
if (AMENDMENT == uint256{} || rules.enabled(AMENDMENT)) \
whitelist[#FUNCTION_NAME] = \
detail::wasmSignature((RETURN_TYPE(*) PARAMS_TUPLE) nullptr);
whitelist[#FUNCTION_NAME] = { \
RETURN_TYPE, HOOK_WRAP_PARAMS PARAMS_TUPLE};
#include "hook_api.macro"
#undef HOOK_API_DEFINITION
#undef HOOK_WRAP_PARAMS
#undef int64_t
#undef int32_t
#undef uint32_t
#pragma pop_macro("HOOK_API_DEFINITION")
return whitelist;
@@ -451,7 +443,6 @@ getImportWhitelist(Rules const& rules)
enum GuardRulesVersion : uint64_t {
GuardRuleFix20250131 = 0x00000001,
GuardRuleDepth32 = 0x00000002,
};
inline uint64_t
@@ -460,8 +451,6 @@ getGuardRulesVersion(Rules const& rules)
uint64_t version = 0;
if (rules.enabled(fix20250131))
version |= GuardRuleFix20250131;
if (rules.enabled(fixGuardDepth32))
version |= GuardRuleDepth32;
return version;
}
+8 -21
View File
@@ -87,7 +87,7 @@ parseSignedLeb128(
}
*end_offset = i;
if (shift < 64 && (b & 0x40U))
val |= (~int64_t{0} << shift);
val |= (~0 << shift);
return val;
}
@@ -204,13 +204,9 @@ struct WasmBlkInf
}
// compute worst case execution time
inline uint64_t
compute_wce(
const WasmBlkInf* blk,
int level,
int max_level,
bool* recursion_limit_reached)
compute_wce(const WasmBlkInf* blk, int level, bool* recursion_limit_reached)
{
if (level > max_level)
if (level > 16)
{
*recursion_limit_reached = true;
return 0;
@@ -237,8 +233,8 @@ compute_wce(
if (blk->children.size() > 0)
for (auto const& child : blk->children)
worst_case_execution += compute_wce(
child, level + 1, max_level, recursion_limit_reached);
worst_case_execution +=
compute_wce(child, level + 1, recursion_limit_reached);
if (parent == 0 ||
parent->iteration_bound ==
@@ -792,17 +788,12 @@ check_guard(
}
bool recursion_limit_reached = false;
int max_level = 16;
if (rulesVersion & hook_api::GuardRuleDepth32)
max_level = 32;
uint64_t wce =
compute_wce(&(*root), 0, max_level, &recursion_limit_reached);
uint64_t wce = compute_wce(&(*root), 0, &recursion_limit_reached);
if (recursion_limit_reached)
{
GUARDLOG(hook::log::NESTING_LIMIT)
<< "GuardCheck "
<< "Maximum allowable depth of blocks reached (" << max_level
<< " levels). Flatten "
<< "Maximum allowable depth of blocks reached (16 levels). Flatten "
"your loops and conditions!.\n";
return {};
}
@@ -1096,11 +1087,7 @@ validateGuards(
{
int name_len = parseLeb128(wasm, i, &i);
CHECK_SHORT_HOOK();
// Only compare the name if all four bytes are in bounds. A
// name running past the end is rejected as a short hook below
// either way, so this does not change which hooks are valid.
if (name_len == 4 &&
static_cast<std::size_t>(i) + 4 <= wasm.size())
if (name_len == 4)
{
if (wasm[i] == 'h' && wasm[i + 1] == 'o' &&
wasm[i + 2] == 'o' && wasm[i + 3] == 'k')
+50 -67
View File
@@ -89,69 +89,58 @@
#define WASM_VAL_TYPE(T, b) CAT2(TYP_, T)
#define UNSIGNED_TYPE(T) std::make_unsigned_t<T>
#define DECLARE_HOOK_FUNCTION(R, F, ...) \
std::variant<UNSIGNED_TYPE(R), hook_api::hook_return_code> F( \
hook::HookContext& hookCtx, \
WasmEdge_CallingFrameContext const& frameCtx __VA_OPT__( \
COMMA __VA_ARGS__)); \
extern WasmEdge_Result WasmFunction##F( \
void* data_ptr, \
const WasmEdge_CallingFrameContext* frameCtx, \
const WasmEdge_Value* in, \
WasmEdge_Value* out); \
extern WasmEdge_ValType WasmFunctionParams##F[]; \
extern WasmEdge_ValType WasmFunctionResult##F[]; \
extern WasmEdge_FunctionTypeContext* WasmFunctionType##F; \
#define DECLARE_HOOK_FUNCTION(R, F, ...) \
R F(hook::HookContext& hookCtx, \
WasmEdge_CallingFrameContext const& frameCtx __VA_OPT__( \
COMMA __VA_ARGS__)); \
extern WasmEdge_Result WasmFunction##F( \
void* data_ptr, \
const WasmEdge_CallingFrameContext* frameCtx, \
const WasmEdge_Value* in, \
WasmEdge_Value* out); \
extern WasmEdge_ValType WasmFunctionParams##F[]; \
extern WasmEdge_ValType WasmFunctionResult##F[]; \
extern WasmEdge_FunctionTypeContext* WasmFunctionType##F; \
extern WasmEdge_String WasmFunctionName##F;
#define DEFINE_HOOK_FUNCTION(R, F, ...) \
WasmEdge_Result hook_api::WasmFunction##F( \
void* data_ptr, \
const WasmEdge_CallingFrameContext* frameCtx, \
const WasmEdge_Value* in, \
WasmEdge_Value* out) \
{ \
__VA_OPT__(int _stack = 0;) \
__VA_OPT__(FOR_VARS(VAR_ASSIGN, 2, __VA_ARGS__);) \
hook::HookContext* hookCtx = \
reinterpret_cast<hook::HookContext*>(data_ptr); \
auto const& return_code = hook_api::F( \
*hookCtx, \
*const_cast<WasmEdge_CallingFrameContext*>(frameCtx) \
__VA_OPT__(COMMA STRIP_TYPES(__VA_ARGS__))); \
if (std::holds_alternative<hook_api::hook_return_code>(return_code) && \
(std::get<hook_api::hook_return_code>(return_code) == \
RC_ROLLBACK || \
std::get<hook_api::hook_return_code>(return_code) == RC_ACCEPT)) \
return WasmEdge_Result_Terminate; \
out[0] = RET_ASSIGN( \
R, \
std::holds_alternative<UNSIGNED_TYPE(R)>(return_code) \
? std::get<UNSIGNED_TYPE(R)>(return_code) \
: R(std::get<hook_api::hook_return_code>(return_code))); \
return WasmEdge_Result_Success; \
}; \
WasmEdge_ValType hook_api::WasmFunctionParams##F[] = { \
__VA_OPT__(FOR_VARS(WASM_VAL_TYPE, 0, __VA_ARGS__))}; \
WasmEdge_ValType hook_api::WasmFunctionResult##F[1] = { \
WASM_VAL_TYPE(R, dummy)}; \
WasmEdge_FunctionTypeContext* hook_api::WasmFunctionType##F = \
WasmEdge_FunctionTypeCreate( \
WasmFunctionParams##F, \
VA_NARGS(NULL __VA_OPT__(, __VA_ARGS__)), \
WasmFunctionResult##F, \
1); \
WasmEdge_String hook_api::WasmFunctionName##F = \
WasmEdge_StringCreateByCString(#F); \
std::variant<UNSIGNED_TYPE(R), hook_api::hook_return_code> hook_api::F( \
hook::HookContext& hookCtx, \
WasmEdge_CallingFrameContext const& frameCtx __VA_OPT__( \
#define DEFINE_HOOK_FUNCTION(R, F, ...) \
WasmEdge_Result hook_api::WasmFunction##F( \
void* data_ptr, \
const WasmEdge_CallingFrameContext* frameCtx, \
const WasmEdge_Value* in, \
WasmEdge_Value* out) \
{ \
__VA_OPT__(int _stack = 0;) \
__VA_OPT__(FOR_VARS(VAR_ASSIGN, 2, __VA_ARGS__);) \
hook::HookContext* hookCtx = \
reinterpret_cast<hook::HookContext*>(data_ptr); \
R return_code = hook_api::F( \
*hookCtx, \
*const_cast<WasmEdge_CallingFrameContext*>(frameCtx) \
__VA_OPT__(COMMA STRIP_TYPES(__VA_ARGS__))); \
if (return_code == RC_ROLLBACK || return_code == RC_ACCEPT) \
return WasmEdge_Result_Terminate; \
out[0] = RET_ASSIGN(R, return_code); \
return WasmEdge_Result_Success; \
}; \
WasmEdge_ValType hook_api::WasmFunctionParams##F[] = { \
__VA_OPT__(FOR_VARS(WASM_VAL_TYPE, 0, __VA_ARGS__))}; \
WasmEdge_ValType hook_api::WasmFunctionResult##F[1] = { \
WASM_VAL_TYPE(R, dummy)}; \
WasmEdge_FunctionTypeContext* hook_api::WasmFunctionType##F = \
WasmEdge_FunctionTypeCreate( \
WasmFunctionParams##F, \
VA_NARGS(NULL __VA_OPT__(, __VA_ARGS__)), \
WasmFunctionResult##F, \
1); \
WasmEdge_String hook_api::WasmFunctionName##F = \
WasmEdge_StringCreateByCString(#F); \
R hook_api::F( \
hook::HookContext& hookCtx, \
WasmEdge_CallingFrameContext const& frameCtx __VA_OPT__( \
COMMA __VA_ARGS__))
#define HOOK_SETUP() \
using enum hook_api::hook_return_code; \
try \
{ \
[[maybe_unused]] ApplyContext& applyCtx = hookCtx.applyCtx; \
@@ -214,7 +203,7 @@
host_memory_ptr, \
guest_memory_length) \
{ \
uint64_t bytes_written = 0; \
int64_t bytes_written = 0; \
WRITE_WASM_MEMORY( \
bytes_written, \
guest_dst_ptr, \
@@ -244,13 +233,7 @@
<< "Tried to accept/rollback but specified " \
"memory outside of the wasm instance " \
<< "limit when specifying a reason string"; \
if (!view.rules().enabled(fix20260929)) \
return OUT_OF_BOUNDS; \
/* fix20260929: terminate as a rollback so the \
failure is visible in HookExecution metadata */ \
hookCtx.result.exitType = hook_api::ExitType::ROLLBACK; \
hookCtx.result.exitCode = (int64_t)OUT_OF_BOUNDS; \
return RC_ROLLBACK; \
return OUT_OF_BOUNDS; \
} \
/* assembly script and some other languages use utf16 for strings \
*/ \
@@ -289,7 +272,7 @@
data_ptr < (data_ptr_in)) \
return INTERNAL_ERROR; \
if (data_len == 0) \
return 0ULL; \
return 0; \
if ((write_ptr_in) == 0) \
return data_as_int64(data_ptr, data_len); \
if (data_len > (write_len_in)) \
+516 -24
View File
@@ -1,31 +1,523 @@
#ifndef HOOKMISC_INCLUDED
#define HOOKMISC_INCLUDED 1
#include <xrpl/basics/base_uint.h>
#include <array>
#include <cstdint>
namespace ripple {
// RH TODO: there's definitely a mucher nicer way to do this, but it involves
// modifying the base_uint class and we don't want to do that yet.
/** UINT256_BIT[i] is the 256-bit value with only bit i set (LSB is bit 0).
Used to encode and test the per-transaction-type bits of the HookOn and
HookCanEmit fields. Built at compile time.
*/
inline constexpr auto UINT256_BIT = []() consteval {
std::array<ripple::uint256, 256> table{};
for (int i = 0; i < 256; ++i)
{
std::array<std::uint8_t, 32> bytes{};
bytes[31 - (i / 8)] = 1 << (i % 8);
table[i] = ripple::uint256(bytes);
}
return table;
}();
static const std::array<ripple::uint256, 256> UINT256_BIT = {
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000000001"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000000002"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000000004"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000000008"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000000010"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000000020"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000000040"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000000080"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000000100"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000000200"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000000400"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000000800"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000001000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000002000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000004000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000008000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000010000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000020000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000040000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000080000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000100000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000200000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000400000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000000800000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000001000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000002000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000004000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000008000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000010000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000020000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000040000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000080000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000100000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000200000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000400000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000000800000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000001000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000002000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000004000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000008000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000010000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000020000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000040000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000080000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000100000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000200000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000400000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000000800000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000001000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000002000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000004000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000008000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000010000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000020000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000040000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000080000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000100000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000200000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000400000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000000800000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000001000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000002000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000004000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000008000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000010000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000020000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000040000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000080000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000100000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000200000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000400000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000000800000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000001000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000002000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000004000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000008000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000010000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000020000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000040000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000080000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000100000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000200000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000400000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000000800000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000001000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000002000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000004000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000008000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000010000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000020000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000040000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000080000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000100000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000200000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000400000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000000800000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000001000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000002000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000004000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000008000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000010000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000020000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000040000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000080000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000100000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000200000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000400000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000000800000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000001000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000002000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000004000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000008000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000010000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000020000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000040000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000080000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000100000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000200000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000400000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000000800000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000001000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000002000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000004000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000008000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000010000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000020000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000040000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000080000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000100000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000200000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000400000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000000800000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000001000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000002000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000004000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000008000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000010000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000020000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000040000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000080000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000100000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000200000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000400000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000000800000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000001000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000002000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000004000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000008000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000010000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000020000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000040000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000080000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000100000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000200000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000400000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000000800000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000001000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000002000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000004000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000008000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000010000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000020000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000040000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000080000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000100000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000200000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000400000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000000800000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000001000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000002000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000004000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000008000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000010000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000020000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000040000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000080000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000100000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000200000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000400000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000000800000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000001000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000002000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000004000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000008000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000010000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000020000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000040000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000080000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000100000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000200000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000400000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000000800000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000001000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000002000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000004000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000008000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000010000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000020000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000040000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000080000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000100000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000200000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000400000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000000800000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000001000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000002000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000004000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000008000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000010000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000020000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000040000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000080000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000100000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000200000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000400000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000000800000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000001000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000002000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000004000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000008000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000010000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000020000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000040000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000080000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000100000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000200000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000400000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000000800000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000001000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000002000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000004000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000008000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000010000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000020000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000040000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000080000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000100000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000200000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000400000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0000800000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0001000000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0002000000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0004000000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0008000000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0010000000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0020000000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0040000000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0080000000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0100000000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0200000000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0400000000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"0800000000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"1000000000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"2000000000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"4000000000000000000000000000000000000000000000000000000000000000"),
ripple::uint256(
"8000000000000000000000000000000000000000000000000000000000000000")};
} // namespace ripple
#endif
+139 -74
View File
@@ -1,309 +1,374 @@
// clang-format off
// int32_t _g(uint32_t guard_id, uint32_t maxiter);
HOOK_API_DEFINITION(
int32_t, _g, (uint32_t guard_id, uint32_t maxiter),
int32_t, _g, (uint32_t, uint32_t),
uint256{})
// int64_t accept(uint32_t read_ptr, uint32_t read_len, int64_t error_code);
HOOK_API_DEFINITION(
int64_t, accept, (uint32_t read_ptr, uint32_t read_len, int64_t error_code),
int64_t, accept, (uint32_t, uint32_t, int64_t),
uint256{})
// int64_t rollback(uint32_t read_ptr, uint32_t read_len, int64_t error_code);
HOOK_API_DEFINITION(
int64_t, rollback, (uint32_t read_ptr, uint32_t read_len, int64_t error_code),
int64_t, rollback, (uint32_t, uint32_t, int64_t),
uint256{})
// int64_t util_raddr(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
HOOK_API_DEFINITION(
int64_t, util_raddr, (uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len),
int64_t, util_raddr, (uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t util_accid(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
HOOK_API_DEFINITION(
int64_t, util_accid, (uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len),
int64_t, util_accid, (uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t util_verify(uint32_t dread_ptr, uint32_t dread_len, uint32_t sread_ptr, uint32_t sread_len, uint32_t kread_ptr, uint32_t kread_len);
HOOK_API_DEFINITION(
int64_t, util_verify, (uint32_t dread_ptr, uint32_t dread_len, uint32_t sread_ptr, uint32_t sread_len, uint32_t kread_ptr, uint32_t kread_len),
int64_t, util_verify, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t util_sha512h(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
HOOK_API_DEFINITION(
int64_t, util_sha512h, (uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len),
int64_t, util_sha512h, (uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t util_keylet(uint32_t write_ptr, uint32_t write_len, uint32_t keylet_type, uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f);
HOOK_API_DEFINITION(
int64_t, util_keylet, (uint32_t write_ptr, uint32_t write_len, uint32_t keylet_type, uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f),
int64_t, util_keylet, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t sto_validate(uint32_t tread_ptr, uint32_t tread_len);
HOOK_API_DEFINITION(
int64_t, sto_validate, (uint32_t tread_ptr, uint32_t tread_len),
int64_t, sto_validate, (uint32_t, uint32_t),
uint256{})
// int64_t sto_subfield(uint32_t read_ptr, uint32_t read_len, uint32_t field_id);
HOOK_API_DEFINITION(
int64_t, sto_subfield, (uint32_t read_ptr, uint32_t read_len, uint32_t field_id),
int64_t, sto_subfield, (uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t sto_subarray(uint32_t read_ptr, uint32_t read_len, uint32_t array_id);
HOOK_API_DEFINITION(
int64_t, sto_subarray, (uint32_t read_ptr, uint32_t read_len, uint32_t array_id),
int64_t, sto_subarray, (uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t sto_emplace(uint32_t write_ptr, uint32_t write_len, uint32_t sread_ptr, uint32_t sread_len, uint32_t fread_ptr, uint32_t fread_len, uint32_t field_id);
HOOK_API_DEFINITION(
int64_t, sto_emplace, (uint32_t write_ptr, uint32_t write_len, uint32_t sread_ptr, uint32_t sread_len, uint32_t fread_ptr, uint32_t fread_len, uint32_t field_id),
int64_t, sto_emplace, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t sto_erase(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len, uint32_t field_id);
HOOK_API_DEFINITION(
int64_t, sto_erase, (uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len, uint32_t field_id),
int64_t, sto_erase, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t etxn_burden();
HOOK_API_DEFINITION(
int64_t, etxn_burden, (),
uint256{})
// int64_t etxn_details(uint32_t write_ptr, uint32_t write_len);
HOOK_API_DEFINITION(
int64_t, etxn_details, (uint32_t write_ptr, uint32_t write_len),
int64_t, etxn_details, (uint32_t, uint32_t),
uint256{})
// int64_t etxn_fee_base(uint32_t read_ptr, uint32_t read_len);
HOOK_API_DEFINITION(
int64_t, etxn_fee_base, (uint32_t read_ptr, uint32_t read_len),
int64_t, etxn_fee_base, (uint32_t, uint32_t),
uint256{})
// int64_t etxn_reserve(uint32_t count);
HOOK_API_DEFINITION(
int64_t, etxn_reserve, (uint32_t count),
int64_t, etxn_reserve, (uint32_t),
uint256{})
// int64_t etxn_generation();
HOOK_API_DEFINITION(
int64_t, etxn_generation, (),
uint256{})
// int64_t etxn_nonce(uint32_t write_ptr, uint32_t write_len);
HOOK_API_DEFINITION(
int64_t, etxn_nonce, (uint32_t write_ptr, uint32_t write_len),
int64_t, etxn_nonce, (uint32_t, uint32_t),
uint256{})
// int64_t emit(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
HOOK_API_DEFINITION(
int64_t, emit, (uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len),
int64_t, emit, (uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t float_set(int32_t exponent, int64_t mantissa);
HOOK_API_DEFINITION(
int64_t, float_set, (int32_t exponent, int64_t mantissa),
int64_t, float_set, (int32_t, int64_t),
uint256{})
// int64_t float_multiply(int64_t float1, int64_t float2);
HOOK_API_DEFINITION(
int64_t, float_multiply, (int64_t float1, int64_t float2),
int64_t, float_multiply, (int64_t, int64_t),
uint256{})
// int64_t float_mulratio(int64_t float1, uint32_t round_up, uint32_t numerator, uint32_t denominator);
HOOK_API_DEFINITION(
int64_t, float_mulratio, (int64_t float1, uint32_t round_up, uint32_t numerator, uint32_t denominator),
int64_t, float_mulratio, (int64_t, uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t float_negate(int64_t float1);
HOOK_API_DEFINITION(
int64_t, float_negate, (int64_t float1),
int64_t, float_negate, (int64_t),
uint256{})
// int64_t float_compare(int64_t float1, int64_t float2, uint32_t mode);
HOOK_API_DEFINITION(
int64_t, float_compare, (int64_t float1, int64_t float2, uint32_t mode),
int64_t, float_compare, (int64_t, int64_t, uint32_t),
uint256{})
// int64_t float_sum(int64_t float1, int64_t float2);
HOOK_API_DEFINITION(
int64_t, float_sum, (int64_t float1, int64_t float2),
int64_t, float_sum, (int64_t, int64_t),
uint256{})
// int64_t float_sto(uint32_t write_ptr, uint32_t write_len, uint32_t cread_ptr, uint32_t cread_len, uint32_t iread_ptr, uint32_t iread_len, int64_t float1, uint32_t field_code);
HOOK_API_DEFINITION(
int64_t, float_sto, (uint32_t write_ptr, uint32_t write_len, uint32_t cread_ptr, uint32_t cread_len, uint32_t iread_ptr, uint32_t iread_len, int64_t float1, uint32_t field_code),
int64_t, float_sto, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, int64_t, uint32_t),
uint256{})
// int64_t float_sto_set(uint32_t read_ptr, uint32_t read_len);
HOOK_API_DEFINITION(
int64_t, float_sto_set, (uint32_t read_ptr, uint32_t read_len),
int64_t, float_sto_set, (uint32_t, uint32_t),
uint256{})
// int64_t float_invert(int64_t float1);
HOOK_API_DEFINITION(
int64_t, float_invert, (int64_t float1),
int64_t, float_invert, (int64_t),
uint256{})
// int64_t float_divide(int64_t float1, int64_t float2);
HOOK_API_DEFINITION(
int64_t, float_divide, (int64_t float1, int64_t float2),
int64_t, float_divide, (int64_t, int64_t),
uint256{})
// int64_t float_one();
HOOK_API_DEFINITION(
int64_t, float_one, (),
uint256{})
// int64_t float_mantissa(int64_t float1);
HOOK_API_DEFINITION(
int64_t, float_mantissa, (int64_t float1),
int64_t, float_mantissa, (int64_t),
uint256{})
// int64_t float_sign(int64_t float1);
HOOK_API_DEFINITION(
int64_t, float_sign, (int64_t float1),
int64_t, float_sign, (int64_t),
uint256{})
// int64_t float_int(int64_t float1, uint32_t decimal_places, uint32_t abs);
HOOK_API_DEFINITION(
int64_t, float_int, (int64_t float1, uint32_t decimal_places, uint32_t abs),
int64_t, float_int, (int64_t, uint32_t, uint32_t),
uint256{})
// int64_t float_log(int64_t float1);
HOOK_API_DEFINITION(
int64_t, float_log, (int64_t float1),
int64_t, float_log, (int64_t),
uint256{})
// int64_t float_root(int64_t float1, uint32_t n);
HOOK_API_DEFINITION(
int64_t, float_root, (int64_t float1, uint32_t n),
int64_t, float_root, (int64_t, uint32_t),
uint256{})
// int64_t fee_base();
HOOK_API_DEFINITION(
int64_t, fee_base, (),
uint256{})
// int64_t ledger_seq();
HOOK_API_DEFINITION(
int64_t, ledger_seq, (),
uint256{})
// int64_t ledger_last_time();
HOOK_API_DEFINITION(
int64_t, ledger_last_time, (),
uint256{})
// int64_t ledger_last_hash(uint32_t write_ptr, uint32_t write_len);
HOOK_API_DEFINITION(
int64_t, ledger_last_hash, (uint32_t write_ptr, uint32_t write_len),
int64_t, ledger_last_hash, (uint32_t, uint32_t),
uint256{})
// int64_t ledger_nonce(uint32_t write_ptr, uint32_t write_len);
HOOK_API_DEFINITION(
int64_t, ledger_nonce, (uint32_t write_ptr, uint32_t write_len),
int64_t, ledger_nonce, (uint32_t, uint32_t),
uint256{})
// int64_t ledger_keylet(uint32_t write_ptr, uint32_t write_len, uint32_t lread_ptr, uint32_t lread_len, uint32_t hread_ptr, uint32_t hread_len);
HOOK_API_DEFINITION(
int64_t, ledger_keylet, (uint32_t write_ptr, uint32_t write_len, uint32_t lread_ptr, uint32_t lread_len, uint32_t hread_ptr, uint32_t hread_len),
int64_t, ledger_keylet, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t hook_account(uint32_t write_ptr, uint32_t write_len);
HOOK_API_DEFINITION(
int64_t, hook_account, (uint32_t write_ptr, uint32_t write_len),
int64_t, hook_account, (uint32_t, uint32_t),
uint256{})
// int64_t hook_hash(uint32_t write_ptr, uint32_t write_len, int32_t hook_no);
HOOK_API_DEFINITION(
int64_t, hook_hash, (uint32_t write_ptr, uint32_t write_len, int32_t hook_no),
int64_t, hook_hash, (uint32_t, uint32_t, int32_t),
uint256{})
// int64_t hook_param_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t hread_ptr, uint32_t hread_len);
HOOK_API_DEFINITION(
int64_t, hook_param_set, (uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t hread_ptr, uint32_t hread_len),
int64_t, hook_param_set, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t hook_param(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
HOOK_API_DEFINITION(
int64_t, hook_param, (uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len),
int64_t, hook_param, (uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t hook_again();
HOOK_API_DEFINITION(
int64_t, hook_again, (),
uint256{})
// int64_t hook_skip(uint32_t read_ptr, uint32_t read_len, uint32_t flags);
HOOK_API_DEFINITION(
int64_t, hook_skip, (uint32_t read_ptr, uint32_t read_len, uint32_t flags),
int64_t, hook_skip, (uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t hook_pos();
HOOK_API_DEFINITION(
int64_t, hook_pos, (),
uint256{})
// int64_t slot(uint32_t write_ptr, uint32_t write_len, uint32_t slot);
HOOK_API_DEFINITION(
int64_t, slot, (uint32_t write_ptr, uint32_t write_len, uint32_t slot),
int64_t, slot, (uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t slot_clear(uint32_t slot);
HOOK_API_DEFINITION(
int64_t, slot_clear, (uint32_t slot),
int64_t, slot_clear, (uint32_t),
uint256{})
// int64_t slot_count(uint32_t slot);
HOOK_API_DEFINITION(
int64_t, slot_count, (uint32_t slot),
int64_t, slot_count, (uint32_t),
uint256{})
// int64_t slot_set(uint32_t read_ptr, uint32_t read_len, uint32_t slot);
HOOK_API_DEFINITION(
int64_t, slot_set, (uint32_t read_ptr, uint32_t read_len, uint32_t slot),
int64_t, slot_set, (uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t slot_size(uint32_t slot);
HOOK_API_DEFINITION(
int64_t, slot_size, (uint32_t slot),
int64_t, slot_size, (uint32_t),
uint256{})
// int64_t slot_subarray(uint32_t parent_slot, uint32_t array_id, uint32_t new_slot);
HOOK_API_DEFINITION(
int64_t, slot_subarray, (uint32_t parent_slot, uint32_t array_id, uint32_t new_slot),
int64_t, slot_subarray, (uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t slot_subfield(uint32_t parent_slot, uint32_t field_id, uint32_t new_slot);
HOOK_API_DEFINITION(
int64_t, slot_subfield, (uint32_t parent_slot, uint32_t field_id, uint32_t new_slot),
int64_t, slot_subfield, (uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t slot_type(uint32_t slot_no, uint32_t flags);
HOOK_API_DEFINITION(
int64_t, slot_type, (uint32_t slot_no, uint32_t flags),
int64_t, slot_type, (uint32_t, uint32_t),
uint256{})
// int64_t slot_float(uint32_t slot_no);
HOOK_API_DEFINITION(
int64_t, slot_float, (uint32_t slot_no),
int64_t, slot_float, (uint32_t),
uint256{})
// int64_t state_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len);
HOOK_API_DEFINITION(
int64_t, state_set, (uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len),
int64_t, state_set, (uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t state_foreign_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t nread_ptr, uint32_t nread_len, uint32_t aread_ptr, uint32_t aread_len);
HOOK_API_DEFINITION(
int64_t, state_foreign_set, (uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t nread_ptr, uint32_t nread_len, uint32_t aread_ptr, uint32_t aread_len),
int64_t, state_foreign_set, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t state(uint32_t write_ptr, uint32_t write_len, uint32_t kread_ptr, uint32_t kread_len);
HOOK_API_DEFINITION(
int64_t, state, (uint32_t write_ptr, uint32_t write_len, uint32_t kread_ptr, uint32_t kread_len),
int64_t, state, (uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t state_foreign(uint32_t write_ptr, uint32_t write_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t nread_ptr, uint32_t nread_len, uint32_t aread_ptr, uint32_t aread_len);
HOOK_API_DEFINITION(
int64_t, state_foreign, (uint32_t write_ptr, uint32_t write_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t nread_ptr, uint32_t nread_len, uint32_t aread_ptr, uint32_t aread_len),
int64_t, state_foreign, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t trace(uint32_t mread_ptr, uint32_t mread_len, uint32_t dread_ptr, uint32_t dread_len, uint32_t as_hex);
HOOK_API_DEFINITION(
int64_t, trace, (uint32_t mread_ptr, uint32_t mread_len, uint32_t dread_ptr, uint32_t dread_len, uint32_t as_hex),
int64_t, trace, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t trace_num(uint32_t read_ptr, uint32_t read_len, int64_t number);
HOOK_API_DEFINITION(
int64_t, trace_num, (uint32_t read_ptr, uint32_t read_len, int64_t number),
int64_t, trace_num, (uint32_t, uint32_t, int64_t),
uint256{})
// int64_t trace_float(uint32_t read_ptr, uint32_t read_len, int64_t float1);
HOOK_API_DEFINITION(
int64_t, trace_float, (uint32_t read_ptr, uint32_t read_len, int64_t float1),
int64_t, trace_float, (uint32_t, uint32_t, int64_t),
uint256{})
// int64_t otxn_burden();
HOOK_API_DEFINITION(
int64_t, otxn_burden, (),
uint256{})
// int64_t otxn_field(uint32_t write_ptr, uint32_t write_len, uint32_t field_id);
HOOK_API_DEFINITION(
int64_t, otxn_field, (uint32_t write_ptr, uint32_t write_len, uint32_t field_id),
int64_t, otxn_field, (uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t otxn_generation();
HOOK_API_DEFINITION(
int64_t, otxn_generation, (),
uint256{})
// int64_t otxn_id(uint32_t write_ptr, uint32_t write_len, uint32_t flags);
HOOK_API_DEFINITION(
int64_t, otxn_id, (uint32_t write_ptr, uint32_t write_len, uint32_t flags),
int64_t, otxn_id, (uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t otxn_type();
HOOK_API_DEFINITION(
int64_t, otxn_type, (),
uint256{})
// int64_t otxn_slot(uint32_t slot_no);
HOOK_API_DEFINITION(
int64_t, otxn_slot, (uint32_t slot_no),
int64_t, otxn_slot, (uint32_t),
uint256{})
// int64_t otxn_param(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
HOOK_API_DEFINITION(
int64_t, otxn_param, (uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len),
int64_t, otxn_param, (uint32_t, uint32_t, uint32_t, uint32_t),
uint256{})
// int64_t meta_slot(uint32_t slot_no);
HOOK_API_DEFINITION(
int64_t, meta_slot, (uint32_t slot_no),
int64_t, meta_slot, (uint32_t),
uint256{})
// int64_t xpop_slot(uint32_t slot_no_tx, uint32_t slot_no_meta);
HOOK_API_DEFINITION(
int64_t, xpop_slot, (uint32_t slot_no_tx, uint32_t slot_no_meta),
int64_t, xpop_slot, (uint32_t, uint32_t),
featureHooksUpdate1)
// int64_t prepare(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
HOOK_API_DEFINITION(
int64_t, prepare, (uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len),
int64_t, prepare, (uint32_t, uint32_t, uint32_t, uint32_t),
featureHooksUpdate2)
HOOK_API_DEFINITION(
int64_t, dice, (uint32_t sides),
featureRNG)
HOOK_API_DEFINITION(
int64_t, util_random, (uint32_t write_ptr, uint32_t write_len),
featureRNG)
// clang-format on
+731 -737
View File
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -215,7 +215,7 @@ Reader::parse(Value& root, BufferSequence const& bs)
std::string s;
s.reserve(buffer_size(bs));
for (auto const& b : bs)
s.append(static_cast<char const*>(b.data()), buffer_size(b));
s.append(buffer_cast<char const*>(b), buffer_size(b));
return parse(s, root);
}
-66
View File
@@ -1,66 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2025 XRPL Labs
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_PROTOCOL_APPLOADER_H_INCLUDED
#define RIPPLE_PROTOCOL_APPLOADER_H_INCLUDED
#include <cstddef>
#include <cstdint>
namespace ripple {
/** Validation of an AppLoader document (sfAppLoader), the bootstrap page of
a Progressive Web App served from an account.
Consensus cannot afford a real HTML parser, so this is a shallow sanity
gate and nothing more. A document must be non-empty and at most
maxAppLoaderLength bytes; well-formed UTF-8; free of C0 control
characters other than TAB, LF, FF and CR, and of DEL; begin, after an
optional BOM and whitespace, with an HTML doctype or an <html start tag;
and contain an <html start tag followed later by a </html> end tag with
nothing but whitespace after the last one. Nothing parses comments,
scripts or attributes, and content is not policed.
Consensus critical: a change to what it accepts needs an amendment.
*/
namespace appLoader {
enum class Result : std::uint8_t {
ok = 0,
empty,
tooLarge,
badUTF8,
badControlChar,
noDoctype, // does not open with a doctype or <html tag
noHtmlElement, // no <html start tag
unclosed, // no </html> end tag after it
trailingGarbage, // non-whitespace after the last </html>
};
/** Total: every input yields a result. `data` may be null iff size is 0. */
Result
validate(std::uint8_t const* data, std::size_t size);
char const*
to_string(Result r);
} // namespace appLoader
} // namespace ripple
#endif
+1 -6
View File
@@ -157,12 +157,7 @@ enum error_code_i {
// Simulate
rpcTX_SIGNED = 97,
// ledger_entry
rpcENTRY_NOT_FOUND = 98,
rpcUNEXPECTED_LEDGER_TYPE = 99,
rpcLAST =
rpcUNEXPECTED_LEDGER_TYPE // rpcLAST should always equal the last code.
rpcLAST = rpcTX_SIGNED // rpcLAST should always equal the last code.
};
/** Codes returned in the `warnings` array of certain RPC commands.
+26 -56
View File
@@ -33,39 +33,35 @@
*
* Steps required to add new features to the code:
*
* 1) Add the appropriate XRPL_FEATURE or XRPL_FIX macro definition for the
* feature to features.macro with the feature's name, `Supported::no`, and
* `VoteBehavior::DefaultNo`.
*
* 2) Use the generated variable name as the parameter to `view.rules.enabled()`
* to control flow into new code that this feature limits. (featureName or
* fixName)
*
* 3) If the feature development is COMPLETE, and the feature is ready to be
* SUPPORTED, change the macro parameter in features.macro to Supported::yes.
*
* 4) In general, any newly supported amendments (`Supported::yes`) should have
* a `VoteBehavior::DefaultNo` indefinitely so that external governance can
* make the decision on when to activate it. High priority bug fixes can be
* an exception to this rule. In such cases, ensure the fix has been
* clearly communicated to the community using appropriate channels,
* then change the macro parameter in features.macro to
* `VoteBehavior::DefaultYes`. The communication process is beyond
* the scope of these instructions.
*
* 1) In this file, increment `numFeatures` and add a uint256 declaration
* for the feature at the bottom
* 2) Add a uint256 definition for the feature to the corresponding source
* file (Feature.cpp). Use `registerFeature` to create the feature with
* the feature's name, `Supported::no`, and `VoteBehavior::DefaultNo`. This
* should be the only place the feature's name appears in code as a string.
* 3) Use the uint256 as the parameter to `view.rules.enabled()` to
* control flow into new code that this feature limits.
* 4) If the feature development is COMPLETE, and the feature is ready to be
* SUPPORTED, change the `registerFeature` parameter to Supported::yes.
* 5) When the feature is ready to be ENABLED, change the `registerFeature`
* parameter to `VoteBehavior::DefaultYes`.
* In general, any newly supported amendments (`Supported::yes`) should have
* a `VoteBehavior::DefaultNo` for at least one full release cycle. High
* priority bug fixes can be an exception to this rule of thumb.
*
* When a feature has been enabled for several years, the conditional code
* may be removed, and the feature "retired". To retire a feature:
*
* 1) MOVE the macro definition in features.macro to the "retired features"
* section at the end of the file, and change the macro to XRPL_RETIRE.
*
* 1) Remove the uint256 declaration from this file.
* 2) MOVE the uint256 definition in Feature.cpp to the "retired features"
* section at the end of the file.
* 3) CHANGE the name of the variable to start with "retired".
* 4) CHANGE the parameters of the `registerFeature` call to `Supported::yes`
* and `VoteBehavior::DefaultNo`.
* The feature must remain registered and supported indefinitely because it
* may exist in the Amendments object on ledger. There is no need to vote
* for it because there's nothing to vote for. If the feature definition is
* removed completely from the code, any instances running that code will get
* amendment blocked. Removing the feature from the ledger is beyond the scope
* of these instructions.
* still exists in the ledger, but there is no need to vote for it because
* there's nothing to vote for. If it is removed completely from the code, any
* instances running that code will get amendment blocked. Removing the
* feature from the ledger is beyond the scope of these instructions.
*
*/
@@ -80,32 +76,11 @@ allAmendments();
namespace detail {
#pragma push_macro("XRPL_FEATURE")
#undef XRPL_FEATURE
#pragma push_macro("XRPL_FIX")
#undef XRPL_FIX
#pragma push_macro("XRPL_RETIRE")
#undef XRPL_RETIRE
#define XRPL_FEATURE(name, supported, vote) +1
#define XRPL_FIX(name, supported, vote) +1
#define XRPL_RETIRE(name) +1
// This value SHOULD be equal to the number of amendments registered in
// Feature.cpp. Because it's only used to reserve storage, and determine how
// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
// the actual number of amendments. A LogicError on startup will verify this.
static constexpr std::size_t numFeatures =
(0 +
#include <xrpl/protocol/detail/features.macro>
);
#undef XRPL_RETIRE
#pragma pop_macro("XRPL_RETIRE")
#undef XRPL_FIX
#pragma pop_macro("XRPL_FIX")
#undef XRPL_FEATURE
#pragma pop_macro("XRPL_FEATURE")
static constexpr std::size_t numFeatures = 113;
/** Amendments that this server supports and the default voting behavior.
Whether they are enabled depends on the Rules defined in the validated
@@ -345,17 +320,12 @@ foreachFeature(FeatureBitset bs, F&& f)
#undef XRPL_FEATURE
#pragma push_macro("XRPL_FIX")
#undef XRPL_FIX
#pragma push_macro("XRPL_RETIRE")
#undef XRPL_RETIRE
#define XRPL_FEATURE(name, supported, vote) extern uint256 const feature##name;
#define XRPL_FIX(name, supported, vote) extern uint256 const fix##name;
#define XRPL_RETIRE(name)
#include <xrpl/protocol/detail/features.macro>
#undef XRPL_RETIRE
#pragma pop_macro("XRPL_RETIRE")
#undef XRPL_FIX
#pragma pop_macro("XRPL_FIX")
#undef XRPL_FEATURE
+4 -49
View File
@@ -24,7 +24,6 @@
#include <xrpl/basics/Log.h>
#include <xrpl/basics/StringUtilities.h>
#include <xrpl/basics/base64.h>
#include <xrpl/basics/chrono.h>
#include <xrpl/json/json_reader.h>
#include <charconv>
@@ -119,9 +118,8 @@ syntaxCheckProof(
{
if (!proof["hash"].isString() ||
proof["hash"].asString().size() != 64 ||
!isHex(proof["hash"].asString()) || !proof["key"].isString() ||
!proof["key"].isString() ||
proof["key"].asString().size() != 64 ||
!isHex(proof["key"].asString()) ||
!proof["children"].isObject())
{
JLOG(j.warn()) << "XPOP.transaction.proof tree node has wrong "
@@ -134,11 +132,7 @@ syntaxCheckProof(
for (const auto& branch : proof.getMemberNames())
{
// Upper case only: the txroot computation only looks up "0"-"F",
// so any other key would be silently ignored.
if (branch.size() != 1 ||
branch.find_first_not_of("0123456789ABCDEF") !=
std::string::npos)
if (branch.size() != 1 || !isHex(branch))
{
JLOG(j.warn())
<< "XPOP.transaction.proof child node was not 0-F "
@@ -149,9 +143,9 @@ syntaxCheckProof(
const auto& node = proof[branch];
if (!node.isObject() || !node["hash"].isString() ||
node["hash"].asString().size() != 64 ||
!isHex(node["hash"].asString()) || !node["key"].isString() ||
!node["key"].isString() ||
node["key"].asString().size() != 64 ||
!isHex(node["key"].asString()) || !node["children"].isObject())
!node["children"].isObject())
{
JLOG(j.warn())
<< "XPOP.transaction.proof tree node has wrong format";
@@ -471,45 +465,6 @@ getVLInfo(Json::Value const& xpop, beast::Journal const& j)
return {{sequence, m->masterKey}};
}
// <effective, expiration> of the unl blob, effective defaulting to the epoch
inline std::optional<std::pair<NetClock::time_point, NetClock::time_point>>
getVLWindow(Json::Value const& xpop, beast::Journal const& j)
{
auto const data =
base64_decode(xpop[jss::validation][jss::unl][jss::blob].asString());
Json::Reader r;
Json::Value parsed;
if (!r.parse(data, parsed) || !parsed.isObject())
{
JLOG(j.warn()) << "Import: unl blob was not a json object (after "
"base64 decoding)";
return {};
}
// const, so that operator[] does not insert missing members
Json::Value const& list = parsed;
auto const time = [&list](Json::StaticString const& field)
-> std::optional<NetClock::time_point> {
auto const& v = list[field];
if (!v.isInt() || v.asInt() < 0)
return {};
return NetClock::time_point{NetClock::duration{v.asUInt()}};
};
auto const validUntil = time(jss::expiration);
auto const validFrom = list.isMember(jss::effective)
? time(jss::effective)
: std::optional<NetClock::time_point>{NetClock::time_point{}};
if (!validUntil || !validFrom)
{
JLOG(j.warn()) << "Import: unl blob json (after base64 decoding) "
"had missing or invalid effective/expiration";
return {};
}
return {{*validFrom, *validUntil}};
}
} // namespace ripple
#endif
+2 -29
View File
@@ -118,10 +118,6 @@ negativeUNL() noexcept;
Keylet const&
UNLReport() noexcept;
/** The (fixed) index of the featureRNG random number generator object. */
Keylet const&
random() noexcept;
/** The beginning of an order book */
struct book_t
{
@@ -332,14 +328,6 @@ xChainCreateAccountClaimID(STXChainBridge const& bridge, std::uint64_t seq);
Keylet
did(AccountID const& account) noexcept;
/** An AppLoader belonging to an account.
There is at most one per account, so the key is derived from the owner's
AccountID alone.
*/
Keylet
appLoader(AccountID const& account) noexcept;
Keylet
oracle(AccountID const& account, std::uint32_t const& documentID) noexcept;
@@ -384,20 +372,6 @@ permissionedDomain(AccountID const& account, std::uint32_t seq) noexcept;
Keylet
permissionedDomain(uint256 const& domainID) noexcept;
Keylet
manifest(PublicKey const& pk) noexcept;
/** The directory listing every master key's ltMANIFEST object.
One entry per master key, made when its first manifest is published and
kept for good: a newer manifest, a revocation included, replaces the object
at the same key and keeps its place. The copy at the ephemeral key is not
listed; it is named by the master object.
*/
Keylet const&
manifestDir() noexcept;
} // namespace keylet
// Everything below is deprecated and should be removed in favor of keylets:
@@ -428,7 +402,7 @@ struct keyletDesc
// This list should include all of the keylet functions that take a single
// AccountID parameter.
std::array<keyletDesc<AccountID const&>, 7> const directAccountKeylets{
std::array<keyletDesc<AccountID const&>, 6> const directAccountKeylets{
{{&keylet::account, jss::AccountRoot, false},
{&keylet::ownerDir, jss::DirectoryNode, true},
{&keylet::signers, jss::SignerList, true},
@@ -436,8 +410,7 @@ std::array<keyletDesc<AccountID const&>, 7> const directAccountKeylets{
// test it anyway, since the invariant checks for it.
{&keylet::nftpage_min, jss::NFTokenPage, true},
{&keylet::nftpage_max, jss::NFTokenPage, true},
{&keylet::did, jss::DID, true},
{&keylet::appLoader, jss::AppLoader, true}}};
{&keylet::did, jss::DID, true}}};
MPTID
makeMptID(std::uint32_t sequence, AccountID const& account);
-22
View File
@@ -84,9 +84,6 @@ std::uint16_t constexpr maxTransferFee = 50000;
/** The maximum length of a URI inside an NFT */
std::size_t constexpr maxTokenURILength = 256;
/** The maximum length of a URI inside an URIToken */
std::size_t constexpr maxURITokenURILength = 256;
/** The maximum length of a Data element inside a DID */
std::size_t constexpr maxDIDDocumentLength = 256;
@@ -99,25 +96,6 @@ std::size_t constexpr maxDIDAttestationLength = 256;
/** The maximum length of a domain */
std::size_t constexpr maxDomainLength = 256;
/** The maximum length of an AppLoader document.
The AppLoader holds the bootstrap document of a Progressive Web App
served from an account. It is deliberately capped: the blob lives in a
ledger object that carries no owner reserve at all, so the only things
standing between it and unbounded ledger growth are this limit and the
per-byte transaction fee below.
*/
std::size_t constexpr maxAppLoaderLength = 4096;
/** Drops of transaction fee charged per byte of AppLoader document.
Storage is paid for through the fee rather than through an owner
reserve, so that a loader can be published by an account sitting at its
reserve floor. The fee is charged on every AccountSet that carries the
field, including overwrites.
*/
std::uint64_t constexpr appLoaderFeeDropsPerByte = 1;
/** The maximum length of a URI inside a Credential */
std::size_t constexpr maxCredentialURILength = 256;
+83 -42
View File
@@ -24,7 +24,6 @@
#include <xrpl/protocol/KeyType.h>
#include <xrpl/protocol/STExchange.h>
#include <xrpl/protocol/UintTypes.h>
#include <xrpl/protocol/detail/KeyBase.h>
#include <xrpl/protocol/json_get_or_throw.h>
#include <xrpl/protocol/tokens.h>
@@ -37,26 +36,6 @@
namespace ripple {
/** Returns the type of public key.
@return std::nullopt If the public key does not
represent a known type.
*/
[[nodiscard]] inline std::optional<KeyType>
publicKeyType(Slice const& slice)
{
if (slice.size() == 33)
{
if (slice[0] == 0xED)
return KeyType::ed25519;
if (slice[0] == 0x02 || slice[0] == 0x03)
return KeyType::secp256k1;
}
return std::nullopt;
}
/** A public key.
Public keys are used in the public-key cryptography
@@ -79,47 +58,77 @@ publicKeyType(Slice const& slice)
prefix constant 0xED, followed by 32 bytes of
public key data.
*/
class PublicKey : public detail::KeyBase<PublicKey, 33>
class PublicKey
{
protected:
// All the constructed public keys are valid, non-empty and contain 33
// bytes of data.
static constexpr std::size_t size_ = 33;
std::uint8_t buf_[size_]; // should be large enough
public:
using const_iterator = std::uint8_t const*;
public:
PublicKey() = delete;
PublicKey(PublicKey const&) = default;
PublicKey(PublicKey const& other);
PublicKey&
operator=(PublicKey const&) = default;
operator=(PublicKey const& other);
explicit PublicKey(Slice const& slice) noexcept
/** Create a public key.
Preconditions:
publicKeyType(slice) != std::nullopt
*/
explicit PublicKey(Slice const& slice);
std::uint8_t const*
data() const noexcept
{
if (slice.size() < buf_.size())
LogicError("PublicKey::PublicKey: undersized buffer");
if (!publicKeyType(slice))
LogicError("PublicKey::PublicKey: invalid type");
std::copy_n(slice.data(), buf_.size(), buf_.data());
return buf_;
}
explicit PublicKey(value_t const& data) noexcept
: PublicKey(makeSlice(data))
std::size_t
size() const noexcept
{
return size_;
}
[[nodiscard]] Slice
const_iterator
begin() const noexcept
{
return buf_;
}
const_iterator
cbegin() const noexcept
{
return buf_;
}
const_iterator
end() const noexcept
{
return buf_ + size_;
}
const_iterator
cend() const noexcept
{
return buf_ + size_;
}
Slice
slice() const noexcept
{
return {buf_.data(), buf_.size()};
return {buf_, size_};
}
operator Slice() const noexcept
{
return slice();
}
[[nodiscard]] auto
operator<=>(PublicKey const& rhs) const
{
return buf_ <=> rhs.buf_;
}
};
/** Print the public key to a stream.
@@ -127,6 +136,22 @@ public:
std::ostream&
operator<<(std::ostream& os, PublicKey const& pk);
inline bool
operator==(PublicKey const& lhs, PublicKey const& rhs)
{
return std::memcmp(lhs.data(), rhs.data(), rhs.size()) == 0;
}
inline bool
operator<(PublicKey const& lhs, PublicKey const& rhs)
{
return std::lexicographical_compare(
lhs.data(),
lhs.data() + lhs.size(),
rhs.data(),
rhs.data() + rhs.size());
}
template <class Hasher>
void
hash_append(Hasher& h, PublicKey const& pk)
@@ -196,6 +221,22 @@ enum class ECDSACanonicality { canonical, fullyCanonical };
std::optional<ECDSACanonicality>
ecdsaCanonicality(Slice const& sig);
/** Returns the type of public key.
@return std::nullopt If the public key does not
represent a known type.
*/
/** @{ */
[[nodiscard]] std::optional<KeyType>
publicKeyType(Slice const& slice);
[[nodiscard]] inline std::optional<KeyType>
publicKeyType(PublicKey const& publicKey)
{
return publicKeyType(publicKey.slice());
}
/** @} */
/** Verify a secp256k1 signature on the digest of a message. */
[[nodiscard]] bool
verifyDigest(
+62 -11
View File
@@ -25,39 +25,90 @@
#include <xrpl/protocol/KeyType.h>
#include <xrpl/protocol/PublicKey.h>
#include <xrpl/protocol/Seed.h>
#include <xrpl/protocol/detail/KeyBase.h>
#include <xrpl/protocol/tokens.h>
#include <array>
#include <cstring>
#include <string>
namespace ripple {
/** A secret key. */
class SecretKey : public detail::KeyBase<SecretKey, 32>
class SecretKey
{
public:
SecretKey() = delete;
private:
std::uint8_t buf_[32];
public:
using const_iterator = std::uint8_t const*;
SecretKey() = delete;
SecretKey(SecretKey const&) = default;
SecretKey&
operator=(SecretKey const&) = default;
/** Destroy the secret key. This will try to securely erase the buffer. */
~SecretKey();
SecretKey(Slice const& slice)
{
if (slice.size() != buf_.size())
LogicError("SecretKey::SecretKey: invalid size");
SecretKey(std::array<std::uint8_t, 32> const& data);
SecretKey(Slice const& slice);
std::copy_n(slice.data(), buf_.size(), buf_.data());
std::uint8_t const*
data() const
{
return buf_;
}
explicit SecretKey(span_t const& data) noexcept : KeyBase(data)
std::size_t
size() const
{
return sizeof(buf_);
}
/** Convert the secret key to a hexadecimal string.
@note The operator<< function is deliberately omitted
to avoid accidental exposure of secret key material.
*/
std::string
to_string() const;
const_iterator
begin() const noexcept
{
return buf_;
}
const_iterator
cbegin() const noexcept
{
return buf_;
}
const_iterator
end() const noexcept
{
return buf_ + sizeof(buf_);
}
const_iterator
cend() const noexcept
{
return buf_ + sizeof(buf_);
}
};
inline bool
operator==(SecretKey const& lhs, SecretKey const& rhs)
{
return lhs.size() == rhs.size() &&
std::memcmp(lhs.data(), rhs.data(), rhs.size()) == 0;
}
inline bool
operator!=(SecretKey const& lhs, SecretKey const& rhs)
{
return !(lhs == rhs);
}
//------------------------------------------------------------------------------
/** Parse a secret key */
+46 -11
View File
@@ -22,37 +22,72 @@
#include <xrpl/basics/Slice.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/protocol/detail/KeyBase.h>
#include <xrpl/protocol/tokens.h>
#include <algorithm>
#include <array>
#include <optional>
namespace ripple {
/** Seeds are used to generate deterministic secret keys. */
class Seed : public detail::KeyBase<Seed, 16>
class Seed
{
private:
std::array<uint8_t, 16> buf_;
public:
using const_iterator = std::array<uint8_t, 16>::const_iterator;
Seed() = delete;
Seed(Seed const&) = default;
Seed&
operator=(Seed const&) = default;
/** Destroy the seed. This will attempt to securely erase the buffer. */
/** Destroy the seed.
The buffer will first be securely erased.
*/
~Seed();
explicit Seed(Slice const& slice)
{
if (slice.size() != buf_.size())
LogicError("Seed::Seed: invalid size");
/** Construct a seed */
/** @{ */
explicit Seed(Slice const& slice);
explicit Seed(uint128 const& seed);
/** @} */
std::copy_n(slice.data(), buf_.size(), buf_.data());
std::uint8_t const*
data() const
{
return buf_.data();
}
explicit Seed(span_t seed) noexcept : KeyBase(seed)
std::size_t
size() const
{
return buf_.size();
}
const_iterator
begin() const noexcept
{
return buf_.begin();
}
const_iterator
cbegin() const noexcept
{
return buf_.cbegin();
}
const_iterator
end() const noexcept
{
return buf_.end();
}
const_iterator
cend() const noexcept
{
return buf_.cend();
}
};
+12 -3
View File
@@ -24,14 +24,18 @@
#include <xrpl/protocol/XRPAmount.h>
#include <cstdint>
#include <string>
#include <string_view>
namespace ripple {
// Various protocol and system specific constant globals.
/* The name of the system. */
inline constexpr std::string_view systemName = "xahau";
static inline std::string const&
systemName()
{
static std::string const name = "xahau";
return name;
}
/** Configure the native currency. */
@@ -54,7 +58,12 @@ isLegalAmountSigned(XRPAmount const& amount)
}
/* The currency code for the native currency. */
inline constexpr std::string_view systemCurrencyCode = "XAH";
static inline std::string const&
systemCurrencyCode()
{
static std::string const code = "XAH";
return code;
}
/** The XRP ledger network's earliest allowed sequence */
static constexpr std::uint32_t XRP_LEDGER_EARLIEST_SEQ{1U};
-5
View File
@@ -69,7 +69,6 @@ enum TELcodes : TERUnderlyingType {
telIMPORT_VL_KEY_NOT_RECOGNISED,
telCAN_NOT_QUEUE_IMPORT,
telENV_RPC_FAILED,
telMANIFEST_FEE_MISMATCH,
};
//------------------------------------------------------------------------------
@@ -138,7 +137,6 @@ enum TEMcodes : TERUnderlyingType {
temXCHAIN_BRIDGE_NONDOOR_OWNER,
temXCHAIN_BRIDGE_BAD_MIN_ACCOUNT_CREATE_AMOUNT,
temXCHAIN_BRIDGE_BAD_REWARD_AMOUNT,
temXCHAIN_TOO_MANY_ATTESTATIONS, // RESERVED - not used
temHOOK_DATA_TOO_LARGE,
temEMPTY_DID,
@@ -195,9 +193,6 @@ enum TEFcodes : TERUnderlyingType {
tefNONDIR_EMIT,
tefIMPORT_BLACKHOLED,
tefINVALID_LEDGER_FIX_TYPE,
tefPAST_MANIFEST_SEQ,
tefREVOKED_MANIFEST,
tefMANIFEST_KEY_IN_USE,
};
//------------------------------------------------------------------------------
+1 -1
View File
@@ -132,7 +132,7 @@ constexpr std::uint32_t tfTrustSetMask =
tfClearFreeze | tfSetDeepFreeze | tfClearDeepFreeze);
// EnableAmendment flags:
enum EnableAmendmentFlags : uint32_t {
enum EnableAmendmentFlags : std::uint32_t {
tfGotMajority = 0x00010000,
tfLostMajority = 0x00020000,
tfTestSuite = 0x80000000,
-21
View File
@@ -152,26 +152,6 @@ public:
return static_cast<bool>(mHookEmissions);
}
/** featureRNG: the RNG state this transaction's first Hook draw saw.
Every value the transaction's Hooks drew is derived from it. */
void
setRandomData(uint256 const& randomData)
{
mRandomData = randomData;
}
bool
hasRandomData() const
{
return static_cast<bool>(mRandomData);
}
uint256 const&
getRandomData() const
{
return *mRandomData;
}
STAmount
getDeliveredAmount() const
{
@@ -196,7 +176,6 @@ private:
std::optional<STAmount> mDelivered;
std::optional<STArray> mHookExecutions;
std::optional<STArray> mHookEmissions;
std::optional<uint256> mRandomData;
STArray mNodes;
};
+60 -169
View File
@@ -24,166 +24,84 @@
#include <xrpl/basics/base_uint.h>
#include <xrpl/beast/utility/Zero.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/SystemParameters.h>
namespace ripple {
using LedgerHash = uint256;
/** Directory is an index into the directory of offer books.
The last 64 bits of this are the quality. */
using Directory = base_uint<256, struct DirectoryTag>;
/** Currency is a hash representing a specific currency. */
using Currency = base_uint<160, struct CurrencyTag>;
/** NodeID is a 160-bit hash representing one node. */
using NodeID = base_uint<160, struct NodeIDTag>;
/** A Multi-Purpose Token Issuance ID,
The ID is the a concatenation of a 32-bit sequence number,
in big endian, and a 160-bit account.
@note This type is, unfortunately, untagged because the authors
of the original code used a deserialization APIs that did
not support tags. It should be fixed.
*/
using MPTID = base_uint<192>;
namespace detail {
// A table mapping which characters we are willing to allow in the ASCII
// representation of a three-letter currency code.
inline constexpr auto validIsoChars = []() consteval {
std::string_view isoCharSet =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789"
"<>(){}[]|?!@#$%^&*";
std::array<bool, 256> table{};
for (unsigned char c : isoCharSet)
table[c] = true;
return table;
}();
// Determines if the given code is composed entirely of letters valid in
// ISO 4217 codes.
[[nodiscard]] inline constexpr bool
isIsoCode(std::string_view code) noexcept
class CurrencyTag
{
return std::all_of(code.begin(), code.end(), [](char c) {
return validIsoChars[static_cast<unsigned char>(c)];
});
}
public:
explicit CurrencyTag() = default;
};
// The location (in bytes) of the 3 digit currency inside a 160-bit value
inline constexpr std::size_t isoCodeOffset = 12;
class DirectoryTag
{
public:
explicit DirectoryTag() = default;
};
// The length of an ISO-4217 like code
inline constexpr std::size_t isoCodeLength = 3;
inline constexpr Currency isoMaskBits = ~Currency(0xFFFFFF0000000000);
// The special currency identifier for the system currency: all-zero
inline constexpr Currency xrpCurrency{0x0000000000000000};
// The special currency identifier meaning "no currency"
inline constexpr Currency noCurrency{0x0000000000000001};
// The system currency identifier in "ISO4217 format" which is reserved.
// We derive this value dynamically from the system currency code.
inline constexpr Currency badCurrency = []() consteval {
if (systemCurrencyCode.size() != isoCodeLength)
throw "Incorrect systemCurrencyCode size (must be 3 digits)";
std::array<std::uint8_t, Currency::bytes> bytes{};
for (std::size_t i = 0; i < isoCodeLength; ++i)
bytes[isoCodeOffset + i] =
static_cast<std::uint8_t>(systemCurrencyCode[i]);
return Currency(bytes);
}();
// We take advantage of the fact that an ASCII value in the [a-z] range
// transforms into the equivalent character in the [A-Z] range when you
// AND it with 0xDF, so we can compare against all possible variants of
// "XAH" in one go. Every byte outside the ISO code position is kept as-is
// by the mask, so a currency is only "bad" when those bytes are all zero
// (i.e. the value is exactly one of the case variants of the code).
inline constexpr Currency badCurrencyCodeMask =
isoMaskBits | Currency{0xDFDFDF0000000000};
class NodeIDTag
{
public:
explicit NodeIDTag() = default;
};
} // namespace detail
/** XRP currency. */
[[nodiscard]] constexpr Currency const&
xrpCurrency() noexcept
{
return detail::xrpCurrency;
}
/** Directory is an index into the directory of offer books.
The last 64 bits of this are the quality. */
using Directory = base_uint<256, detail::DirectoryTag>;
[[nodiscard]] constexpr bool
isXRP(Currency const& c) noexcept
{
return c == detail::xrpCurrency;
}
/** Currency is a hash representing a specific currency. */
using Currency = base_uint<160, detail::CurrencyTag>;
/** NodeID is a 160-bit hash representing one node. */
using NodeID = base_uint<160, detail::NodeIDTag>;
/** MPTID is a 192-bit value representing MPT Issuance ID,
* which is a concatenation of a 32-bit sequence (big endian)
* and a 160-bit account */
using MPTID = base_uint<192>;
/** XRP currency. */
Currency const&
xrpCurrency();
/** A placeholder for empty currencies. */
[[nodiscard]] constexpr Currency const&
noCurrency() noexcept
{
return detail::noCurrency;
}
Currency const&
noCurrency();
/** We deliberately disallow the currency that looks like "XAH" because too
many people were using it instead of the correct XAH currency. */
[[nodiscard]] constexpr Currency const&
badCurrency() noexcept
Currency const&
badCurrency();
inline bool
isXRP(Currency const& c)
{
return detail::badCurrency;
return c == beast::zero;
}
[[nodiscard]] constexpr bool
isBadCurrency(Currency const& c) noexcept
inline bool
isBadCurrency(Currency const& c)
{
// We take advantage of the fact that an ASCII value in the [a-z] range
// transforms into the equivalent character in the [A-Z] range when you
// AND it with 0xDF, so we can compare against all possible variants of
// the bad currency code in one go:
return (c & detail::badCurrencyCodeMask) == badCurrency();
static const std::set<Currency> badCurrencies{
Currency(0x7861680000000000), // xah
Currency(0x7861480000000000), // xaH
Currency(0x7841680000000000), // xAh
Currency(0x7841480000000000), // xAH
Currency(0x5861680000000000), // Xah
Currency(0x5861480000000000), // XaH
Currency(0x5841680000000000), // XAh
Currency(0x5841480000000000) // XAH
};
return badCurrencies.find(c) != badCurrencies.end();
}
/** Returns "", "XAH", three letter ISO code or the hex representation. */
[[nodiscard]] inline std::string
to_string(Currency const& currency)
{
if (currency == xrpCurrency())
return std::string{systemCurrencyCode};
if (currency == noCurrency())
return "1";
if ((currency & detail::isoMaskBits) == beast::zero)
{
std::string_view const iso(
reinterpret_cast<char const*>(currency.data()) +
detail::isoCodeOffset,
detail::isoCodeLength);
// Specifying the system currency code using ISO-style representation
// is not allowed. Note that the check is case-sensitive; yet another
// instance of legacy code smell.
if (detail::isIsoCode(iso) && iso != systemCurrencyCode)
return std::string{iso};
}
return strHex(currency);
}
/** Returns "", "XAH", or three letter ISO code. */
std::string
to_string(Currency const& c);
/** Tries to convert a string to a Currency, returns true on success.
@@ -192,29 +110,8 @@ to_string(Currency const& currency)
will require very careful checking everywhere and may mean having
to rewrite some unit test code.
*/
[[nodiscard]] constexpr bool
to_currency(Currency& currency, std::string_view code) noexcept
{
if (code.empty() || code == systemCurrencyCode)
{
currency = xrpCurrency();
return true;
}
// Handle ISO-4217-like 3-digit character codes.
if (code.size() != detail::isoCodeLength)
return currency.parseHex(code);
if (!detail::isIsoCode(code))
return false;
currency = beast::zero;
std::copy_n(
code.data(), code.size(), currency.begin() + detail::isoCodeOffset);
return true;
}
bool
to_currency(Currency&, std::string const&);
/** Tries to convert a string to a Currency, returns noCurrency() on failure.
@@ -222,14 +119,8 @@ to_currency(Currency& currency, std::string_view code) noexcept
unfortunate; changing this will require very careful checking
everywhere and may mean having to rewrite some unit test code.
*/
[[nodiscard]] constexpr Currency
to_currency(std::string_view code) noexcept
{
if (Currency currency; to_currency(currency, code))
return currency;
return noCurrency();
}
Currency
to_currency(std::string const&);
inline std::ostream&
operator<<(std::ostream& os, Currency const& x)
-114
View File
@@ -1,114 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of xahaud: https://github.com/xahau/xahaud
Copyright (c) 2026, the Xahaud developers.
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 XAHAU_PROTOCOL_KEYBASE_H_INCLUDED
#define XAHAU_PROTOCOL_KEYBASE_H_INCLUDED
#include <algorithm>
#include <array>
#include <cstdint>
#include <span>
namespace ripple {
namespace detail {
/** Common base for fixed-size key and seed types.
This CRTP base provides storage, accessors, and equality comparison
for types like seeds and secret/public keys, which wrap a fixed-size
byte array. The Derived parameter ensures that unrelated types with
the same size do not implicitly interoperate with one another.
Equality comparison is provided automatically. Derived classes that
want to can opt in to ordering by declaring operator<=> as a
hidden friend.
@tparam Derived The concrete type inheriting from this base (CRTP).
@tparam N The size of the underlying byte array.
*/
template <class Derived, std::size_t N>
class KeyBase
{
public:
/** The type we use to store the data. */
using value_t = std::array<std::uint8_t, N>;
/** The span type corresponding to the type we use to store the data. */
using span_t = std::span<std::uint8_t, N>;
protected:
value_t buf_;
KeyBase() noexcept = default;
explicit KeyBase(span_t data) noexcept
{
std::copy_n(data.data(), N, buf_.data());
}
public:
[[nodiscard]] std::uint8_t const*
data() const
{
return buf_.data();
}
[[nodiscard]] std::size_t
size() const
{
return buf_.size();
}
[[nodiscard]] auto
begin() const noexcept
{
return buf_.begin();
}
[[nodiscard]] auto
cbegin() const noexcept
{
return buf_.cbegin();
}
[[nodiscard]] auto
end() const noexcept
{
return buf_.end();
}
[[nodiscard]] auto
cend() const noexcept
{
return buf_.cend();
}
[[nodiscard]] friend bool
operator==(Derived const& lhs, Derived const& rhs)
{
// This is not a constant time comparison. This is probably OK
// for the xahaud codebase.
return lhs.buf_ == rhs.buf_;
}
};
} // namespace detail
} // namespace ripple
#endif
+15 -52
View File
@@ -23,9 +23,6 @@
#if !defined(XRPL_FIX)
#error "undefined macro: XRPL_FIX"
#endif
#if !defined(XRPL_RETIRE)
#error "undefined macro: XRPL_RETIRE"
#endif
// clang-format off
@@ -34,24 +31,11 @@
// If you add an amendment here, then do not forget to increment `numFeatures`
// in include/xrpl/protocol/Feature.h.
XRPL_FEATURE(RNG, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(PWALoader, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (20261005, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(EscrowDestinationCancel, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (20260929, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(HookOnV2_1, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(OnChainManifests, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (HookMap, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (GuardDepth32, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(NamedHooks, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(IOURewardClaim, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (IOULockedBalanceInvariant, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (ImportIssuer, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(HookAPISerializedType240, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(PermissionedDomains, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(DynamicNFT, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(Credentials, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(AMMClawback, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(AMMClawback, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(MPTokensV1, Supported::no, VoteBehavior::DefaultNo)
// InvariantsV1_1 will be changes to Supported::yes when all the
// invariants expected to be included under it are complete.
@@ -68,19 +52,18 @@ XRPL_FIX (FillOrKill, Supported::yes, VoteBehavior::DefaultYe
XRPL_FEATURE(DID, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (DisallowIncomingV1, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(XChainBridge, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(AMM, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(AMM, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (ReducedOffersV1, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(HooksUpdate2, Supported::yes, VoteBehavior::DefaultNo)
// replaced to HookOnV2_1
XRPL_FEATURE(HookOnV2, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (HookAPI20251128, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (CronStacking, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(ExtendedHookState, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(Cron, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(IOUIssuerWeakTSH, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(DeepFreeze, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (ProvisionalDoubleThreading, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(HooksUpdate2, Supported::yes, VoteBehavior::DefaultNo);
XRPL_FEATURE(HookOnV2, Supported::yes, VoteBehavior::DefaultNo);
XRPL_FIX (HookAPI20251128, Supported::yes, VoteBehavior::DefaultYes);
XRPL_FIX (CronStacking, Supported::yes, VoteBehavior::DefaultYes);
XRPL_FEATURE(ExtendedHookState, Supported::yes, VoteBehavior::DefaultNo);
XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultYes);
XRPL_FEATURE(Cron, Supported::yes, VoteBehavior::DefaultNo);
XRPL_FEATURE(IOUIssuerWeakTSH, Supported::yes, VoteBehavior::DefaultNo);
XRPL_FEATURE(DeepFreeze, Supported::yes, VoteBehavior::DefaultNo);
XRPL_FIX (ProvisionalDoubleThreading, Supported::yes, VoteBehavior::DefaultYes);
XRPL_FEATURE(Clawback, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (RewardClaimFlags, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(HookCanEmit, Supported::yes, VoteBehavior::DefaultNo)
@@ -90,11 +73,14 @@ XRPL_FIX (ReduceImport, Supported::yes, VoteBehavior::DefaultYe
XRPL_FEATURE(Touch, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(Remarks, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (FloatDivide, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (240911, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (PageCap, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (240819, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (NSDelete, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(ZeroB2M, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(Remit, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (XahauV2, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (XahauV1, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(HooksUpdate1, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(XahauGenesis, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(Import, Supported::yes, VoteBehavior::DefaultYes)
@@ -161,27 +147,4 @@ XRPL_FIX (NFTokenDirV1, Supported::yes, VoteBehavior::Obsolete)
XRPL_FEATURE(NonFungibleTokensV1, Supported::yes, VoteBehavior::Obsolete)
XRPL_FEATURE(CryptoConditionsSuite, Supported::yes, VoteBehavior::Obsolete)
// The following amendments have been active for at least two years. Their
// pre-amendment code has been removed and the identifiers are deprecated.
// All known amendments and amendments that may appear in a validated
// ledger must be registered either here or above with the "active" amendments
XRPL_RETIRE(fix240911)
XRPL_RETIRE(fixXahauV2)
XRPL_RETIRE(fixXahauV1)
XRPL_RETIRE(MultiSign)
XRPL_RETIRE(TrustSetAuth)
XRPL_RETIRE(FeeEscalation)
XRPL_RETIRE(PayChan)
XRPL_RETIRE(CryptoConditions)
XRPL_RETIRE(TickSize)
XRPL_RETIRE(fix1368)
XRPL_RETIRE(Escrow)
XRPL_RETIRE(fix1373)
XRPL_RETIRE(EnforceInvariants)
XRPL_RETIRE(SortedDirectories)
XRPL_RETIRE(fix1201)
XRPL_RETIRE(fix1512)
XRPL_RETIRE(fix1523)
XRPL_RETIRE(fix1528)
// clang-format on
@@ -22,14 +22,14 @@
#endif
#ifndef LEDGER_ENTRY_DUPLICATE
// The LEDGER_ENTRY_EXPAND macro is needed for Windows
// The EXPAND macro is needed for Windows
// https://stackoverflow.com/questions/5134523/msvc-doesnt-expand-va-args-correctly
#define LEDGER_ENTRY_EXPAND(x) x
#define EXPAND(x) x
// The `LEDGER_ENTRY_DUPLICATE macro is needed to avoid JSS conflicts
// Since some transactions and ledger entries have the same name (like `DepositPreauth`)
// The compiler won't accept two instances of `JSS(DepositPreauth)`
#define LEDGER_ENTRY_DUPLICATE(...) LEDGER_ENTRY_EXPAND(LEDGER_ENTRY(__VA_ARGS__))
#define LEDGER_ENTRY_DUPLICATE(...) EXPAND(LEDGER_ENTRY(__VA_ARGS__))
#endif
/**
@@ -93,7 +93,7 @@ LEDGER_ENTRY(ltCHECK, 0x0043, Check, check, ({
*/
LEDGER_ENTRY(ltHOOK_DEFINITION, 'D', HookDefinition, hook_definition, ({
{sfHookHash, soeREQUIRED},
{sfHookOn, soeOPTIONAL},
{sfHookOn, soeREQUIRED},
{sfHookOnIncoming, soeOPTIONAL},
{sfHookOnOutgoing, soeOPTIONAL},
{sfHookCanEmit, soeOPTIONAL},
@@ -142,22 +142,6 @@ LEDGER_ENTRY(ltIMPORT_VLSEQ, 0x0049, ImportVLSequence, import_vlseq, ({
{sfPreviousTxnLgrSeq, soeOPTIONAL},
}))
/** The bootstrap document of a Progressive Web App (featurePWALoader).
At most one per account, keyed on the owner alone (keylet::appLoader).
It is in no owner directory and takes no reserve: its storage is paid
for by a per-byte fee on the AccountSet that writes it, and
DeleteAccount erases it explicitly. AppLoaderSequence equals the owner's
AccountRoot AppLoaderSequence as of the AccountSet that wrote it.
*/
LEDGER_ENTRY(ltAPP_LOADER, 0x004c, AppLoader, app_loader, ({
{sfOwner, soeREQUIRED},
{sfAppLoader, soeREQUIRED},
{sfAppLoaderSequence, soeREQUIRED},
{sfPreviousTxnID, soeREQUIRED},
{sfPreviousTxnLgrSeq, soeREQUIRED},
}))
/** The ledger object which tracks the current negative UNL state.
\note This is a singleton: only one such object exists in the ledger.
@@ -196,26 +180,6 @@ LEDGER_ENTRY_DUPLICATE(ltUNL_REPORT, 0x0052, UNLReport, unl_report, ({
{sfPreviousTxnLgrSeq, soeREQUIRED},
}))
/** featureRNG: the consensus random number generator.
A singleton. sfRandomData is seeded from validator reveals by the
ttENTROPY transactions applied at the start of each ledger, and then
iterated by every Hook API draw for the rest of that ledger.
sfRandomData and sfRandomDigests are never written to metadata, and
Hooks cannot load this object.
\sa keylet::random
*/
LEDGER_ENTRY(ltRANDOM, 0x526E, Random, random, ({
{sfLedgerSequence, soeREQUIRED},
{sfRandomData, soeREQUIRED},
{sfEntropyCount, soeREQUIRED},
{sfEntropyDenominator, soeREQUIRED},
{sfRandomDigests, soeREQUIRED},
{sfPreviousTxnID, soeREQUIRED},
{sfPreviousTxnLgrSeq, soeREQUIRED},
}))
/** A ledger object which contains a signer list for an account.
\sa keylet::signers
@@ -298,8 +262,6 @@ LEDGER_ENTRY(ltACCOUNT_ROOT, 0x0061, AccountRoot, account, ({
{sfHookStateScale, soeOPTIONAL},
{sfCron, soeOPTIONAL},
{sfAMMID, soeOPTIONAL},
{sfAppLoaderSequence, soeOPTIONAL},
{sfManifestID, soeOPTIONAL},
}))
/** A ledger object which contains a list of object identifiers.
@@ -434,8 +396,6 @@ LEDGER_ENTRY(ltRIPPLE_STATE, 0x0072, RippleState, state, ({
{sfHighQualityOut, soeOPTIONAL},
{sfLockedBalance, soeOPTIONAL},
{sfLockCount, soeOPTIONAL},
{sfHighReward, soeOPTIONAL},
{sfLowReward, soeOPTIONAL},
}))
/** The ledger object which lists the network's fee settings.
@@ -630,27 +590,6 @@ LEDGER_ENTRY(ltDID, 0x008D, DID, did, ({
{sfPreviousTxnLgrSeq, soeREQUIRED},
}))
LEDGER_ENTRY(ltMANIFEST, 0x004D, Manifest, manifest_entry, ({
{sfAccount, soeREQUIRED},
{sfPublicKey, soeREQUIRED},
{sfSigningPubKey, soeOPTIONAL}, /* may be absent if the master is revoked */
{sfSequence, soeREQUIRED},
/* sfVersion defaults to 0 and is omitted from the signed payload when
absent. Storing it unconditionally would change the bytes and break
signature verification when the manifest is reconstructed. */
{sfVersion, soeOPTIONAL},
{sfDomain, soeOPTIONAL},
/* The signatures are mirrored so the object is a lossless copy of the
manifest and can be independently verified, and re-served to peers,
by any node reading it (see ManifestCache::applyLedger). */
{sfMasterSignature, soeREQUIRED},
{sfSignature, soeOPTIONAL}, /* absent if the master is revoked */
{sfManifestID, soeOPTIONAL}, /* pointer to the identical other copy on the other key */
{sfOwnerNode, soeOPTIONAL}, /* master copy only: its page in keylet::manifestDir() */
{sfPreviousTxnID, soeREQUIRED},
{sfPreviousTxnLgrSeq, soeREQUIRED},
}))
#undef LEDGER_ENTRY_EXPAND
#undef EXPAND
#undef LEDGER_ENTRY_DUPLICATE
+1 -18
View File
@@ -59,8 +59,6 @@ TYPED_SFIELD(sfHookExecutionIndex, UINT16, 19)
TYPED_SFIELD(sfHookApiVersion, UINT16, 20)
TYPED_SFIELD(sfHookStateScale, UINT16, 21)
TYPED_SFIELD(sfLedgerFixType, UINT16, 22)
TYPED_SFIELD(sfEntropyCount, UINT16, 99)
TYPED_SFIELD(sfEntropyDenominator, UINT16, 100)
// 32-bit integers (common)
TYPED_SFIELD(sfNetworkID, UINT32, 1)
@@ -125,7 +123,6 @@ TYPED_SFIELD(sfImportSequence, UINT32, 97)
TYPED_SFIELD(sfRewardTime, UINT32, 98)
TYPED_SFIELD(sfRewardLgrFirst, UINT32, 99)
TYPED_SFIELD(sfRewardLgrLast, UINT32, 100)
TYPED_SFIELD(sfAppLoaderSequence, UINT32, 101)
// 64-bit integers (common)
TYPED_SFIELD(sfIndexNext, UINT64, 1)
@@ -213,10 +210,6 @@ TYPED_SFIELD(sfOfferID, UINT256, 34)
TYPED_SFIELD(sfEscrowID, UINT256, 35)
TYPED_SFIELD(sfURITokenID, UINT256, 36)
TYPED_SFIELD(sfDomainID, UINT256, 37)
TYPED_SFIELD(sfNextRandomDigest, UINT256, 89)
// RNG running state: never written to metadata (see featureRNG)
TYPED_SFIELD(sfRandomData, UINT256, 90, SField::sMD_Never)
TYPED_SFIELD(sfManifestID, UINT256, 91)
TYPED_SFIELD(sfHookOnOutgoing, UINT256, 93)
TYPED_SFIELD(sfHookOnIncoming, UINT256, 94)
TYPED_SFIELD(sfCron, UINT256, 95)
@@ -264,7 +257,6 @@ TYPED_SFIELD(sfPrice, AMOUNT, 28)
TYPED_SFIELD(sfSignatureReward, AMOUNT, 29)
TYPED_SFIELD(sfMinAccountCreateAmount, AMOUNT, 30)
TYPED_SFIELD(sfLPTokenBalance, AMOUNT, 31)
TYPED_SFIELD(sfTrustLineRewardAccumulator,AMOUNT, 99)
// variable length (common)
TYPED_SFIELD(sfPublicKey, VL, 1)
@@ -300,8 +292,6 @@ TYPED_SFIELD(sfAssetClass, VL, 29)
TYPED_SFIELD(sfProvider, VL, 30)
TYPED_SFIELD(sfMPTokenMetadata, VL, 31)
TYPED_SFIELD(sfCredentialType, VL, 32)
TYPED_SFIELD(sfAppLoader, VL, 96)
TYPED_SFIELD(sfHookName, VL, 97)
TYPED_SFIELD(sfRemarkValue, VL, 98)
TYPED_SFIELD(sfRemarkName, VL, 99)
@@ -350,7 +340,6 @@ TYPED_SFIELD(sfLockingChainIssue, ISSUE, 1)
TYPED_SFIELD(sfIssuingChainIssue, ISSUE, 2)
TYPED_SFIELD(sfAsset, ISSUE, 3)
TYPED_SFIELD(sfAsset2, ISSUE, 4)
TYPED_SFIELD(sfClaimCurrency, ISSUE, 5)
// bridge
TYPED_SFIELD(sfXChainBridge, XCHAIN_BRIDGE, 1)
@@ -378,7 +367,7 @@ UNTYPED_SFIELD(sfMajority, OBJECT, 18)
UNTYPED_SFIELD(sfDisabledValidator, OBJECT, 19)
UNTYPED_SFIELD(sfEmittedTxn, OBJECT, 20)
UNTYPED_SFIELD(sfHookExecution, OBJECT, 21)
// 22 unused
UNTYPED_SFIELD(sfHookDefinition, OBJECT, 22)
UNTYPED_SFIELD(sfHookParameter, OBJECT, 23)
UNTYPED_SFIELD(sfHookGrant, OBJECT, 24)
UNTYPED_SFIELD(sfVoteEntry, OBJECT, 25)
@@ -390,8 +379,6 @@ UNTYPED_SFIELD(sfXChainClaimAttestationCollectionElement, OBJECT, 30)
UNTYPED_SFIELD(sfXChainCreateAccountAttestationCollectionElement, OBJECT, 31)
UNTYPED_SFIELD(sfPriceData, OBJECT, 32)
UNTYPED_SFIELD(sfCredential, OBJECT, 33)
UNTYPED_SFIELD(sfRandomDigestEntry, OBJECT, 88)
UNTYPED_SFIELD(sfManifest, OBJECT, 90)
UNTYPED_SFIELD(sfAmountEntry, OBJECT, 91)
UNTYPED_SFIELD(sfMintURIToken, OBJECT, 92)
UNTYPED_SFIELD(sfHookEmission, OBJECT, 93)
@@ -399,8 +386,6 @@ UNTYPED_SFIELD(sfImportVLKey, OBJECT, 94)
UNTYPED_SFIELD(sfActiveValidator, OBJECT, 95)
UNTYPED_SFIELD(sfGenesisMint, OBJECT, 96)
UNTYPED_SFIELD(sfRemark, OBJECT, 97)
UNTYPED_SFIELD(sfHighReward, OBJECT, 98)
UNTYPED_SFIELD(sfLowReward, OBJECT, 99)
// array of objects (common)
// ARRAY/1 is reserved for end of array
@@ -431,8 +416,6 @@ UNTYPED_SFIELD(sfAuthAccounts, ARRAY, 25)
UNTYPED_SFIELD(sfAuthorizeCredentials, ARRAY, 26)
UNTYPED_SFIELD(sfUnauthorizeCredentials, ARRAY, 27)
UNTYPED_SFIELD(sfAcceptedCredentials, ARRAY, 28)
// RNG validator commitments: never written to metadata (see featureRNG)
UNTYPED_SFIELD(sfRandomDigests, ARRAY, 91, SField::sMD_Never)
UNTYPED_SFIELD(sfAmounts, ARRAY, 92)
UNTYPED_SFIELD(sfHookEmissions, ARRAY, 93)
UNTYPED_SFIELD(sfImportVLKeys, ARRAY, 94)
@@ -74,7 +74,6 @@ TRANSACTION(ttACCOUNT_SET, 3, AccountSet, ({
{sfTickSize, soeOPTIONAL},
{sfNFTokenMinter, soeOPTIONAL},
{sfHookStateScale, soeOPTIONAL},
{sfAppLoader, soeOPTIONAL},
}))
/** This transaction type cancels an existing escrow. */
@@ -501,28 +500,6 @@ TRANSACTION(ttPERMISSIONED_DOMAIN_DELETE, 72, PermissionedDomainDelete, ({
{sfDomainID, soeREQUIRED},
}))
/** featureRNG: a validator's entropy contribution for one ledger.
Each proposing UNLReport validator places exactly one of these in its own
initial position when it closes the ledger. It reveals the secret behind
the validator's commitment currently stored in the Random object (if any)
and commits to the secret it will reveal next time. It never enters the
open ledger, so a reveal only becomes public after the revealing
validator's transaction set is locked.
*/
TRANSACTION(ttENTROPY, 89, Entropy, ({
{sfLedgerSequence, soeREQUIRED},
{sfPublicKey, soeREQUIRED},
{sfNextRandomDigest, soeREQUIRED},
{sfRandomData, soeOPTIONAL},
}))
/* sfAccount is supplied by TxFormats::commonFields; listing it here as well
makes the SOTemplate reject the format at construction. */
TRANSACTION(ttMANIFEST_SET, 91, SetManifest, ({
{sfManifest, soeREQUIRED},
}))
/* A pseudo-txn alarm signal for invoking a hook, emitted by validators after alarm set conditions are met */
TRANSACTION(ttCRON, 92, Cron, ({
{sfOwner, soeREQUIRED},
@@ -573,7 +550,6 @@ TRANSACTION(ttIMPORT, 97, Import, ({
* from a specified hook */
TRANSACTION(ttCLAIM_REWARD, 98, ClaimReward, ({
{sfIssuer, soeOPTIONAL},
{sfClaimCurrency, soeOPTIONAL},
}))
/** This transaction invokes a hook, providing arbitrary data. Essentially as a 0 drop payment. **/
+3 -22
View File
@@ -47,7 +47,6 @@ JSS(AL_hit_rate); // out: GetCounts
JSS(AcceptedCredentials); // out: AccountObjects
JSS(Account); // in: TransactionSign; field.
JSS(AMMID); // field
JSS(API); // out: RPC server_definitions (HOOK)
JSS(Amount); // in: TransactionSign; field.
JSS(Authorize); // field
JSS(Amount2); // in/out: AMM IOU/XRP pool, deposit, withdraw amount
@@ -69,9 +68,6 @@ JSS(Destination); // in: TransactionSign; field.
JSS(EPrice); // in: AMM Deposit option
JSS(Fee); // in/out: TransactionSign; field.
JSS(FIELDS); // out: RPC server_definitions
JSS(HOOK); // out: RPC server_definitions
JSS(KEYLET_TYPES); // out: RPC server_definitions (HOOK)
JSS(RETURN_CODES); // out: RPC server_definitions (HOOK)
JSS(Flags); // in/out: TransactionSign; field.
JSS(GenesisMints);
JSS(GovernanceMarks);
@@ -80,7 +76,6 @@ JSS(Holder); // field.
JSS(HookApiVersion); // field
JSS(HookCanEmit); // field
JSS(HookHash); // field
JSS(HookName); // field
JSS(HookNamespace); // field
JSS(HookOn); // field
JSS(HookOnIncoming); // field
@@ -100,15 +95,11 @@ JSS(isVLEncoded); // out: RPC server_definitions
// matches definitions.json format
JSS(Invalid); //
JSS(Issuer); // in: Credential transactions
JSS(IssuingChainDoor); // field.
JSS(IssuingChainIssue); // field.
JSS(InvoiceID); // field
JSS(LastLedgerSequence); // in: TransactionSign; field
JSS(FirstLedgerSequence); // in: TransactionSign; field
JSS(LastUpdateTime); // field.
JSS(LimitAmount); // field.
JSS(LockingChainDoor); // field.
JSS(LockingChainIssue); // field.
JSS(NetworkID); // field.
JSS(LPTokenOut); // in: AMM Liquidity Provider deposit tokens
JSS(LPTokenIn); // in: AMM Liquidity Provider withdraw tokens
@@ -175,7 +166,6 @@ JSS(amendment_blocked); // out: NetworkOPs
JSS(amm_account); // in: amm_info
JSS(amount); // out: AccountChannels, amm_info
JSS(amount2); // out: amm_info
JSS(anchored_through); // out: CatalogueLoad
JSS(api_version); // in: many, out: Version
JSS(api_version_low); // out: Version
JSS(applied); // out: SubmitTransaction
@@ -243,7 +233,7 @@ JSS(closed); // out: NetworkOPs, LedgerToJson,
// handlers/Ledger
JSS(closed_ledger); // out: NetworkOPs
JSS(cluster); // out: PeerImp
JSS(code); // in: HookValidate; out: errors
JSS(code); // out: errors
JSS(command); // in: RPCHandler
JSS(complete); // out: NetworkOPs, InboundLedger
JSS(complete_ledgers); // out: NetworkOPs, PeerImp
@@ -301,9 +291,7 @@ JSS(duration_us); // out: NetworkOPs
JSS(effective); // out: ValidatorList
// in: UNL
JSS(elapsed_seconds);
JSS(enabled); // out: AmendmentTable (on-ledger);
// ServerDefinitions (this server)
JSS(ledger_enabled); // out: ServerDefinitions (on-ledger)
JSS(enabled); // out: AmendmentTable
JSS(engine_result); // out: NetworkOPs, TransactionSign, Submit
JSS(engine_result_code); // out: NetworkOPs, TransactionSign, Submit
JSS(engine_result_message); // out: NetworkOPs, TransactionSign, Submit
@@ -361,7 +349,6 @@ JSS(hash_mismatches); // out: catalogue
JSS(have_header); // out: InboundLedger
JSS(have_state); // out: InboundLedger
JSS(have_transactions); // out: InboundLedger
JSS(hooks); // in/out: AccountInfo
JSS(high); // out: BookChanges
JSS(highest_sequence); // out: AccountInfo
JSS(highest_ticket); // out: AccountInfo
@@ -383,8 +370,6 @@ JSS(index); // in: LedgerEntry,
// LedgerEntry, TxHistory, LedgerData
JSS(info); // out: ServerInfo, ConsensusInfo, FetchInfo
JSS(initial_sync_duration_us);
JSS(instruction_count_cbak); // out: HookValidate
JSS(instruction_count_hook); // out: HookValidate
JSS(internal_command); // in: Internal
JSS(invalid_API_version); // out: Many, when a request has an invalid
// version
@@ -458,7 +443,6 @@ JSS(local); // out: resource/Logic.h
JSS(local_txs); // out: GetCounts
JSS(local_static_keys); // out: ValidatorList
JSS(locked_balance); // out: AccountLines
JSS(log); // out: HookValidate
JSS(low); // out: BookChanges
JSS(lock_count); // out: AccountLines
JSS(lowest_sequence); // out: AccountInfo
@@ -597,6 +581,7 @@ JSS(queue_data); // out: AccountInfo
JSS(queued); // out: SubmitTransaction
JSS(queued_duration_us);
JSS(quote_asset); // in: get_aggregate_price
JSS(random); // out: Random
JSS(raw_meta); // out: AcceptedLedgerTx
JSS(receive_currencies); // out: AccountCurrencies
JSS(reference_level); // out: TxQ
@@ -614,7 +599,6 @@ JSS(reserve_base_native); // out: NetworkOPs
JSS(reserve_inc); // out: NetworkOPs
JSS(reserve_inc_xrp); // out: NetworkOPs
JSS(reserve_inc_native); // out: NetworkOPs
JSS(reset); // in/out: PWAInfo
JSS(response); // websocket
JSS(result); // RPC
JSS(ripple_lines); // out: NetworkOPs
@@ -749,7 +733,6 @@ JSS(TRANSACTION_FLAGS_INDICES); // out: RPC server_definitions
JSS(type_hex); // out: STPathSet
JSS(unl); // out: UnlList
JSS(unlimited); // out: Connection.h
JSS(unpinned); // out: CatalogueUnpin
JSS(uptime); // out: GetCounts
JSS(uri); // out: ValidatorSites
JSS(url); // in/out: Subscribe, Unsubscribe
@@ -757,7 +740,6 @@ JSS(url_password); // in: Subscribe
JSS(url_username); // in: Subscribe
JSS(urlgravatar); //
JSS(username); // in: Subscribe
JSS(valid); // out: HookValidate
JSS(validated); // out: NetworkOPs, RPCHelpers, AccountTx*
// Tx
JSS(validator_list_expires); // out: NetworkOps, ValidatorList
@@ -779,7 +761,6 @@ JSS(validator_sites); // out: ValidatorSites
JSS(value); // out: STAmount
JSS(version); // out: RPCVersion
JSS(vetoed); // out: AmendmentTableImpl
JSS(vm_error); // out: HookValidate
JSS(volume_a); // out: BookChanges
JSS(volume_b); // out: BookChanges
JSS(vote); // in: Feature
-20
View File
@@ -22,7 +22,6 @@
#include <xrpl/basics/BasicConfig.h>
#include <xrpl/beast/net/IPEndpoint.h>
#include <xrpl/protocol/AccountID.h>
#include <boost/asio/ip/address.hpp>
#include <boost/asio/ip/network_v4.hpp>
#include <boost/asio/ip/network_v6.hpp>
@@ -58,12 +57,6 @@ struct Port
std::vector<boost::asio::ip::network_v6> admin_nets_v6;
std::vector<boost::asio::ip::network_v4> secure_gateway_nets_v4;
std::vector<boost::asio::ip::network_v6> secure_gateway_nets_v6;
// "pwa" ports only; see the "pwa ports" section of xahaud-example.cfg.
std::set<std::string> pwa_domains; // zones, lower case, no trailing dot
std::set<AccountID> pwa_allowlist; // if non-empty, only these are served
std::set<AccountID> pwa_blocklist; // never served; wins over allowlist
bool pwa_custom_domains = false; // serve hosts named by TXT records
std::optional<beast::IP::Endpoint> pwa_resolver; // for those; else system
std::string user;
std::string password;
std::string admin_user;
@@ -100,18 +93,8 @@ struct Port
return protocol.count("udp") > 0;
}
bool
has_peer() const
{
return protocol.count("peer") > 0;
}
// Maximum UDP packet size (default 64KB)
std::size_t udp_packet_size = 65536;
// If this is a peer port, also listen for UDP Superhighway (XUSH)
// datagrams on the same port number.
bool udp_highway = false;
};
std::ostream&
@@ -143,9 +126,6 @@ struct ParsedPort
std::vector<boost::asio::ip::network_v6> admin_nets_v6;
std::vector<boost::asio::ip::network_v4> secure_gateway_nets_v4;
std::vector<boost::asio::ip::network_v6> secure_gateway_nets_v6;
std::set<std::string> pwa_domains;
bool pwa_custom_domains = false;
std::optional<beast::IP::Endpoint> pwa_resolver;
};
void
+3 -4
View File
@@ -24,8 +24,7 @@
#include <xrpl/beast/utility/PropertyStream.h>
#include <xrpl/server/Port.h>
#include <xrpl/server/detail/ServerImpl.h>
#include <boost/asio/io_context.hpp>
#include <boost/asio/io_service.hpp>
namespace ripple {
@@ -34,10 +33,10 @@ template <class Handler>
std::unique_ptr<Server>
make_Server(
Handler& handler,
boost::asio::io_context& io_context,
boost::asio::io_service& io_service,
beast::Journal journal)
{
return std::make_unique<ServerImpl<Handler>>(handler, io_context, journal);
return std::make_unique<ServerImpl<Handler>>(handler, io_service, journal);
}
} // namespace ripple
+4 -2
View File
@@ -86,7 +86,9 @@ public:
++iter)
{
typename BufferSequence::value_type const& buffer(*iter);
write(buffer.data(), boost::asio::buffer_size(buffer));
write(
boost::asio::buffer_cast<void const*>(buffer),
boost::asio::buffer_size(buffer));
}
}
@@ -100,7 +102,7 @@ public:
/** Detach the session.
This holds the session open so that the response can be sent
asynchronously. Calls to io_context::run made by the server
asynchronously. Calls to io_service::run made by the server
will not return until all detached sessions are closed.
*/
virtual std::shared_ptr<Session>
+10 -18
View File
@@ -24,12 +24,10 @@
#include <xrpl/beast/net/IPAddressConversion.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/server/Session.h>
#include <xrpl/server/detail/Spawn.h>
#include <xrpl/server/detail/io_list.h>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <boost/asio/strand.hpp>
#include <boost/asio/streambuf.hpp>
#include <boost/beast/core/stream_traits.hpp>
#include <boost/beast/http/dynamic_body.hpp>
@@ -216,8 +214,8 @@ BaseHTTPPeer<Handler, Impl>::BaseHTTPPeer(
ConstBufferSequence const& buffers)
: port_(port)
, handler_(handler)
, work_(boost::asio::make_work_guard(executor))
, strand_(boost::asio::make_strand(executor))
, work_(executor)
, strand_(executor)
, remote_address_(remote_address)
, journal_(journal)
{
@@ -302,13 +300,7 @@ BaseHTTPPeer<Handler, Impl>::do_read(yield_context do_yield)
{
complete_ = false;
error_code ec;
// Do not treat an established keep-alive waiting for its next request as
// an unfinished loopback request.
if (request_count_ == 0)
start_timer();
else
boost::beast::get_lowest_layer(impl().stream_)
.expires_after(std::chrono::seconds(timeoutSeconds));
start_timer();
boost::beast::http::async_read(
impl().stream_, read_buf_, message_, do_yield[ec]);
cancel_timer();
@@ -363,7 +355,7 @@ BaseHTTPPeer<Handler, Impl>::on_write(
return;
if (graceful_)
return do_close();
util::spawn(
boost::asio::spawn(
strand_,
std::bind(
&BaseHTTPPeer<Handler, Impl>::do_read,
@@ -382,7 +374,7 @@ BaseHTTPPeer<Handler, Impl>::do_writer(
{
auto const p = impl().shared_from_this();
resume = std::function<void(void)>([this, p, writer, keep_alive]() {
util::spawn(
boost::asio::spawn(
strand_,
std::bind(
&BaseHTTPPeer<Handler, Impl>::do_writer,
@@ -413,7 +405,7 @@ BaseHTTPPeer<Handler, Impl>::do_writer(
if (!keep_alive)
return do_close();
util::spawn(
boost::asio::spawn(
strand_,
std::bind(
&BaseHTTPPeer<Handler, Impl>::do_read,
@@ -455,14 +447,14 @@ BaseHTTPPeer<Handler, Impl>::write(
std::shared_ptr<Writer> const& writer,
bool keep_alive)
{
util::spawn(
boost::asio::spawn(bind_executor(
strand_,
std::bind(
&BaseHTTPPeer<Handler, Impl>::do_writer,
impl().shared_from_this(),
writer,
keep_alive,
std::placeholders::_1));
std::placeholders::_1)));
}
// DEPRECATED
@@ -497,12 +489,12 @@ BaseHTTPPeer<Handler, Impl>::complete()
}
// keep-alive
util::spawn(
boost::asio::spawn(bind_executor(
strand_,
std::bind(
&BaseHTTPPeer<Handler, Impl>::do_read,
impl().shared_from_this(),
std::placeholders::_1));
std::placeholders::_1)));
}
// DEPRECATED
+2 -2
View File
@@ -89,8 +89,8 @@ BasePeer<Handler, Impl>::BasePeer(
return "##" + std::to_string(++id) + " ";
}())
, j_(sink_)
, work_(boost::asio::make_work_guard(executor))
, strand_(boost::asio::make_strand(executor))
, work_(executor)
, strand_(executor)
{
}
+7 -20
View File
@@ -29,7 +29,6 @@
#include <xrpl/server/detail/BasePeer.h>
#include <xrpl/server/detail/LowestLayer.h>
#include <boost/asio/error.hpp>
#include <boost/beast/core/multi_buffer.hpp>
#include <boost/beast/http/message.hpp>
#include <boost/beast/websocket.hpp>
@@ -421,17 +420,11 @@ BaseWSPeer<Handler, Impl>::start_timer()
// Max seconds without completing a message
static constexpr std::chrono::seconds timeout{30};
static constexpr std::chrono::seconds timeoutLocal{3};
try
{
timer_.expires_after(
remote_endpoint().address().is_loopback() ? timeoutLocal : timeout);
}
catch (boost::system::system_error const& e)
{
return fail(e.code(), "start_timer");
}
error_code ec;
timer_.expires_from_now(
remote_endpoint().address().is_loopback() ? timeoutLocal : timeout, ec);
if (ec)
return fail(ec, "start_timer");
timer_.async_wait(bind_executor(
strand_,
std::bind(
@@ -445,14 +438,8 @@ template <class Handler, class Impl>
void
BaseWSPeer<Handler, Impl>::cancel_timer()
{
try
{
timer_.cancel();
}
catch (boost::system::system_error const&)
{
// ignored
}
error_code ec;
timer_.cancel(ec);
}
template <class Handler, class Impl>
+10 -11
View File
@@ -69,7 +69,7 @@ private:
stream_type stream_;
socket_type& socket_;
endpoint_type remote_address_;
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
boost::asio::io_context::strand strand_;
beast::Journal const j_;
public:
@@ -95,7 +95,7 @@ private:
Handler& handler_;
boost::asio::io_context& ioc_;
acceptor_type acceptor_;
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
boost::asio::io_context::strand strand_;
bool ssl_;
bool plain_;
@@ -155,7 +155,7 @@ Door<Handler>::Detector::Detector(
, stream_(std::move(stream))
, socket_(stream_.socket())
, remote_address_(remote_address)
, strand_(boost::asio::make_strand(ioc_))
, strand_(ioc_)
, j_(j)
{
}
@@ -164,7 +164,7 @@ template <class Handler>
void
Door<Handler>::Detector::run()
{
util::spawn(
boost::asio::spawn(
strand_,
std::bind(
&Detector::do_detect,
@@ -269,7 +269,7 @@ Door<Handler>::reOpen()
Throw<std::exception>();
}
acceptor_.listen(boost::asio::socket_base::max_listen_connections, ec);
acceptor_.listen(boost::asio::socket_base::max_connections, ec);
if (ec)
{
JLOG(j_.error()) << "Listen on port '" << port_.name
@@ -291,14 +291,14 @@ Door<Handler>::Door(
, handler_(handler)
, ioc_(io_context)
, acceptor_(io_context)
, strand_(boost::asio::make_strand(io_context))
, strand_(io_context)
, ssl_(
port_.protocol.count("https") > 0 ||
port_.protocol.count("wss") > 0 || port_.protocol.count("wss2") > 0 ||
port_.protocol.count("peer") > 0)
, plain_(
port_.protocol.count("http") > 0 || port_.protocol.count("ws") > 0 ||
port_.protocol.count("ws2") || port_.protocol.count("pwa"))
port_.protocol.count("ws2"))
{
reOpen();
}
@@ -307,7 +307,7 @@ template <class Handler>
void
Door<Handler>::run()
{
util::spawn(
boost::asio::spawn(
strand_,
std::bind(
&Door<Handler>::do_accept,
@@ -320,8 +320,7 @@ void
Door<Handler>::close()
{
if (!strand_.running_in_this_thread())
return boost::asio::post(
strand_,
return strand_.post(
std::bind(&Door<Handler>::close, this->shared_from_this()));
error_code ec;
acceptor_.close(ec);
@@ -401,7 +400,7 @@ Door<Handler>::do_accept(boost::asio::yield_context do_yield)
{
create(
ssl_,
boost::asio::const_buffer{},
boost::asio::null_buffers{},
std::move(stream),
remote_address);
}
+2 -2
View File
@@ -103,7 +103,7 @@ PlainHTTPPeer<Handler>::run()
{
if (!this->handler_.onAccept(this->session(), this->remote_address_))
{
util::spawn(
boost::asio::spawn(
this->strand_,
std::bind(&PlainHTTPPeer::do_close, this->shared_from_this()));
return;
@@ -112,7 +112,7 @@ PlainHTTPPeer<Handler>::run()
if (!socket_.is_open())
return;
util::spawn(
boost::asio::spawn(
this->strand_,
std::bind(
&PlainHTTPPeer::do_read,
+3 -3
View File
@@ -113,14 +113,14 @@ SSLHTTPPeer<Handler>::run()
{
if (!this->handler_.onAccept(this->session(), this->remote_address_))
{
util::spawn(
boost::asio::spawn(
this->strand_,
std::bind(&SSLHTTPPeer::do_close, this->shared_from_this()));
return;
}
if (!socket_.is_open())
return;
util::spawn(
boost::asio::spawn(
this->strand_,
std::bind(
&SSLHTTPPeer::do_handshake,
@@ -162,7 +162,7 @@ SSLHTTPPeer<Handler>::do_handshake(yield_context do_yield)
this->port().protocol.count("https") > 0;
if (http)
{
util::spawn(
boost::asio::spawn(
this->strand_,
std::bind(
&SSLHTTPPeer::do_read,
+13 -27
View File
@@ -27,8 +27,6 @@
#include <xrpl/server/detail/io_list.h>
#include <boost/asio.hpp>
#include <boost/asio/executor_work_guard.hpp>
#include <boost/asio/io_context.hpp>
#include <array>
#include <chrono>
@@ -88,11 +86,9 @@ private:
Handler& handler_;
beast::Journal const j_;
boost::asio::io_context& io_context_;
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
std::optional<boost::asio::executor_work_guard<
boost::asio::io_context::executor_type>>
work_;
boost::asio::io_service& io_service_;
boost::asio::io_service::strand strand_;
std::optional<boost::asio::io_service::work> work_;
std::mutex m_;
std::vector<Port> ports_;
@@ -105,7 +101,7 @@ private:
public:
ServerImpl(
Handler& handler,
boost::asio::io_context& io_context,
boost::asio::io_service& io_service,
beast::Journal journal);
~ServerImpl();
@@ -128,10 +124,10 @@ public:
return ios_;
}
boost::asio::io_context&
get_io_context()
boost::asio::io_service&
get_io_service()
{
return io_context_;
return io_service_;
}
bool
@@ -145,13 +141,13 @@ private:
template <class Handler>
ServerImpl<Handler>::ServerImpl(
Handler& handler,
boost::asio::io_context& io_context,
boost::asio::io_service& io_service,
beast::Journal journal)
: handler_(handler)
, j_(journal)
, io_context_(io_context)
, strand_(boost::asio::make_strand(io_context_))
, work_(std::in_place, boost::asio::make_work_guard(io_context_))
, io_service_(io_service)
, strand_(io_service_)
, work_(io_service_)
{
}
@@ -183,7 +179,7 @@ ServerImpl<Handler>::ports(std::vector<Port> const& ports)
{
// UDP-RPC door
if (auto sp = ios_.emplace<UDPDoor<Handler>>(
handler_, io_context_, internalPort, j_))
handler_, io_service_, internalPort, j_))
{
auto ep = sp->get_endpoint();
if (!internalPort.port)
@@ -197,7 +193,7 @@ ServerImpl<Handler>::ports(std::vector<Port> const& ports)
{
// Standard TCP door
if (auto sp = ios_.emplace<Door<Handler>>(
handler_, io_context_, internalPort, j_))
handler_, io_service_, internalPort, j_))
{
list_.push_back(sp);
@@ -208,16 +204,6 @@ ServerImpl<Handler>::ports(std::vector<Port> const& ports)
sp->run();
}
// UDP Superhighway (XUSH) datagrams arrive on the peer port
// number. TCP and UDP port numbers are independent, so this
// needs no socket sharing with the TCP door.
if (internalPort.has_peer() && internalPort.udp_highway)
{
if (auto sp = ios_.emplace<UDPDoor<Handler>>(
handler_, io_context_, internalPort, j_))
sp->run();
}
}
}
return eps;
-111
View File
@@ -1,111 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright(c) 2025 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_SERVER_SPAWN_H_INCLUDED
#define RIPPLE_SERVER_SPAWN_H_INCLUDED
#include <xrpl/basics/Log.h>
#include <boost/asio/spawn.hpp>
#include <boost/asio/strand.hpp>
#include <concepts>
#include <type_traits>
namespace ripple::util {
namespace impl {
template <typename T>
concept IsStrand = std::same_as<
std::decay_t<T>,
boost::asio::strand<typename std::decay_t<T>::inner_executor_type>>;
/**
* @brief A completion handler that restores `boost::asio::spawn`'s behaviour
* from Boost 1.83
*
* This is intended to be passed as the third argument to `boost::asio::spawn`
* so that exceptions are not ignored but propagated to `io_context.run()` call
* site.
*
* @param ePtr The exception that was caught on the coroutine
*/
inline constexpr auto kPROPAGATE_EXCEPTIONS = [](std::exception_ptr ePtr) {
if (ePtr)
{
try
{
std::rethrow_exception(ePtr);
}
catch (std::exception const& e)
{
JLOG(debugLog().warn()) << "Spawn exception: " << e.what();
throw;
}
catch (...)
{
JLOG(debugLog().warn()) << "Spawn exception: Unknown";
throw;
}
}
};
} // namespace impl
/**
* @brief Spawns a coroutine using `boost::asio::spawn`
*
* @note This uses kPROPAGATE_EXCEPTIONS to force asio to propagate exceptions
* through `io_context`
* @note Since implicit strand was removed from boost::asio::spawn this helper
* function adds the strand back
*
* @tparam Ctx The type of the context/strand
* @tparam F The type of the function to execute
* @param ctx The execution context
* @param func The function to execute. Must return `void`
*/
template <typename Ctx, typename F>
requires std::is_invocable_r_v<void, F, boost::asio::yield_context>
void
spawn(Ctx&& ctx, F&& func)
{
if constexpr (impl::IsStrand<Ctx>)
{
boost::asio::spawn(
std::forward<Ctx>(ctx),
std::forward<F>(func),
impl::kPROPAGATE_EXCEPTIONS);
}
else
{
// make_strand accepts an executor or an execution context directly.
// Going through get_associated_executor here resolved a plain
// executor to asio's inline executor, which cannot be stranded and
// did not compile; nothing in the tree had instantiated this branch.
boost::asio::spawn(
boost::asio::make_strand(std::forward<Ctx>(ctx)),
std::forward<F>(func),
impl::kPROPAGATE_EXCEPTIONS);
}
}
} // namespace ripple::util
#endif
+5 -10
View File
@@ -78,9 +78,10 @@ public:
error_code ec;
// Create UDP endpoint from port configuration
boost::asio::ip::udp::endpoint udp_endpoint(port_.ip, port_.port);
auto const addr = port_.ip.to_v4();
boost::asio::ip::udp::endpoint udp_endpoint(addr, port_.port);
socket_.open(udp_endpoint.protocol(), ec);
socket_.open(boost::asio::ip::udp::v4(), ec);
if (ec)
{
JLOG(j_.error()) << "UDP socket open failed: " << ec.message();
@@ -93,22 +94,17 @@ public:
{
JLOG(j_.error())
<< "UDP set reuse_address failed: " << ec.message();
close();
return;
}
socket_.bind(udp_endpoint, ec);
if (ec)
{
// Close the socket so that run() does not start receiving on an
// unbound socket, which would silently bind an ephemeral port.
JLOG(j_.error()) << "UDP socket bind to " << udp_endpoint
<< " failed: " << ec.message();
close();
JLOG(j_.error()) << "UDP socket bind failed: " << ec.message();
return;
}
JLOG(j_.info()) << "UDP listening on " << udp_endpoint;
JLOG(j_.info()) << "UDP-RPC listening on " << udp_endpoint;
}
endpoint_type
@@ -173,7 +169,6 @@ private:
handler_.onUDPMessage(
std::string(recv_buffer_.data(), bytes_transferred),
tcp_endpoint,
port_,
[this, tcp_endpoint](std::string const& response) {
do_send(response, tcp_endpoint);
});
+1 -1
View File
@@ -166,7 +166,7 @@ public:
May be called concurrently.
Preconditions:
No call to io_context::run on any io_context
No call to io_service::run on any io_service
used by work objects associated with this io_list
exists in the caller's call stack.
*/
+17 -16
View File
@@ -11,11 +11,11 @@ echo "START BUILDING (HOST)"
echo "Cleaning previously built binary"
rm -f release-build/xahaud
BUILD_CORES=$(echo "scale=0 ; $(nproc) / 1.337" | bc)
BUILD_CORES=$(echo "scale=0 ; `nproc` / 1.337" | bc)
if [[ "$GITHUB_REPOSITORY" == "" ]]; then
#Default
BUILD_CORES=${BUILD_CORES:-8}
BUILD_CORES=${BUILD_CORES:-8}
fi
# Ensure still works outside of GH Actions by setting these to /dev/null
@@ -31,19 +31,21 @@ echo "-- GITHUB_SHA: $GITHUB_SHA"
echo "-- GITHUB_RUN_NUMBER: $GITHUB_RUN_NUMBER"
echo "-- CONTAINER_NAME: $CONTAINER_NAME"
which docker 2>/dev/null 2>/dev/null
if [ "$?" -eq "1" ]; then
which docker 2> /dev/null 2> /dev/null
if [ "$?" -eq "1" ]
then
echo 'Docker not found. Install it first.'
exit 1
fi
stat .git 2>/dev/null 2>/dev/null
if [ "$?" -eq "1" ]; then
stat .git 2> /dev/null 2> /dev/null
if [ "$?" -eq "1" ]
then
echo 'Run this inside the source directory. (.git dir not found).'
exit 1
fi
STATIC_CONTAINER=$(docker ps -a | grep $CONTAINER_NAME | wc -l)
STATIC_CONTAINER=$(docker ps -a | grep $CONTAINER_NAME |wc -l)
CACHE_VOLUME_NAME="xahau-release-builder-cache"
@@ -55,14 +57,13 @@ if false; then
docker stop $CONTAINER_NAME
else
echo "No static container, build on temp container"
rm -rf release-build
mkdir -p release-build
rm -rf release-build;
mkdir -p release-build;
docker volume create $CACHE_VOLUME_NAME
# Create inline Dockerfile with environment setup for build-full.sh
DOCKERFILE_CONTENT=$(
cat <<'DOCKERFILE_EOF'
DOCKERFILE_CONTENT=$(cat <<'DOCKERFILE_EOF'
FROM ghcr.io/phusion/holy-build-box:4.0.1-amd64
ARG BUILD_CORES=8
@@ -217,7 +218,7 @@ RUN /hbb_exe/activate-exec bash -c "ccache -M 100G && \
ln -s ../../bin/ccache /usr/lib64/ccache/c++"
DOCKERFILE_EOF
)
)
# Build custom Docker image
IMAGE_NAME="xahaud-builder:latest"
@@ -227,14 +228,14 @@ DOCKERFILE_EOF
if [[ "$GITHUB_REPOSITORY" == "" ]]; then
# Non GH, local building
echo "Non-GH runner, local building, temp container"
docker run -i --user 0:$(id -g) --rm -v /data/builds:/data/builds -v $(pwd):/io -v "$CACHE_VOLUME_NAME":/cache --network host "$IMAGE_NAME" /hbb_exe/activate-exec bash -c "source /opt/rh/gcc-toolset-11/enable && bash -x /io/build-full.sh '$GITHUB_REPOSITORY' '$GITHUB_SHA' '$BUILD_CORES' '$GITHUB_RUN_NUMBER'"
docker run -i --user 0:$(id -g) --rm -v /data/builds:/data/builds -v `pwd`:/io -v "$CACHE_VOLUME_NAME":/cache --network host "$IMAGE_NAME" /hbb_exe/activate-exec bash -c "source /opt/rh/gcc-toolset-11/enable && bash -x /io/build-full.sh '$GITHUB_REPOSITORY' '$GITHUB_SHA' '$BUILD_CORES' '$GITHUB_RUN_NUMBER'"
else
# GH Action, runner
echo "GH Action, runner, clean & re-create create persistent container"
docker rm -f $CONTAINER_NAME
echo "echo 'Stopping container: $CONTAINER_NAME'" >>"$JOB_CLEANUP_SCRIPT"
echo "docker stop --time=15 \"$CONTAINER_NAME\" || echo 'Failed to stop container or container not running'" >>"$JOB_CLEANUP_SCRIPT"
docker run -di --user 0:$(id -g) --name $CONTAINER_NAME -v /data/builds:/data/builds -v $(pwd):/io -v "$CACHE_VOLUME_NAME":/cache --network host "$IMAGE_NAME" /hbb_exe/activate-exec bash
echo "echo 'Stopping container: $CONTAINER_NAME'" >> "$JOB_CLEANUP_SCRIPT"
echo "docker stop --time=15 \"$CONTAINER_NAME\" || echo 'Failed to stop container or container not running'" >> "$JOB_CLEANUP_SCRIPT"
docker run -di --user 0:$(id -g) --name $CONTAINER_NAME -v /data/builds:/data/builds -v `pwd`:/io -v "$CACHE_VOLUME_NAME":/cache --network host "$IMAGE_NAME" /hbb_exe/activate-exec bash
docker exec -i $CONTAINER_NAME /hbb_exe/activate-exec bash -c "source /opt/rh/gcc-toolset-11/enable && bash -x /io/build-full.sh '$GITHUB_REPOSITORY' '$GITHUB_SHA' '$BUILD_CORES' '$GITHUB_RUN_NUMBER'"
docker stop $CONTAINER_NAME
fi
Loaded 100 of 463 files, more files were not shown because too many files have changed in this diff. Show more