Compare commits

...

94 Commits

Author SHA1 Message Date
Sergey Kuznetsov
bcc0345c35 chore: Use released libxrpl 3.2.0 (#3105) 2026-06-16 17:31:10 +01:00
Sergey Kuznetsov
14645e1494 fix: Proxy support (#3103)
Port of two changes onto release/2.7.1:
- #3006 (d3381a1d): resolve proxy ip before processing any request
- #3043 (d7bcf6e7): re-resolve client ip when a proxy reuses a TCP
connection for different clients (resolveClientIp now returns
std::optional; extractClientIp made public; isProxyConnection_ tracked)
2026-06-09 16:25:02 +01:00
Sergey Kuznetsov
ce44aec245 ci: Use docker images with glibc version in conan (#3100) 2026-06-08 15:16:50 +01:00
Sergey Kuznetsov
94da8459dd ci: Use glibc version in conan profile (#3099) 2026-06-08 14:01:33 +01:00
Sergey Kuznetsov
8f3afd09e6 chore: Use libxrpl 3.2.0 (#3095) 2026-06-05 17:48:07 +01:00
Sergey Kuznetsov
6bb4953f16 ci: Remove arm (#3094) 2026-06-05 15:37:58 +01:00
Sergey Kuznetsov
884c1e8cde ci: Remove arm 2026-06-05 15:33:38 +01:00
Sergey Kuznetsov
7edeb14629 ci: Update docker actions, fix llvm repo (#3093) 2026-06-05 14:34:51 +01:00
Sergey Kuznetsov
b6241b7c7f ci: Update actions, fix llvm repo 2026-06-05 13:00:31 +01:00
Sergey Kuznetsov
2c715323a9 ci: Fix docker update ci (#3092) 2026-06-05 12:18:10 +01:00
Sergey Kuznetsov
b5889e4382 Fix docker update ci 2026-06-05 12:00:42 +01:00
Sergey Kuznetsov
df295ff6ed ci: Ubuntu 20.04 -> 22.04 (#3090) 2026-06-05 11:03:06 +01:00
Sergey Kuznetsov
419ab53caa ci: Ubuntu 20.04 -> 22.04 2026-06-04 17:16:37 +01:00
Ayaz Salikhov
3215e43c11 ci: Restart colima on macOS (#2923) 2026-01-15 19:03:47 +00:00
Ayaz Salikhov
e8c977e7de chore: Commits for 2.7.0-rc3 (#2912) 2026-01-13 16:53:44 +00:00
Ayaz Salikhov
6f6d8cdf25 ci: Change build date format (#2914) 2026-01-13 16:02:37 +00:00
Ayaz Salikhov
232838862a ci: Use env for BUILD_TYPE in reusable-build.yml (#2913) 2026-01-13 15:00:09 +00:00
Ayaz Salikhov
cd93b2a469 chore: Use actual build date instead of date of last commit for BUILD_DATE (#2911) 2026-01-13 14:50:49 +00:00
Ayaz Salikhov
95712c22b1 ci: Use images/actions with new tools / conan / cmake (#2909) 2026-01-13 14:50:13 +00:00
Ayaz Salikhov
14342e087c chore: Update tooling in Docker images (#2907) 2026-01-13 13:54:27 +00:00
Ayaz Salikhov
159024898e chore: Update gtest and spdlog (#2908) 2026-01-13 13:44:32 +00:00
Alex Kremer
c6be761f33 fix: Faster implementation of work queue (#2887) 2026-01-13 12:21:20 +00:00
Alex Kremer
f33f15c02d fix: Workaround an edge case exception in AmendmentCenter (#2897)
Fixes #2881
Better fix, including removal of exceptions for control flow will be done in #2895
2026-01-13 12:20:13 +00:00
Ayaz Salikhov
e733fadb45 ci: Pass version explicitly and don't rely on tags (#2904) 2026-01-12 17:31:09 +00:00
Ayaz Salikhov
a7ac7b54a8 ci: Show ccache stats with -vv (#2902) 2026-01-12 17:30:45 +00:00
Sergey Kuznetsov
88866ea6fd fix: No output from failed asserts in tests (#2905)
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2026-01-12 17:29:20 +00:00
Sergey Kuznetsov
bb39bce40b style: Fix clang-tidy error (#2901) 2026-01-12 14:31:34 +00:00
Ayaz Salikhov
bb3159bda0 feat: Add build information to clio_server --version (#2893) 2026-01-09 13:59:43 +00:00
Ayaz Salikhov
c0c5c14791 chore: Fix branch name and commit SHA for GitHub PRs (#2888) 2026-01-09 12:33:32 +00:00
github-actions[bot]
b0abe14057 style: clang-tidy auto fixes (#2891) 2026-01-09 10:07:21 +00:00
Bart
c9df784c4e ci: Use updated prepare-runner in actions and worfklows (#2889) 2026-01-08 20:13:49 +00:00
Alex Kremer
a9787b131e feat: Basic support for channels (#2859)
This PR implements go-like channels wrapper (on top of asio experimental
channels).
In the future this will be integrated into the AsyncFramework.

---------

Co-authored-by: Sergey Kuznetsov <skuznetsov@ripple.com>
2026-01-08 14:21:46 +00:00
Sergey Kuznetsov
9f76eabf0a feat: Option to save cache asyncronously (#2883)
This PR adds an option to save cache to file asynchronously in parallel
with shutting down the rest of Clio services.
2026-01-07 17:20:56 +00:00
github-actions[bot]
79c08fc735 style: Update pre-commit hooks (#2875)
Co-authored-by: mathbunnyru <12270691+mathbunnyru@users.noreply.github.com>
2026-01-05 01:10:10 +00:00
dependabot[bot]
2c9c5634ad ci: [DEPENDABOT] Bump actions/cache from 4.3.0 to 5.0.1 (#2871)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2025-12-23 01:46:14 +00:00
dependabot[bot]
850333528c ci: [DEPENDABOT] Bump docker/setup-buildx-action from 3.11.1 to 3.12.0 (#2870)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-22 11:52:41 +00:00
github-actions[bot]
8da4194fe2 style: clang-tidy auto fixes (#2874)
Co-authored-by: godexsoft <385326+godexsoft@users.noreply.github.com>
2025-12-22 11:52:23 +00:00
dependabot[bot]
4dece23ede ci: [DEPENDABOT] Bump docker/setup-buildx-action from 3.11.1 to 3.12.0 in /.github/actions/build-docker-image (#2872)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-22 11:52:04 +00:00
Ayaz Salikhov
c59fcf343f chore: Commits for 2.7.0-rc2 (#2868) 2025-12-19 15:45:02 +00:00
Alex Kremer
2327e81b0b fix: WorkQueue contention (#2866)
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2025-12-19 15:26:55 +00:00
Bart
5269ea0223 ci: Remove unnecessary creation of build directory (#2867) 2025-12-18 15:15:00 +00:00
github-actions[bot]
89fbcbf66a style: clang-tidy auto fixes (#2862) 2025-12-17 10:19:20 +00:00
Ayaz Salikhov
4b731a92ae ci: Update shared actions (#2852) 2025-12-16 20:54:48 +00:00
Ayaz Salikhov
7600e740a0 revert: "refactor: Add writing command to etl::SystemState" (#2860) 2025-12-16 15:06:35 +00:00
dependabot[bot]
db9a460867 ci: [DEPENDABOT] Bump actions/upload-artifact from 5.0.0 to 6.0.0 in /.github/actions/code-coverage (#2858)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-15 12:36:09 +00:00
dependabot[bot]
d5b0329e70 ci: [DEPENDABOT] Bump codecov/codecov-action from 5.5.1 to 5.5.2 (#2857)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-15 12:35:58 +00:00
dependabot[bot]
612434677a ci: [DEPENDABOT] Bump actions/upload-artifact from 5.0.0 to 6.0.0 (#2856)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-15 12:35:49 +00:00
dependabot[bot]
5a5a79fe30 ci: [DEPENDABOT] Bump actions/download-artifact from 6.0.0 to 7.0.0 (#2855)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-15 12:35:19 +00:00
dependabot[bot]
b1a49fdaab ci: [DEPENDABOT] Bump peter-evans/create-pull-request from 7.0.11 to 8.0.0 (#2854)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-15 12:35:11 +00:00
dependabot[bot]
f451996944 ci: [DEPENDABOT] Bump tj-actions/changed-files from 46.0.5 to 47.0.1 (#2853)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-15 12:34:55 +00:00
Ayaz Salikhov
488bb05d22 chore: Add a script to regenerate conan lockfile (#2849) 2025-12-12 16:40:00 +00:00
Ayaz Salikhov
f2c4275f61 ci: Put debian package to release (#2850) 2025-12-12 16:39:53 +00:00
github-actions[bot]
e9b98cf5b3 style: clang-tidy auto fixes (#2848)
Co-authored-by: godexsoft <385326+godexsoft@users.noreply.github.com>
2025-12-11 09:51:03 +00:00
Sergey Kuznetsov
3aa1854129 refactor: Add writing command to etl::SystemState (#2842) 2025-12-10 16:29:29 +00:00
Ayaz Salikhov
c35649eb6e chore: Commits for 2.7.0-rc1 (#2846) 2025-12-10 16:26:07 +00:00
Ayaz Salikhov
f2f5a6ab19 chore: Switch to xrpl/3.0.0 (#2843) 2025-12-10 16:06:21 +00:00
Ayaz Salikhov
1469d4b198 chore: Add systemd file to the debian package (#2844) 2025-12-10 16:02:43 +00:00
yinyiqian1
06ea05891d feat: Add DynamicMPT in account_mptoken_issuances (#2820)
Support DynamicMPT for the  account_mptoken_issuances handler.

Related commit:
eed757e0c4

The original spec for `DynamicMPT` can be found here:
https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0094-dynamic-MPT

---------

Co-authored-by: Sergey Kuznetsov <skuznetsov@ripple.com>
2025-12-10 11:36:24 +00:00
Ayaz Salikhov
c7c270cc03 style: Use shfmt for shell scripts (#2841) 2025-12-09 18:51:56 +00:00
Alex Kremer
c1f2f5b100 chore: Less delay in ETL taskman (#2802) 2025-12-09 12:25:00 +00:00
github-actions[bot]
bea0b51c8b style: clang-tidy auto fixes (#2840) 2025-12-09 10:36:53 +00:00
Alex Kremer
69b8e5bd06 feat: Add observable value util (#2831)
This implements a simple observable value. Can be used for a more
reactive approach. Will be used in ETL state and across the codebase
with time.
2025-12-08 16:44:43 +00:00
dependabot[bot]
33dc4ad95a ci: [DEPENDABOT] Bump ytanikin/pr-conventional-commits from 1.4.2 to 1.5.1 (#2835)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-08 10:52:52 +00:00
dependabot[bot]
13cbb405c7 ci: [DEPENDABOT] Bump peter-evans/create-pull-request from 7.0.9 to 7.0.11 (#2836)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-08 10:52:02 +00:00
dependabot[bot]
8a37a2e083 ci: [DEPENDABOT] Bump actions/checkout from 6.0.0 to 6.0.1 (#2837)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-08 10:51:32 +00:00
github-actions[bot]
f8b6c98219 style: Update pre-commit hooks (#2825)
Co-authored-by: mathbunnyru <12270691+mathbunnyru@users.noreply.github.com>
2025-12-07 18:42:50 +00:00
dependabot[bot]
92883bf012 ci: [DEPENDABOT] Bump docker/metadata-action from 5.9.0 to 5.10.0 in /.github/actions/build-docker-image (#2826)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-07 18:42:34 +00:00
Alex Kremer
88881e95dd chore: TSAN fix async-signal-unsafe (#2824)
Co-authored-by: Sergey Kuznetsov <skuznetsov@ripple.com>
2025-12-02 17:36:36 +00:00
Alex Kremer
94e70e4026 chore: Add mathbunnyru to maintainers (#2823) 2025-11-27 19:24:05 +00:00
github-actions[bot]
b534570cdd style: clang-tidy auto fixes (#2822)
Co-authored-by: godexsoft <385326+godexsoft@users.noreply.github.com>
2025-11-27 09:46:53 +00:00
Ayaz Salikhov
56fbfc63c2 chore: Update lockfile (#2818) 2025-11-26 17:06:38 +00:00
Ayaz Salikhov
80978657c0 ci: Update images to use latest Ninja (#2817) 2025-11-26 16:15:18 +00:00
Ayaz Salikhov
067449c3f8 chore: Install latest Ninja in images (#2813) 2025-11-26 13:54:19 +00:00
Ayaz Salikhov
946976546a chore: Use boost::asio::ssl::stream instead of boost::beast::ssl_stream (#2814) 2025-11-26 12:27:48 +00:00
github-actions[bot]
73e90b0a3f style: clang-tidy auto fixes (#2816)
Co-authored-by: godexsoft <385326+godexsoft@users.noreply.github.com>
2025-11-26 09:44:53 +00:00
Ayaz Salikhov
7681c58a3a style: Add black pre-commit hook (#2811) 2025-11-25 17:13:29 +00:00
Alex Kremer
391e7b07ab chore: WebServerAdminTestsSuit TSAN issues (#2809) 2025-11-25 12:17:24 +00:00
Alex Kremer
4eadaa85fa chore: Repeat-based tests TSAN fixes (#2810) 2025-11-25 12:15:43 +00:00
Ayaz Salikhov
1b1a46c429 feat: Handle prometheus requests in WorkQueue (#2790) 2025-11-24 16:17:45 +00:00
Ayaz Salikhov
89707d9668 ci: Run clang-tidy 3 times to make sure we don't have to fix again (#2803) 2025-11-24 12:19:34 +00:00
Ayaz Salikhov
ae260d1229 chore: Update spdlog and fmt libraries (#2804) 2025-11-24 11:27:29 +00:00
dependabot[bot]
058c05cfb6 ci: [DEPENDABOT] Bump actions/checkout from 5.0.0 to 6.0.0 (#2806)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 09:59:28 +00:00
dependabot[bot]
b2a7d185cb ci: [DEPENDABOT] Bump peter-evans/create-pull-request from 7.0.8 to 7.0.9 (#2805)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 09:58:51 +00:00
github-actions[bot]
9ea61ba6b9 style: clang-tidy auto fixes (#2801)
Co-authored-by: mathbunnyru <12270691+mathbunnyru@users.noreply.github.com>
2025-11-21 11:27:40 +00:00
github-actions[bot]
19157dec74 style: clang-tidy auto fixes (#2799)
Co-authored-by: mathbunnyru <12270691+mathbunnyru@users.noreply.github.com>
2025-11-21 11:02:07 +00:00
github-actions[bot]
42a6f516dc style: clang-tidy auto fixes (#2797) 2025-11-21 10:17:56 +00:00
emrearıyürek
2cd8226a11 refactor: Make getLedgerIndex return std::expected instead of throwing (#2788)
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
Co-authored-by: Sergey Kuznetsov <kuzzz99@gmail.com>
2025-11-20 17:46:15 +00:00
Sergey Kuznetsov
4da4b49eda chore: Commits for 2.7.0-b2 (#2795) 2025-11-20 14:53:12 +00:00
Sergey Kuznetsov
e3170203de fix: Print cache saving error (#2794) 2025-11-20 14:48:42 +00:00
Ayaz Salikhov
8b280e7742 ci: Always upload cache on develop (#2793) 2025-11-19 20:42:18 +00:00
Ayaz Salikhov
7ed30bc40d ci: Don't download ccache on develop branch (#2792) 2025-11-19 19:32:12 +00:00
Sergey Kuznetsov
ac608004bc docs: Fix graceful_period description (#2791) 2025-11-19 19:17:44 +00:00
Alex Kremer
6ab92ca0a6 chore: Enable TSAN in CI (#2785) 2025-11-19 18:06:33 +00:00
Alex Kremer
77387d8f9f chore: Add defines for asan/tsan to conan profile (#2784)
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2025-11-19 17:28:10 +00:00
360 changed files with 11154 additions and 6975 deletions

View File

@@ -14,7 +14,7 @@ runs:
using: composite
steps:
- name: Get number of processors
uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a
uses: XRPLF/actions/get-nproc@cf0433aa74563aead044a1e395610c96d65a37cf
id: nproc
with:
subtract: ${{ inputs.nproc_subtract }}

View File

@@ -34,32 +34,32 @@ runs:
steps:
- name: Login to DockerHub
if: ${{ inputs.push_image == 'true' && inputs.dockerhub_repo != '' }}
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
username: ${{ env.DOCKERHUB_USER }}
password: ${{ env.DOCKERHUB_PW }}
- name: Login to GitHub Container Registry
if: ${{ inputs.push_image == 'true' }}
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ env.GITHUB_TOKEN }}
- uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
- uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
with:
cache-image: false
- uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- uses: docker/metadata-action@318604b99e75e41977312d83839a89be02ca4893 # v5.9.0
- uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
id: meta
with:
images: ${{ inputs.images }}
tags: ${{ inputs.tags }}
- name: Build and push
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: ${{ inputs.directory }}
platforms: ${{ inputs.platforms }}

View File

@@ -37,6 +37,10 @@ inputs:
description: Whether to generate Debian package
required: true
default: "false"
version:
description: Version of the clio_server binary
required: false
default: ""
runs:
using: composite
@@ -57,6 +61,19 @@ runs:
STATIC: "${{ inputs.static == 'true' && 'ON' || 'OFF' }}"
TIME_TRACE: "${{ inputs.time_trace == 'true' && 'ON' || 'OFF' }}"
PACKAGE: "${{ inputs.package == 'true' && 'ON' || 'OFF' }}"
# GitHub creates a merge commit for a PR
# https://www.kenmuse.com/blog/the-many-shas-of-a-github-pull-request/
#
# We:
# - explicitly provide branch name
# - use `github.head_ref` to get the SHA of last commit in the PR branch
#
# This way it works both for PRs and pushes to branches.
GITHUB_BRANCH_NAME: "${{ github.head_ref || github.ref_name }}"
GITHUB_HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}"
#
# If tag is being pushed, or it's a nightly release, we use that version.
FORCE_CLIO_VERSION: ${{ inputs.version }}
run: |
cmake \
-B "${BUILD_DIR}" \

View File

@@ -24,7 +24,7 @@ runs:
-j8 --exclude-throw-branches
- name: Archive coverage report
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: coverage-report.xml
path: build/coverage_report.xml

View File

@@ -21,10 +21,6 @@ inputs:
runs:
using: composite
steps:
- name: Create build directory
shell: bash
run: mkdir -p "${{ inputs.build_dir }}"
- name: Run conan
shell: bash
env:

View File

@@ -4,7 +4,7 @@ import json
LINUX_OS = ["heavy", "heavy-arm64"]
LINUX_CONTAINERS = [
'{ "image": "ghcr.io/xrplf/clio-ci:62369411404eb32b0140603a785ff05e1dc36ce8" }'
'{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'
]
LINUX_COMPILERS = ["gcc", "clang"]

View File

@@ -40,9 +40,9 @@ mkdir -p "$PROFILES_DIR"
if [[ "$(uname)" == "Darwin" ]]; then
create_profile_with_sanitizers "apple-clang" "$APPLE_CLANG_PROFILE"
echo "include(apple-clang)" > "$PROFILES_DIR/default"
echo "include(apple-clang)" >"$PROFILES_DIR/default"
else
create_profile_with_sanitizers "clang" "$CLANG_PROFILE"
create_profile_with_sanitizers "gcc" "$GCC_PROFILE"
echo "include(gcc)" > "$PROFILES_DIR/default"
echo "include(gcc)" >"$PROFILES_DIR/default"
fi

25
.github/scripts/conan/regenerate_lockfile.sh vendored Executable file
View File

@@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -ex
TEMP_DIR=$(mktemp -d)
trap "rm -rf $TEMP_DIR" EXIT
echo "Using temporary CONAN_HOME: $TEMP_DIR"
# We use a temporary Conan home to avoid polluting the user's existing Conan
# configuration and to not use local cache (which leads to non-reproducible lockfiles).
export CONAN_HOME="$TEMP_DIR"
# Ensure that the xrplf remote is the first to be consulted, so any recipes we
# patched are used. We also add it there to not created huge diff when the
# official Conan Center Index is updated.
conan remote add --force --index 0 xrplf https://conan.ripplex.io
# Delete any existing lockfile.
rm -f conan.lock
# Create a new lockfile that is compatible with macOS.
# It should also work on Linux.
conan lock create . \
--profile:all=.github/scripts/conan/apple-clang-17.profile

View File

@@ -22,8 +22,8 @@ fi
TEST_BINARY=$1
if [[ ! -f "$TEST_BINARY" ]]; then
echo "Test binary not found: $TEST_BINARY"
exit 1
echo "Test binary not found: $TEST_BINARY"
exit 1
fi
TESTS=$($TEST_BINARY --gtest_list_tests | awk '/^ / {print suite $1} !/^ / {suite=$1}')
@@ -35,12 +35,12 @@ export TSAN_OPTIONS="die_after_fork=0"
export MallocNanoZone='0' # for MacOSX
for TEST in $TESTS; do
OUTPUT_FILE="$OUTPUT_DIR/${TEST//\//_}.log"
$TEST_BINARY --gtest_filter="$TEST" > "$OUTPUT_FILE" 2>&1
OUTPUT_FILE="$OUTPUT_DIR/${TEST//\//_}.log"
$TEST_BINARY --gtest_filter="$TEST" >"$OUTPUT_FILE" 2>&1
if [ $? -ne 0 ]; then
echo "'$TEST' failed a sanitizer check."
else
rm "$OUTPUT_FILE"
fi
if [ $? -ne 0 ]; then
echo "'$TEST' failed a sanitizer check."
else
rm "$OUTPUT_FILE"
fi
done

View File

@@ -20,5 +20,5 @@ for artifact_name in $(ls); do
rm "${artifact_name}/${BINARY_NAME}"
rm -r "${artifact_name}"
sha256sum "./${artifact_name}.zip" > "./${artifact_name}.zip.sha256sum"
sha256sum "./${artifact_name}.zip" >"./${artifact_name}.zip.sha256sum"
done

View File

@@ -48,11 +48,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Download Clio binary from artifact
if: ${{ inputs.artifact_name != null }}
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: ${{ inputs.artifact_name }}
path: ./docker/clio/artifact/

View File

@@ -49,7 +49,7 @@ jobs:
build_type: [Release, Debug]
container:
[
'{ "image": "ghcr.io/xrplf/clio-ci:62369411404eb32b0140603a785ff05e1dc36ce8" }',
'{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }',
]
static: [true]
@@ -79,7 +79,7 @@ jobs:
uses: ./.github/workflows/reusable-build.yml
with:
runs_on: heavy
container: '{ "image": "ghcr.io/xrplf/clio-ci:62369411404eb32b0140603a785ff05e1dc36ce8" }'
container: '{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'
conan_profile: gcc
build_type: Debug
download_ccache: true
@@ -92,35 +92,17 @@ jobs:
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
package:
name: Build packages
uses: ./.github/workflows/reusable-build.yml
with:
runs_on: heavy
container: '{ "image": "ghcr.io/xrplf/clio-ci:62369411404eb32b0140603a785ff05e1dc36ce8" }'
conan_profile: gcc
build_type: Release
download_ccache: true
upload_ccache: false
code_coverage: false
static: true
upload_clio_server: false
package: true
targets: package
analyze_build_time: false
check_config:
name: Check Config Description
needs: build-and-test
runs-on: heavy
container:
image: ghcr.io/xrplf/clio-ci:62369411404eb32b0140603a785ff05e1dc36ce8
image: ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: clio_server_Linux_Release_gcc

View File

@@ -21,17 +21,17 @@ jobs:
name: Build Clio / `libXRPL ${{ github.event.client_payload.version }}`
runs-on: heavy
container:
image: ghcr.io/xrplf/clio-ci:62369411404eb32b0140603a785ff05e1dc36ce8
image: ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
- name: Prepare runner
uses: XRPLF/actions/.github/actions/prepare-runner@8abb0722cbff83a9a2dc7d06c473f7a4964b7382
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
with:
disable_ccache: true
enable_ccache: false
- name: Update libXRPL version requirement
run: |
@@ -59,7 +59,7 @@ jobs:
run: strip build/clio_tests
- name: Upload clio_tests
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: clio_tests_check_libxrpl
path: build/clio_tests
@@ -69,10 +69,10 @@ jobs:
needs: build
runs-on: heavy
container:
image: ghcr.io/xrplf/clio-ci:62369411404eb32b0140603a785ff05e1dc36ce8
image: ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031
steps:
- uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: clio_tests_check_libxrpl
@@ -92,7 +92,7 @@ jobs:
issues: write
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Create an issue
uses: ./.github/actions/create-issue

View File

@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: ytanikin/pr-conventional-commits@b72758283dcbee706975950e96bc4bf323a8d8c0 # 1.4.2
- uses: ytanikin/pr-conventional-commits@fda730cb152c05a849d6d84325e50c6182d9d1e9 # 1.5.1
with:
task_types: '["build","feat","fix","docs","test","ci","style","refactor","perf","chore"]'
add_label: false

View File

@@ -31,7 +31,7 @@ jobs:
if: github.event_name != 'push' || contains(github.event.head_commit.message, 'clang-tidy auto fixes')
runs-on: heavy
container:
image: ghcr.io/xrplf/clio-ci:62369411404eb32b0140603a785ff05e1dc36ce8
image: ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031
permissions:
contents: write
@@ -39,14 +39,14 @@ jobs:
pull-requests: write
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
- name: Prepare runner
uses: XRPLF/actions/.github/actions/prepare-runner@8abb0722cbff83a9a2dc7d06c473f7a4964b7382
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
with:
disable_ccache: true
enable_ccache: false
- name: Run conan
uses: ./.github/actions/conan
@@ -59,30 +59,33 @@ jobs:
conan_profile: ${{ env.CONAN_PROFILE }}
- name: Get number of processors
uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a
uses: XRPLF/actions/get-nproc@cf0433aa74563aead044a1e395610c96d65a37cf
id: nproc
- name: Run clang-tidy
- name: Run clang-tidy (several times)
continue-on-error: true
id: run_clang_tidy
id: clang_tidy
run: |
run-clang-tidy-${{ env.LLVM_TOOLS_VERSION }} -p build -j "${{ steps.nproc.outputs.nproc }}" -fix -quiet 1>output.txt
# We run clang-tidy several times, because some fixes may enable new fixes in subsequent runs.
CLANG_TIDY_COMMAND="run-clang-tidy-${{ env.LLVM_TOOLS_VERSION }} -p build -j ${{ steps.nproc.outputs.nproc }} -fix -quiet"
${CLANG_TIDY_COMMAND} ||
${CLANG_TIDY_COMMAND} ||
${CLANG_TIDY_COMMAND}
- name: Check for changes
id: files_changed
continue-on-error: true
run: |
git diff --exit-code
- name: Fix local includes and clang-format style
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
if: ${{ steps.files_changed.outcome != 'success' }}
run: |
pre-commit run --all-files fix-local-includes || true
pre-commit run --all-files clang-format || true
- name: Print issues found
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: |
sed -i '/error\||/!d' ./output.txt
cat output.txt
rm output.txt
- name: Create an issue
if: ${{ steps.run_clang_tidy.outcome != 'success' && github.event_name != 'pull_request' }}
if: ${{ (steps.clang_tidy.outcome != 'success' || steps.files_changed.outcome != 'success') && github.event_name != 'pull_request' }}
id: create_issue
uses: ./.github/actions/create-issue
env:
@@ -95,7 +98,7 @@ jobs:
List of the issues found: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/
- uses: crazy-max/ghaction-import-gpg@e89d40939c28e39f97cf32126055eeae86ba74ec # v6.3.0
if: ${{ steps.run_clang_tidy.outcome != 'success' && github.event_name != 'pull_request' }}
if: ${{ steps.files_changed.outcome != 'success' && github.event_name != 'pull_request' }}
with:
gpg_private_key: ${{ secrets.ACTIONS_GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.ACTIONS_GPG_PASSPHRASE }}
@@ -103,8 +106,8 @@ jobs:
git_commit_gpgsign: true
- name: Create PR with fixes
if: ${{ steps.run_clang_tidy.outcome != 'success' && github.event_name != 'pull_request' }}
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
if: ${{ steps.files_changed.outcome != 'success' && github.event_name != 'pull_request' }}
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0
env:
GH_REPO: ${{ github.repository }}
GH_TOKEN: ${{ github.token }}
@@ -119,5 +122,5 @@ jobs:
reviewers: "godexsoft,kuznetsss,PeterChen13579,mathbunnyru"
- name: Fail the job
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
if: ${{ steps.clang_tidy.outcome != 'success' || steps.files_changed.outcome != 'success' }}
run: exit 1

View File

@@ -18,18 +18,18 @@ jobs:
build:
runs-on: ubuntu-latest
container:
image: ghcr.io/xrplf/clio-ci:62369411404eb32b0140603a785ff05e1dc36ce8
image: ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
lfs: true
- name: Prepare runner
uses: XRPLF/actions/.github/actions/prepare-runner@8abb0722cbff83a9a2dc7d06c473f7a4964b7382
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
with:
disable_ccache: true
enable_ccache: false
- name: Create build directory
run: mkdir build_docs

View File

@@ -28,8 +28,20 @@ defaults:
shell: bash
jobs:
get_date:
name: Get Date
runs-on: ubuntu-latest
outputs:
date: ${{ steps.get_date.outputs.date }}
steps:
- name: Get current date
id: get_date
run: |
echo "date=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT
build-and-test:
name: Build and Test
needs: get_date
strategy:
fail-fast: false
@@ -43,17 +55,17 @@ jobs:
conan_profile: gcc
build_type: Release
static: true
container: '{ "image": "ghcr.io/xrplf/clio-ci:62369411404eb32b0140603a785ff05e1dc36ce8" }'
container: '{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'
- os: heavy
conan_profile: gcc
build_type: Debug
static: true
container: '{ "image": "ghcr.io/xrplf/clio-ci:62369411404eb32b0140603a785ff05e1dc36ce8" }'
container: '{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'
- os: heavy
conan_profile: gcc.ubsan
build_type: Release
static: false
container: '{ "image": "ghcr.io/xrplf/clio-ci:62369411404eb32b0140603a785ff05e1dc36ce8" }'
container: '{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'
uses: ./.github/workflows/reusable-build-test.yml
with:
@@ -67,9 +79,31 @@ jobs:
upload_clio_server: true
download_ccache: false
upload_ccache: false
version: nightly-${{ needs.get_date.outputs.date }}
package:
name: Build debian package
needs: get_date
uses: ./.github/workflows/reusable-build.yml
with:
runs_on: heavy
container: '{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'
conan_profile: gcc
build_type: Release
download_ccache: false
upload_ccache: false
code_coverage: false
static: true
upload_clio_server: false
package: true
version: nightly-${{ needs.get_date.outputs.date }}
targets: package
analyze_build_time: false
analyze_build_time:
name: Analyze Build Time
needs: get_date
strategy:
fail-fast: false
@@ -77,7 +111,7 @@ jobs:
include:
- os: heavy
conan_profile: clang
container: '{ "image": "ghcr.io/xrplf/clio-ci:62369411404eb32b0140603a785ff05e1dc36ce8" }'
container: '{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'
static: true
- os: macos15
conan_profile: apple-clang
@@ -96,20 +130,10 @@ jobs:
upload_clio_server: false
targets: all
analyze_build_time: true
get_date:
name: Get Date
runs-on: ubuntu-latest
outputs:
date: ${{ steps.get_date.outputs.date }}
steps:
- name: Get current date
id: get_date
run: |
echo "date=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT
version: nightly-${{ needs.get_date.outputs.date }}
nightly_release:
needs: [build-and-test, get_date]
needs: [build-and-test, package, get_date]
uses: ./.github/workflows/reusable-release.yml
with:
delete_pattern: "nightly-*"
@@ -145,7 +169,7 @@ jobs:
issues: write
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Create an issue
uses: ./.github/actions/create-issue

View File

@@ -12,7 +12,7 @@ on:
jobs:
auto-update:
uses: XRPLF/actions/.github/workflows/pre-commit-autoupdate.yml@afbcbdafbe0ce5439492fb87eda6441371086386
uses: XRPLF/actions/.github/workflows/pre-commit-autoupdate.yml@ad4ab1ae5a54a4bab0e87294c31fc0729f788b2b
with:
sign_commit: true
committer: "Clio CI <skuznetsov@ripple.com>"

View File

@@ -8,7 +8,7 @@ on:
jobs:
run-hooks:
uses: XRPLF/actions/.github/workflows/pre-commit.yml@34790936fae4c6c751f62ec8c06696f9c1a5753a
uses: XRPLF/actions/.github/workflows/pre-commit.yml@282890f46d6921249d5659dd38babcb0bd8aef48
with:
runs_on: heavy
container: '{ "image": "ghcr.io/xrplf/clio-pre-commit:c117f470f2ef954520ab5d1c8a5ed2b9e68d6f8a" }'
container: '{ "image": "ghcr.io/xrplf/clio-pre-commit:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'

View File

@@ -29,7 +29,7 @@ jobs:
conan_profile: gcc
build_type: Release
static: true
container: '{ "image": "ghcr.io/xrplf/clio-ci:62369411404eb32b0140603a785ff05e1dc36ce8" }'
container: '{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'
uses: ./.github/workflows/reusable-build-test.yml
with:
@@ -43,10 +43,29 @@ jobs:
upload_clio_server: true
download_ccache: false
upload_ccache: false
expected_version: ${{ github.event_name == 'push' && github.ref_name || '' }}
version: ${{ github.event_name == 'push' && github.ref_name || '' }}
package:
name: Build debian package
uses: ./.github/workflows/reusable-build.yml
with:
runs_on: heavy
container: '{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'
conan_profile: gcc
build_type: Release
download_ccache: false
upload_ccache: false
code_coverage: false
static: true
upload_clio_server: false
package: true
version: ${{ github.event_name == 'push' && github.ref_name || '' }}
targets: package
analyze_build_time: false
release:
needs: build-and-test
needs: [build-and-test, package]
uses: ./.github/workflows/reusable-release.yml
with:
delete_pattern: ""

View File

@@ -63,18 +63,18 @@ on:
type: string
default: all
expected_version:
description: Expected version of the clio_server binary
required: false
type: string
default: ""
package:
description: Whether to generate Debian package
required: false
type: boolean
default: false
version:
description: Version of the clio_server binary
required: false
type: string
default: ""
jobs:
build:
uses: ./.github/workflows/reusable-build.yml
@@ -90,8 +90,8 @@ jobs:
upload_clio_server: ${{ inputs.upload_clio_server }}
targets: ${{ inputs.targets }}
analyze_build_time: false
expected_version: ${{ inputs.expected_version }}
package: ${{ inputs.package }}
version: ${{ inputs.version }}
test:
needs: build

View File

@@ -60,17 +60,17 @@ on:
required: true
type: boolean
expected_version:
description: Expected version of the clio_server binary
required: false
type: string
default: ""
package:
description: Whether to generate Debian package
required: false
type: boolean
version:
description: Version of the clio_server binary
required: false
type: string
default: ""
secrets:
CODECOV_TOKEN:
required: false
@@ -88,20 +88,16 @@ jobs:
steps:
- name: Cleanup workspace
if: ${{ runner.os == 'macOS' }}
uses: XRPLF/actions/.github/actions/cleanup-workspace@ea9970b7c211b18f4c8bcdb28c29f5711752029f
uses: XRPLF/actions/cleanup-workspace@cf0433aa74563aead044a1e395610c96d65a37cf
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
# We need to fetch tags to have correct version in the release
# The workaround is based on https://github.com/actions/checkout/issues/1467
fetch-tags: true
ref: ${{ github.ref }}
- name: Prepare runner
uses: XRPLF/actions/.github/actions/prepare-runner@8abb0722cbff83a9a2dc7d06c473f7a4964b7382
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
with:
disable_ccache: ${{ !inputs.download_ccache }}
enable_ccache: ${{ inputs.download_ccache }}
- name: Setup conan on macOS
if: ${{ runner.os == 'macOS' }}
@@ -116,9 +112,8 @@ jobs:
code_coverage: ${{ inputs.code_coverage }}
- name: Restore ccache cache
if: ${{ inputs.download_ccache }}
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
id: restore_cache
if: ${{ inputs.download_ccache && github.ref != 'refs/heads/develop' }}
uses: actions/cache/restore@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ steps.cache_key.outputs.key }}
@@ -140,6 +135,7 @@ jobs:
static: ${{ inputs.static }}
time_trace: ${{ inputs.analyze_build_time }}
package: ${{ inputs.package }}
version: ${{ inputs.version }}
- name: Build Clio
uses: ./.github/actions/build-clio
@@ -155,23 +151,20 @@ jobs:
- name: Upload build time analyze report
if: ${{ inputs.analyze_build_time }}
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: build_time_report_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
path: build_time_report.txt
- name: Show ccache's statistics
- name: Show ccache's statistics and zero it
if: ${{ inputs.download_ccache }}
id: ccache_stats
run: |
ccache -s > /tmp/ccache.stats
miss_rate=$(cat /tmp/ccache.stats | grep 'Misses' | head -n1 | sed 's/.*(\(.*\)%).*/\1/')
echo "miss_rate=${miss_rate}" >> $GITHUB_OUTPUT
cat /tmp/ccache.stats
ccache --show-stats -vv
ccache --zero-stats
- name: Save ccache cache
if: ${{ inputs.upload_ccache && github.ref == 'refs/heads/develop' && (steps.restore_cache.outputs.cache-hit != 'true' || steps.ccache_stats.outputs.miss_rate == '100.0') }}
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
if: ${{ inputs.upload_ccache && github.ref == 'refs/heads/develop' }}
uses: actions/cache/save@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ steps.cache_key.outputs.key }}
@@ -186,28 +179,28 @@ jobs:
- name: Upload clio_server
if: ${{ inputs.upload_clio_server && !inputs.code_coverage && !inputs.analyze_build_time }}
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: clio_server_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
path: build/clio_server
- name: Upload clio_tests
if: ${{ !inputs.code_coverage && !inputs.analyze_build_time && !inputs.package }}
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: clio_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
path: build/clio_tests
- name: Upload clio_integration_tests
if: ${{ !inputs.code_coverage && !inputs.analyze_build_time && !inputs.package }}
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: clio_integration_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
path: build/clio_integration_tests
- name: Upload Clio Linux package
if: ${{ inputs.package }}
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: clio_deb_package_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
path: build/*.deb
@@ -222,15 +215,20 @@ jobs:
if: ${{ inputs.code_coverage }}
uses: ./.github/actions/code-coverage
- name: Verify expected version
if: ${{ inputs.expected_version != '' }}
- name: Verify version is expected
if: ${{ inputs.version != '' }}
env:
INPUT_EXPECTED_VERSION: ${{ inputs.expected_version }}
INPUT_VERSION: ${{ inputs.version }}
BUILD_TYPE: ${{ inputs.build_type }}
run: |
set -e
EXPECTED_VERSION="clio-${INPUT_EXPECTED_VERSION}"
actual_version=$(./build/clio_server --version)
if [[ "$actual_version" != "$EXPECTED_VERSION" ]]; then
EXPECTED_VERSION="clio-${INPUT_VERSION}"
if [[ "${BUILD_TYPE}" == "Debug" ]]; then
EXPECTED_VERSION="${EXPECTED_VERSION}+DEBUG"
fi
actual_version=$(./build/clio_server --version | head -n 1)
if [[ "${actual_version}" != "${EXPECTED_VERSION}" ]]; then
echo "Expected version '${EXPECTED_VERSION}', but got '${actual_version}'"
exit 1
fi

View File

@@ -46,7 +46,7 @@ jobs:
release:
runs-on: heavy
container:
image: ghcr.io/xrplf/clio-ci:62369411404eb32b0140603a785ff05e1dc36ce8
image: ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031
env:
GH_REPO: ${{ github.repository }}
GH_TOKEN: ${{ github.token }}
@@ -55,20 +55,28 @@ jobs:
contents: write
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
- name: Prepare runner
uses: XRPLF/actions/.github/actions/prepare-runner@8abb0722cbff83a9a2dc7d06c473f7a4964b7382
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
with:
disable_ccache: true
enable_ccache: false
- uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
path: release_artifacts
pattern: clio_server_*
- name: Prepare release artifacts
run: .github/scripts/prepare-release-artifacts.sh release_artifacts
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
path: release_artifacts
pattern: clio_deb_package_*
- name: Create release notes
env:
RELEASE_HEADER: ${{ inputs.header }}
@@ -83,14 +91,10 @@ jobs:
LAST_TAG="$(gh release view --json tagName -q .tagName --repo XRPLF/clio)"
LAST_TAG_COMMIT="$(git rev-parse $LAST_TAG)"
BASE_COMMIT="$(git merge-base HEAD $LAST_TAG_COMMIT)"
git-cliff "${BASE_COMMIT}..HEAD" --ignore-tags "nightly|-b|-rc"
cat CHANGELOG.md >> "${RUNNER_TEMP}/release_notes.md"
- name: Prepare release artifacts
run: .github/scripts/prepare-release-artifacts.sh release_artifacts
git-cliff "${BASE_COMMIT}..HEAD" --ignore-tags "nightly|-b|-rc" >> "${RUNNER_TEMP}/release_notes.md"
- name: Upload release notes
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: release_notes_${{ inputs.version }}
path: "${RUNNER_TEMP}/release_notes.md"
@@ -122,4 +126,4 @@ jobs:
--target "${GITHUB_SHA}" \
${DRAFT_OPTION} \
--notes-file "${RUNNER_TEMP}/release_notes.md" \
./release_artifacts/clio_server*
./release_artifacts/clio_*

View File

@@ -52,13 +52,13 @@ jobs:
steps:
- name: Cleanup workspace
if: ${{ runner.os == 'macOS' }}
uses: XRPLF/actions/.github/actions/cleanup-workspace@ea9970b7c211b18f4c8bcdb28c29f5711752029f
uses: XRPLF/actions/cleanup-workspace@cf0433aa74563aead044a1e395610c96d65a37cf
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
- uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: clio_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
@@ -85,7 +85,7 @@ jobs:
- name: Upload sanitizer report
if: ${{ env.SANITIZER_IGNORE_ERRORS == 'true' && steps.check_report.outputs.found_report == 'true' }}
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: sanitizer_report_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
path: .sanitizer-report/*
@@ -124,7 +124,13 @@ jobs:
steps:
- name: Cleanup workspace
if: ${{ runner.os == 'macOS' }}
uses: XRPLF/actions/.github/actions/cleanup-workspace@ea9970b7c211b18f4c8bcdb28c29f5711752029f
uses: XRPLF/actions/cleanup-workspace@cf0433aa74563aead044a1e395610c96d65a37cf
- name: Restart colima
if: ${{ runner.os == 'macOS' }}
run: |
colima delete --force
colima start
- name: Spin up scylladb
if: ${{ runner.os == 'macOS' }}
@@ -146,7 +152,7 @@ jobs:
sleep 5
done
- uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: clio_integration_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}

View File

@@ -16,19 +16,19 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
- name: Download report artifact
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: coverage-report.xml
path: build
- name: Upload coverage report
if: ${{ hashFiles('build/coverage_report.xml') != '' }}
uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
with:
files: build/coverage_report.xml
fail_ci_if_error: true

View File

@@ -44,14 +44,13 @@ jobs:
uses: ./.github/workflows/reusable-build-test.yml
with:
runs_on: heavy
container: '{ "image": "ghcr.io/xrplf/clio-ci:62369411404eb32b0140603a785ff05e1dc36ce8" }'
container: '{ "image": "ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031" }'
download_ccache: false
upload_ccache: false
conan_profile: ${{ matrix.compiler }}${{ matrix.sanitizer_ext }}
build_type: ${{ matrix.build_type }}
static: false
# Currently, both gcc.tsan and clang.tsan unit tests hang
run_unit_tests: ${{ matrix.sanitizer_ext != '.tsan' }}
run_unit_tests: true
run_integration_tests: false
upload_clio_server: false
targets: clio_tests clio_integration_tests

View File

@@ -56,11 +56,11 @@ jobs:
needs: repo
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891 # v47.0.1
with:
files: "docker/compilers/gcc/**"
@@ -77,10 +77,10 @@ jobs:
push_image: ${{ github.event_name != 'pull_request' }}
directory: docker/compilers/gcc
tags: |
type=raw,value=amd64-latest
type=raw,value=amd64-${{ env.GCC_MAJOR_VERSION }}
type=raw,value=amd64-${{ env.GCC_VERSION }}
type=raw,value=amd64-${{ github.sha }}
type=raw,value=latest
type=raw,value=${{ env.GCC_MAJOR_VERSION }}
type=raw,value=${{ env.GCC_VERSION }}
type=raw,value=${{ github.sha }}
platforms: linux/amd64
build_args: |
GCC_MAJOR_VERSION=${{ env.GCC_MAJOR_VERSION }}
@@ -89,16 +89,17 @@ jobs:
dockerhub_description: GCC compiler for XRPLF/clio.
gcc-arm64:
if: false
name: Build and push GCC docker image (arm64)
runs-on: heavy-arm64
needs: repo
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46.0.5
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891 # v47.0.1
with:
files: "docker/compilers/gcc/**"
@@ -127,25 +128,26 @@ jobs:
dockerhub_description: GCC compiler for XRPLF/clio.
gcc-merge:
if: false
name: Merge and push multi-arch GCC docker image
runs-on: heavy
needs: [repo, gcc-amd64, gcc-arm64]
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891 # v47.0.1
with:
files: "docker/compilers/gcc/**"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Login to GitHub Container Registry
if: ${{ github.event_name != 'pull_request' }}
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -153,7 +155,7 @@ jobs:
- name: Login to DockerHub
if: ${{ github.repository_owner == 'XRPLF' && github.event_name != 'pull_request' }}
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_PW }}
@@ -174,7 +176,7 @@ jobs:
}
push_image ${{ needs.repo.outputs.GHCR_REPO }}/clio-gcc
if [[ ${{ github.repository_owner }} == 'XRPLF' ]]; then
push_image rippleci/clio_clang
push_image rippleci/clio_gcc
fi
clang:
@@ -183,11 +185,11 @@ jobs:
needs: repo
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891 # v47.0.1
with:
files: "docker/compilers/clang/**"
@@ -207,7 +209,8 @@ jobs:
type=raw,value=latest
type=raw,value=${{ env.CLANG_MAJOR_VERSION }}
type=raw,value=${{ github.sha }}
platforms: linux/amd64,linux/arm64
# platforms: linux/amd64,linux/arm64
platforms: linux/amd64
build_args: |
CLANG_MAJOR_VERSION=${{ env.CLANG_MAJOR_VERSION }}
dockerhub_repo: ${{ github.repository_owner == 'XRPLF' && 'rippleci/clio_clang' || '' }}
@@ -216,14 +219,14 @@ jobs:
tools-amd64:
name: Build and push tools docker image (amd64)
runs-on: heavy
needs: [repo, gcc-merge]
needs: [repo, gcc-amd64]
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891 # v47.0.1
with:
files: "docker/tools/**"
@@ -237,24 +240,25 @@ jobs:
push_image: ${{ github.event_name != 'pull_request' }}
directory: docker/tools
tags: |
type=raw,value=amd64-latest
type=raw,value=amd64-${{ github.sha }}
type=raw,value=latest
type=raw,value=${{ github.sha }}
platforms: linux/amd64
build_args: |
GHCR_REPO=${{ needs.repo.outputs.GHCR_REPO }}
GCC_VERSION=${{ env.GCC_VERSION }}
tools-arm64:
if: false
name: Build and push tools docker image (arm64)
runs-on: heavy-arm64
needs: [repo, gcc-merge]
needs: [repo, gcc-amd64]
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46.0.5
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891 # v47.0.1
with:
files: "docker/tools/**"
@@ -276,25 +280,26 @@ jobs:
GCC_VERSION=${{ env.GCC_VERSION }}
tools-merge:
if: false
name: Merge and push multi-arch tools docker image
runs-on: heavy
needs: [repo, tools-amd64, tools-arm64]
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891 # v47.0.1
with:
files: "docker/tools/**"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Login to GitHub Container Registry
if: ${{ github.event_name != 'pull_request' }}
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -313,10 +318,10 @@ jobs:
pre-commit:
name: Build and push pre-commit docker image
runs-on: heavy
needs: [repo, tools-merge]
needs: [repo, tools-amd64]
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/actions/build-docker-image
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -328,17 +333,18 @@ jobs:
tags: |
type=raw,value=latest
type=raw,value=${{ github.sha }}
platforms: linux/amd64,linux/arm64
# platforms: linux/amd64,linux/arm64
platforms: linux/amd64
build_args: |
GHCR_REPO=${{ needs.repo.outputs.GHCR_REPO }}
ci:
name: Build and push CI docker image
runs-on: heavy
needs: [repo, gcc-merge, clang, tools-merge]
needs: [repo, gcc-amd64, clang, tools-amd64]
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/actions/build-docker-image
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -354,7 +360,8 @@ jobs:
type=raw,value=latest
type=raw,value=gcc_${{ env.GCC_MAJOR_VERSION }}_clang_${{ env.CLANG_MAJOR_VERSION }}
type=raw,value=${{ github.sha }}
platforms: linux/amd64,linux/arm64
# platforms: linux/amd64,linux/arm64
platforms: linux/amd64
build_args: |
GHCR_REPO=${{ needs.repo.outputs.GHCR_REPO }}
CLANG_MAJOR_VERSION=${{ env.CLANG_MAJOR_VERSION }}

View File

@@ -22,6 +22,7 @@ on:
- .github/actions/conan/action.yml
- ".github/scripts/conan/**"
- "!.github/scripts/conan/regenerate_lockfile.sh"
- conanfile.py
- conan.lock
@@ -32,6 +33,7 @@ on:
- .github/actions/conan/action.yml
- ".github/scripts/conan/**"
- "!.github/scripts/conan/regenerate_lockfile.sh"
- conanfile.py
- conan.lock
@@ -50,7 +52,7 @@ jobs:
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Calculate conan matrix
id: set-matrix
@@ -73,12 +75,12 @@ jobs:
CONAN_PROFILE: ${{ matrix.compiler }}${{ matrix.sanitizer_ext }}
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Prepare runner
uses: XRPLF/actions/.github/actions/prepare-runner@8abb0722cbff83a9a2dc7d06c473f7a4964b7382
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
with:
disable_ccache: true
enable_ccache: false
- name: Setup conan on macOS
if: ${{ runner.os == 'macOS' }}

View File

@@ -29,12 +29,12 @@ repos:
# Autoformat: YAML, JSON, Markdown, etc.
- repo: https://github.com/rbubley/mirrors-prettier
rev: 5ba47274f9b181bce26a5150a725577f3c336011 # frozen: v3.6.2
rev: 14abee445aea04b39069c19b4bd54efff6775819 # frozen: v3.7.4
hooks:
- id: prettier
- repo: https://github.com/igorshubovych/markdownlint-cli
rev: 192ad822316c3a22fb3d3cc8aa6eafa0b8488360 # frozen: v0.45.0
rev: 76b3d32d3f4b965e1d6425253c59407420ae2c43 # frozen: v0.47.0
hooks:
- id: markdownlint-fix
exclude: LICENSE.md
@@ -58,6 +58,17 @@ repos:
--ignore-words=pre-commit-hooks/codespell_ignore.txt,
]
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 831207fd435b47aeffdf6af853097e64322b4d44 # frozen: 25.12.0
hooks:
- id: black
- repo: https://github.com/scop/pre-commit-shfmt
rev: 2a30809d16bc7a60d9b97353c797f42b510d3368 # frozen: v3.12.0-2
hooks:
- id: shfmt
args: ["-i", "4", "--write"]
# Running some C++ hooks before clang-format
# to ensure that the style is consistent.
- repo: local
@@ -83,7 +94,7 @@ repos:
language: script
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: 719856d56a62953b8d2839fb9e851f25c3cfeef8 # frozen: v21.1.2
rev: 75ca4ad908dc4a99f57921f29b7e6c1521e10b26 # frozen: v21.1.8
hooks:
- id: clang-format
args: [--style=file]

View File

@@ -75,11 +75,6 @@ if (san)
endif ()
target_compile_options(clio_options INTERFACE ${SAN_OPTIMIZATION_FLAG} ${SAN_FLAG} -fno-omit-frame-pointer)
if (san STREQUAL "address")
# ASAN needs these definitions as well as correct b2 flags in conan profile for sanitizers
target_compile_definitions(clio_options INTERFACE BOOST_USE_ASAN=1 BOOST_USE_UCONTEXT=1)
endif ()
target_link_libraries(clio_options INTERFACE ${SAN_FLAG} ${SAN_LIB})
endif ()

View File

@@ -180,6 +180,7 @@ Existing maintainers can resign, or be subject to a vote for removal at the behe
- [kuznetsss](https://github.com/kuznetsss) (Ripple)
- [legleux](https://github.com/legleux) (Ripple)
- [PeterChen13579](https://github.com/PeterChen13579) (Ripple)
- [mathbunnyru](https://github.com/mathbunnyru) (Ripple)
### Honorable ex-Maintainers

View File

@@ -9,10 +9,12 @@ target_sources(
util/async/ExecutionContextBenchmarks.cpp
# Logger
util/log/LoggerBenchmark.cpp
# WorkQueue
rpc/WorkQueueBenchmarks.cpp
)
include(deps/gbench)
target_include_directories(clio_benchmark PRIVATE .)
target_link_libraries(clio_benchmark PUBLIC clio_util benchmark::benchmark_main spdlog::spdlog)
target_link_libraries(clio_benchmark PUBLIC clio_util clio_rpc benchmark::benchmark_main spdlog::spdlog)
set_target_properties(clio_benchmark PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})

View File

@@ -0,0 +1,147 @@
//------------------------------------------------------------------------------
/*
This file is part of clio: https://github.com/XRPLF/clio
Copyright (c) 2025, the clio developers.
Permission to use, copy, modify, and 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.
*/
//==============================================================================
#include "rpc/WorkQueue.hpp"
#include "util/Assert.hpp"
#include "util/config/Array.hpp"
#include "util/config/ConfigConstraints.hpp"
#include "util/config/ConfigDefinition.hpp"
#include "util/config/ConfigValue.hpp"
#include "util/config/Types.hpp"
#include "util/log/Logger.hpp"
#include "util/prometheus/Prometheus.hpp"
#include <benchmark/benchmark.h>
#include <boost/asio/steady_timer.hpp>
#include <boost/asio/thread_pool.hpp>
#include <boost/json/object.hpp>
#include <algorithm>
#include <atomic>
#include <cassert>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <mutex>
#include <thread>
#include <vector>
using namespace rpc;
using namespace util::config;
namespace {
auto const kCONFIG = ClioConfigDefinition{
{"prometheus.compress_reply", ConfigValue{ConfigType::Boolean}.defaultValue(true)},
{"prometheus.enabled", ConfigValue{ConfigType::Boolean}.defaultValue(true)},
{"log.channels.[].channel", Array{ConfigValue{ConfigType::String}}},
{"log.channels.[].level", Array{ConfigValue{ConfigType::String}}},
{"log.level", ConfigValue{ConfigType::String}.defaultValue("info")},
{"log.format", ConfigValue{ConfigType::String}.defaultValue(R"(%Y-%m-%d %H:%M:%S.%f %^%3!l:%n%$ - %v)")},
{"log.is_async", ConfigValue{ConfigType::Boolean}.defaultValue(false)},
{"log.enable_console", ConfigValue{ConfigType::Boolean}.defaultValue(false)},
{"log.directory", ConfigValue{ConfigType::String}.optional()},
{"log.rotation_size", ConfigValue{ConfigType::Integer}.defaultValue(2048).withConstraint(gValidateUint32)},
{"log.directory_max_files", ConfigValue{ConfigType::Integer}.defaultValue(25).withConstraint(gValidateUint32)},
{"log.tag_style", ConfigValue{ConfigType::String}.defaultValue("none")},
};
// this should be a fixture but it did not work with Args very well
void
init()
{
static std::once_flag kONCE;
std::call_once(kONCE, [] {
PrometheusService::init(kCONFIG);
(void)util::LogService::init(kCONFIG);
});
}
} // namespace
static void
benchmarkWorkQueue(benchmark::State& state)
{
init();
auto const wqThreads = static_cast<uint32_t>(state.range(0));
auto const maxQueueSize = static_cast<uint32_t>(state.range(1));
auto const clientThreads = static_cast<uint32_t>(state.range(2));
auto const itemsPerClient = static_cast<uint32_t>(state.range(3));
auto const clientProcessingMs = static_cast<uint32_t>(state.range(4));
for (auto _ : state) {
std::atomic_size_t totalExecuted = 0uz;
std::atomic_size_t totalQueued = 0uz;
state.PauseTiming();
WorkQueue queue(wqThreads, maxQueueSize);
state.ResumeTiming();
std::vector<std::thread> threads;
threads.reserve(clientThreads);
for (auto t = 0uz; t < clientThreads; ++t) {
threads.emplace_back([&] {
for (auto i = 0uz; i < itemsPerClient; ++i) {
totalQueued += static_cast<std::size_t>(queue.postCoro(
[&clientProcessingMs, &totalExecuted](auto yield) {
++totalExecuted;
boost::asio::steady_timer timer(
yield.get_executor(), std::chrono::milliseconds{clientProcessingMs}
);
timer.async_wait(yield);
std::this_thread::sleep_for(std::chrono::microseconds{10});
},
/* isWhiteListed = */ false
));
}
});
}
for (auto& t : threads)
t.join();
queue.stop();
ASSERT(totalExecuted == totalQueued, "Totals don't match");
ASSERT(totalQueued <= itemsPerClient * clientThreads, "Queued more than requested");
if (maxQueueSize == 0) {
ASSERT(totalQueued == itemsPerClient * clientThreads, "Queued exactly the expected amount");
} else {
ASSERT(totalQueued >= std::min(maxQueueSize, itemsPerClient * clientThreads), "Queued less than expected");
}
}
}
// Usage example:
/*
./clio_benchmark \
--benchmark_repetitions=10 \
--benchmark_display_aggregates_only=true \
--benchmark_min_time=1x \
--benchmark_filter="WorkQueue"
*/
// TODO: figure out what happens on 1 thread
BENCHMARK(benchmarkWorkQueue)
->ArgsProduct({{2, 4, 8, 16}, {0, 5'000}, {4, 8, 16}, {1'000, 10'000}, {10, 100, 250}})
->Unit(benchmark::kMillisecond);

View File

@@ -49,8 +49,6 @@ postprocessors = [
]
# render body even when there are no releases to process
# render_always = true
# output file path
output = "CHANGELOG.md"
[git]
# parse the commits based on https://www.conventionalcommits.org

View File

@@ -1,42 +1,42 @@
find_package(Git REQUIRED)
set(GIT_COMMAND describe --tags --exact-match)
execute_process(
COMMAND ${GIT_EXECUTABLE} ${GIT_COMMAND}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE TAG
RESULT_VARIABLE RC
ERROR_VARIABLE ERR
OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE
)
if (RC EQUAL 0)
message(STATUS "Found tag '${TAG}' in git. Will use it as Clio version")
set(CLIO_VERSION "${TAG}")
set(DOC_CLIO_VERSION "${TAG}")
if (DEFINED ENV{GITHUB_BRANCH_NAME})
set(GIT_BUILD_BRANCH $ENV{GITHUB_BRANCH_NAME})
set(GIT_COMMIT_HASH $ENV{GITHUB_HEAD_SHA})
else ()
message(STATUS "Error finding tag in git: ${ERR}")
message(STATUS "Will use 'YYYYMMDDHMS-<branch>-<git-rev>' as Clio version")
set(GIT_COMMAND show -s --date=format:%Y%m%d%H%M%S --format=%cd)
execute_process(
COMMAND ${GIT_EXECUTABLE} ${GIT_COMMAND} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE DATE
OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY
)
set(GIT_COMMAND branch --show-current)
execute_process(
COMMAND ${GIT_EXECUTABLE} ${GIT_COMMAND} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE BRANCH
COMMAND ${GIT_EXECUTABLE} ${GIT_COMMAND} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE GIT_BUILD_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY
)
set(GIT_COMMAND rev-parse --short HEAD)
set(GIT_COMMAND rev-parse HEAD)
execute_process(
COMMAND ${GIT_EXECUTABLE} ${GIT_COMMAND} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE REV
COMMAND ${GIT_EXECUTABLE} ${GIT_COMMAND} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY
)
endif ()
set(CLIO_VERSION "${DATE}-${BRANCH}-${REV}")
execute_process(
COMMAND date +%Y%m%d%H%M%S WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE BUILD_DATE
OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY
)
message(STATUS "Git branch: ${GIT_BUILD_BRANCH}")
message(STATUS "Git commit hash: ${GIT_COMMIT_HASH}")
message(STATUS "Build date: ${BUILD_DATE}")
if (DEFINED ENV{FORCE_CLIO_VERSION} AND NOT "$ENV{FORCE_CLIO_VERSION}" STREQUAL "")
message(STATUS "Using explicitly provided '${FORCE_CLIO_VERSION}' as Clio version")
set(CLIO_VERSION "$ENV{FORCE_CLIO_VERSION}")
set(DOC_CLIO_VERSION "$ENV{FORCE_CLIO_VERSION}")
else ()
message(STATUS "Using 'YYYYMMDDHMS-<branch>-<git short rev>' as Clio version")
string(SUBSTRING ${GIT_COMMIT_HASH} 0 7 GIT_COMMIT_HASH_SHORT)
set(CLIO_VERSION "${BUILD_DATE}-${GIT_BUILD_BRANCH}-${GIT_COMMIT_HASH_SHORT}")
set(DOC_CLIO_VERSION "develop")
endif ()

View File

@@ -1,4 +1,4 @@
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_STATIC_RUNTIME ON)
find_package(Boost 1.82 REQUIRED CONFIG COMPONENTS program_options coroutine system log log_setup)
find_package(Boost 1.82 REQUIRED CONFIG COMPONENTS program_options system log log_setup)

View File

@@ -1,3 +1,3 @@
find_package(OpenSSL 1.1.1 REQUIRED CONFIG)
find_package(OpenSSL 3 REQUIRED CONFIG)
set_target_properties(OpenSSL::SSL PROPERTIES INTERFACE_COMPILE_DEFINITIONS OPENSSL_NO_SSL2)

View File

@@ -0,0 +1,17 @@
[Unit]
Description=Clio XRPL API server
Documentation=https://github.com/XRPLF/clio.git
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=@CLIO_INSTALL_DIR@/bin/clio_server @CLIO_INSTALL_DIR@/etc/config.json
Restart=on-failure
User=clio
Group=clio
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target

View File

@@ -11,3 +11,6 @@ file(READ docs/examples/config/example-config.json config)
string(REGEX REPLACE "./clio_log" "/var/log/clio/" config "${config}")
file(WRITE ${CMAKE_BINARY_DIR}/install-config.json "${config}")
install(FILES ${CMAKE_BINARY_DIR}/install-config.json DESTINATION etc RENAME config.json)
configure_file("${CMAKE_SOURCE_DIR}/cmake/install/clio.service.in" "${CMAKE_BINARY_DIR}/clio.service")
install(FILES "${CMAKE_BINARY_DIR}/clio.service" DESTINATION /lib/systemd/system)

View File

@@ -10,37 +10,36 @@ CLIO_BIN="$CLIO_PREFIX/bin/${CLIO_EXECUTABLE}"
CLIO_CONFIG="$CLIO_PREFIX/etc/config.json"
case "$1" in
configure)
if ! id -u "$USER_NAME" >/dev/null 2>&1; then
# Users who should not have a home directory should have their home directory set to /nonexistent
# https://www.debian.org/doc/debian-policy/ch-opersys.html#non-existent-home-directories
useradd \
--system \
--home-dir /nonexistent \
--no-create-home \
--shell /usr/sbin/nologin \
--comment "system user for ${CLIO_EXECUTABLE}" \
--user-group \
${USER_NAME}
fi
configure)
if ! id -u "$USER_NAME" >/dev/null 2>&1; then
# Users who should not have a home directory should have their home directory set to /nonexistent
# https://www.debian.org/doc/debian-policy/ch-opersys.html#non-existent-home-directories
useradd \
--system \
--home-dir /nonexistent \
--no-create-home \
--shell /usr/sbin/nologin \
--comment "system user for ${CLIO_EXECUTABLE}" \
--user-group \
${USER_NAME}
fi
install -d -o "$USER_NAME" -g "$GROUP_NAME" /var/log/clio
install -d -o "$USER_NAME" -g "$GROUP_NAME" /var/log/clio
if [ -f "$CLIO_CONFIG" ]; then
chown "$USER_NAME:$GROUP_NAME" "$CLIO_CONFIG"
fi
if [ -f "$CLIO_CONFIG" ]; then
chown "$USER_NAME:$GROUP_NAME" "$CLIO_CONFIG"
fi
chown -R "$USER_NAME:$GROUP_NAME" "$CLIO_PREFIX"
chown -R "$USER_NAME:$GROUP_NAME" "$CLIO_PREFIX"
ln -sf "$CLIO_BIN" "/usr/bin/${CLIO_EXECUTABLE}"
ln -sf "$CLIO_BIN" "/usr/bin/${CLIO_EXECUTABLE}"
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
;;
abort-upgrade | abort-remove | abort-deconfigure) ;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
exit 0

View File

@@ -1,57 +1,76 @@
{
"version": "0.5",
"requires": [
"zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1756234269.497",
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1756234289.683",
"xrpl/3.0.0-rc1#f5c8ecd42bdf511ad36f57bc702dacd2%1762975621.294",
"sqlite3/3.49.1#8631739a4c9b93bd3d6b753bac548a63%1756234266.869",
"spdlog/1.15.3#3ca0e9e6b83af4d0151e26541d140c86%1754401846.61",
"soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1756234262.318",
"re2/20230301#dfd6e2bf050eb90ddd8729cfb4c844a4%1756234257.976",
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1778091116.056",
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987",
"xrpl/3.2.0#c3c124909c6461012758a4fab7c90cd5%1781569913.756",
"sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1778091117.311",
"spdlog/1.17.0#bcbaaf7147bda6ad24ffbd1ac3d7142c%1768312128.781",
"soci/4.0.3#fe32b9ad5eb47e79ab9e45a68f363945%1774450067.231",
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1765850147.878",
"secp256k1/0.7.1#481881709eb0bdd0185a12b912bbe8ad%1770910500.329",
"rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1765850186.86",
"re2/20251105#8579cfd0bda4daf0683f9e3898f964b4%1774398111.888",
"rapidjson/cci.20220822#1b9d8c2256876a154172dc5cfbe447c6%1754325007.656",
"protobuf/3.21.12#d927114e28de9f4691a6bbcdd9a529d1%1756234251.614",
"openssl/1.1.1w#a8f0792d7c5121b954578a7149d23e03%1756223730.729",
"nudb/2.0.9#fb8dfd1a5557f5e0528114c2da17721e%1763150366.909",
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12",
"openssl/3.6.2#4789bbf131b77d0515d15e094c8f697f%1778071755.506",
"nudb/2.0.9#11149c73f8f2baff9a0198fe25971fc7%1775040983.408",
"minizip/1.2.13#9e87d57804bd372d6d1e32b1871517a3%1754325004.374",
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1756234228.999",
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914",
"libuv/1.46.0#dc28c1f653fa197f00db5b577a6f6011%1754325003.592",
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1756223727.64",
"libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1756230911.03",
"libarchive/3.8.1#5cf685686322e906cb42706ab7e099a8%1756234256.696",
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492",
"libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1765842973.03",
"libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1778091117.848",
"http_parser/2.9.4#98d91690d6fd021e9e624218a85d9d97%1754325001.385",
"gtest/1.14.0#f8f0757a574a8dd747d16af62d6eb1b7%1754325000.842",
"grpc/1.50.1#02291451d1e17200293a409410d1c4e1%1756234248.958",
"fmt/11.2.0#579bb2cdf4a7607621beea4eb4651e0f%1754324999.086",
"doctest/2.4.11#a4211dfc329a16ba9f280f9574025659%1756234220.819",
"date/3.0.4#f74bbba5a08fa388256688743136cb6f%1756234217.493",
"cassandra-cpp-driver/2.17.0#e50919efac8418c26be6671fd702540a%1754324997.363",
"c-ares/1.34.5#b78b91e7cfb1f11ce777a285bbf169c6%1756234217.915",
"bzip2/1.0.8#00b4a4658791c1f06914e087f0e792f5%1756234261.716",
"boost/1.83.0#5d975011d65b51abb2d2f6eb8386b368%1754325043.336",
"gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1768312129.152",
"grpc/1.78.1#b1a9e74b145cc471bed4dc64dc6eb2c1%1774467387.342",
"fmt/12.1.0#50abab23274d56bb8f42c94b3b9a40c7%1763984116.926",
"ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1765850143.772",
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772",
"cassandra-cpp-driver/2.17.0#bd3934138689482102c265d01288a316%1764175359.611",
"c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1774439234.681",
"bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837",
"boost/1.91.0#ea540ca2133d831b560036aa24dece3c%1778091165.282",
"benchmark/1.9.4#ce4403f7a24d3e1f907cd9da4b678be4%1754578869.672",
"abseil/20230802.1#f0f91485b111dc9837a68972cb19ca7b%1756234220.907"
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196"
],
"build_requires": [
"zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1756234269.497",
"protobuf/3.21.12#d927114e28de9f4691a6bbcdd9a529d1%1756234251.614",
"cmake/3.31.8#dde3bde00bb843687e55aea5afa0e220%1756234232.89",
"b2/5.3.3#107c15377719889654eb9a162a673975%1756234226.28"
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1778091116.056",
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12",
"cmake/4.3.0#b939a42e98f593fb34d3a8c5cc860359%1774439249.183",
"cmake/3.31.11#f325c933f618a1fcebc1e1c0babfd1ba%1774439246.719",
"b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1774439233.447",
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196"
],
"python_requires": [],
"overrides": {
"boost/1.83.0": [
null,
"boost/1.83.0#5d975011d65b51abb2d2f6eb8386b368"
"zlib/[>=1.2.11 <2]": [
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb"
],
"protobuf/3.21.12": [
"zlib/1.3.2": [
null,
"protobuf/3.21.12#d927114e28de9f4691a6bbcdd9a529d1"
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb"
],
"boost/1.91.0": [
"boost/1.91.0#ea540ca2133d831b560036aa24dece3c"
],
"protobuf/[>=5.27.0 <7]": [
"protobuf/6.33.5"
],
"lz4/1.9.4": [
"lz4/1.10.0"
],
"sqlite3/3.44.2": [
"sqlite3/3.49.1"
"boost/[>=1.83.0 <1.91.0]": [
"boost/1.91.0"
],
"sqlite3/[>=3.44 <4]": [
"sqlite3/3.53.0"
],
"boost/1.83.0": [
"boost/1.91.0"
],
"lz4/[>=1.9.4 <2]": [
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504"
]
},
"config_requires": []

View File

@@ -3,62 +3,68 @@ from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
class ClioConan(ConanFile):
name = 'clio'
license = 'ISC'
author = 'Alex Kremer <akremer@ripple.com>, John Freeman <jfreeman@ripple.com>, Ayaz Salikhov <asalikhov@ripple.com>'
url = 'https://github.com/xrplf/clio'
description = 'Clio RPC server'
settings = 'os', 'compiler', 'build_type', 'arch'
name = "clio"
license = "ISC"
author = "Alex Kremer <akremer@ripple.com>, John Freeman <jfreeman@ripple.com>, Ayaz Salikhov <asalikhov@ripple.com>"
url = "https://github.com/xrplf/clio"
description = "Clio RPC server"
settings = "os", "compiler", "build_type", "arch"
options = {}
requires = [
'boost/1.83.0',
'cassandra-cpp-driver/2.17.0',
'fmt/11.2.0',
'protobuf/3.21.12',
'grpc/1.50.1',
'openssl/1.1.1w',
'xrpl/3.0.0-rc1',
'zlib/1.3.1',
'libbacktrace/cci.20210118',
'spdlog/1.15.3',
"cassandra-cpp-driver/2.17.0",
"fmt/12.1.0",
"libbacktrace/cci.20210118",
"spdlog/1.17.0",
"xrpl/3.2.0",
]
default_options = {
'xrpl/*:tests': False,
'xrpl/*:rocksdb': False,
'cassandra-cpp-driver/*:shared': False,
'date/*:header_only': True,
'grpc/*:shared': False,
'grpc/*:secure': True,
'libpq/*:shared': False,
'lz4/*:shared': False,
'openssl/*:shared': False,
'protobuf/*:shared': False,
'protobuf/*:with_zlib': True,
'snappy/*:shared': False,
'gtest/*:no_main': True,
"cassandra-cpp-driver/*:shared": False,
"date/*:header_only": True,
"grpc/*:secure": True,
"grpc/*:shared": False,
"gtest/*:no_main": True,
"libpq/*:shared": False,
"lz4/*:shared": False,
"openssl/*:shared": False,
"protobuf/*:shared": False,
"protobuf/*:with_zlib": True,
"snappy/*:shared": False,
"xrpl/*:rocksdb": True, # TODO: revert to false when includes are fixed in libxrpl
"xrpl/*:tests": False,
}
exports_sources = (
'CMakeLists.txt', 'cmake/*', 'src/*'
)
exports_sources = ("CMakeLists.txt", "cmake/*", "src/*")
def requirements(self):
self.requires('gtest/1.14.0')
self.requires('benchmark/1.9.4')
self.requires("gtest/1.17.0")
self.requires("benchmark/1.9.4")
# Clio's own code includes grpc (<grpcpp/...>) and openssl (via
# <boost/asio/ssl>) headers directly, but xrpl does not re-export them
# (only boost/date/xxhash are required with transitive_headers=True).
# So they must be direct requirements of clio to get their include dirs;
# the version pins match xrpl's, so this does not change any package_id.
self.requires("grpc/1.78.1")
self.requires("openssl/3.6.2")
# Pin the remaining transitive deps to the exact versions xrpl uses.
# override=True only sets the version when the package appears
# transitively (it does not make them direct deps), and matches xrpl's
# force=True boost pin that overrides nudb's `boost < 1.91.0` cap.
self.requires("boost/1.91.0", override=True)
self.requires("zlib/1.3.2", override=True)
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 layout(self):
cmake_layout(self)
# Fix this setting to follow the default introduced in Conan 1.48
# to align with our build instructions.
self.folders.generators = 'build/generators'
self.folders.generators = "build/generators"
generators = 'CMakeDeps'
generators = "CMakeDeps"
def generate(self):
tc = CMakeToolchain(self)

View File

@@ -36,7 +36,6 @@ RUN apt-get update \
libmpfr-dev \
libncurses-dev \
make \
ninja-build \
wget \
zip \
&& apt-get clean \
@@ -55,7 +54,7 @@ RUN pip install -q --no-cache-dir \
# lxml 6.0.0 is not compatible with our image
'lxml<6.0.0' \
cmake \
conan==2.22.1 \
conan==2.24.0 \
gcovr \
# We're adding pre-commit to this image as well,
# because clang-tidy workflow requires it
@@ -64,7 +63,7 @@ RUN pip install -q --no-cache-dir \
# Install LLVM tools
ARG LLVM_TOOLS_VERSION=20
RUN echo "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-${LLVM_TOOLS_VERSION} main" >> /etc/apt/sources.list \
RUN echo "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-${LLVM_TOOLS_VERSION} main" >> /etc/apt/sources.list \
&& wget --progress=dot:giga -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
RUN apt-get update \
@@ -107,6 +106,7 @@ COPY --from=clio-tools \
/usr/local/bin/git-cliff \
/usr/local/bin/gh \
/usr/local/bin/gdb \
/usr/local/bin/ninja \
/usr/local/bin/
WORKDIR /root

View File

@@ -3,18 +3,19 @@
This image contains an environment to build [Clio](https://github.com/XRPLF/clio), check code and documentation.
It is used in [Clio Github Actions](https://github.com/XRPLF/clio/actions) but can also be used to compile Clio locally.
The image is based on Ubuntu 20.04 and contains:
The image is based on Ubuntu 22.04 and contains:
- ccache 4.12.1
- ccache 4.12.2
- Clang 19
- ClangBuildAnalyzer 1.6.0
- Conan 2.22.1
- Doxygen 1.15.0
- Conan 2.24.0
- Doxygen 1.16.1
- GCC 15.2.0
- GDB 16.3
- gh 2.82.1
- git-cliff 2.10.1
- GDB 17.1
- gh 2.83.2
- git-cliff 2.11.0
- mold 2.40.4
- Ninja 1.13.2
- Python 3.8
- and some other useful tools

View File

@@ -10,3 +10,5 @@ os=Linux
[conf]
tools.build:compiler_executables={"c": "/usr/bin/clang-19", "cpp": "/usr/bin/clang++-19"}
grpc/1.50.1:tools.build:cxxflags+=["-Wno-missing-template-arg-list-after-template-kw"]
user.package:libc_version=2.32
tools.info.package_id:confs+=["user.package:libc_version"]

View File

@@ -9,3 +9,5 @@ os=Linux
[conf]
tools.build:compiler_executables={"c": "/usr/bin/gcc-15", "cpp": "/usr/bin/g++-15"}
user.package:libc_version=2.32
tools.info.package_id:confs+=["user.package:libc_version"]

View File

@@ -3,7 +3,11 @@
{% set sanitizer_opt_map = {"asan": "address", "tsan": "thread", "ubsan": "undefined"} %}
{% set sanitizer = sanitizer_opt_map[sani] %}
{% set sanitizer_b2_flags_map = {"address": "define=BOOST_USE_ASAN=1 context-impl=ucontext address-sanitizer=on", "thread": "thread-sanitizer=on", "undefined": "undefined-sanitizer=on"} %}
{% set sanitizer_b2_flags_map = {
"address": "context-impl=ucontext address-sanitizer=norecover",
"thread": "context-impl=ucontext thread-sanitizer=norecover",
"undefined": "undefined-sanitizer=norecover"
} %}
{% set sanitizer_b2_flags_str = sanitizer_b2_flags_map[sanitizer] %}
{% set sanitizer_build_flags_str = "-fsanitize=" ~ sanitizer ~ " -g -O1 -fno-omit-frame-pointer" %}
@@ -24,4 +28,10 @@ tools.build:cxxflags+={{ sanitizer_build_flags }}
tools.build:exelinkflags+={{ sanitizer_link_flags }}
tools.build:sharedlinkflags+={{ sanitizer_link_flags }}
tools.info.package_id:confs+=["tools.build:cflags", "tools.build:cxxflags", "tools.build:exelinkflags", "tools.build:sharedlinkflags"]
{% if sanitizer == "address" %}
tools.build:defines+=["BOOST_USE_ASAN", "BOOST_USE_UCONTEXT"]
{% elif sanitizer == "thread" %}
tools.build:defines+=["BOOST_USE_TSAN", "BOOST_USE_UCONTEXT"]
{% endif %}
tools.info.package_id:confs+=["tools.build:cflags", "tools.build:cxxflags", "tools.build:exelinkflags", "tools.build:sharedlinkflags", "tools.build:defines"]

View File

@@ -1,4 +1,4 @@
FROM ubuntu:20.04
FROM ubuntu:22.04
ARG DEBIAN_FRONTEND=noninteractive

View File

@@ -1,4 +1,4 @@
ARG UBUNTU_VERSION=20.04
ARG UBUNTU_VERSION=22.04
ARG GCC_MAJOR_VERSION=invalid

View File

@@ -1,6 +1,6 @@
services:
clio_develop:
image: ghcr.io/xrplf/clio-ci:62369411404eb32b0140603a785ff05e1dc36ce8
image: ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031
volumes:
- clio_develop_conan_data:/root/.conan2/p
- clio_develop_ccache:/root/.ccache

View File

@@ -2,7 +2,7 @@
script_dir=$(dirname $0)
pushd $script_dir > /dev/null
pushd $script_dir >/dev/null
function start_container {
if [ -z "$(docker ps -q -f name=clio_develop)" ]; then
@@ -41,21 +41,26 @@ EOF
}
case $1 in
-h|--help)
print_help ;;
-h | --help)
print_help
;;
-t|--terminal)
open_terminal ;;
-t | --terminal)
open_terminal
;;
-s|--stop)
stop_container ;;
-s | --stop)
stop_container
;;
-*)
echo "Unknown option: $1"
print_help ;;
-*)
echo "Unknown option: $1"
print_help
;;
*)
run "$@" ;;
*)
run "$@"
;;
esac
popd > /dev/null
popd >/dev/null

View File

@@ -12,7 +12,6 @@ ARG BUILD_VERSION=0
RUN apt-get update \
&& apt-get install -y --no-install-recommends --no-install-suggests \
ninja-build \
python3 \
python3-pip \
software-properties-common \
@@ -24,6 +23,15 @@ RUN apt-get update \
WORKDIR /tmp
ARG NINJA_VERSION=1.13.2
RUN wget --progress=dot:giga "https://github.com/ninja-build/ninja/archive/refs/tags/v${NINJA_VERSION}.tar.gz" \
&& tar xf "v${NINJA_VERSION}.tar.gz" \
&& cd "ninja-${NINJA_VERSION}" \
&& ./configure.py --bootstrap \
&& mv ninja /usr/local/bin/ninja \
&& rm -rf /tmp/* /var/tmp/*
ARG MOLD_VERSION=2.40.4
RUN wget --progress=dot:giga "https://github.com/rui314/mold/archive/refs/tags/v${MOLD_VERSION}.tar.gz" \
&& tar xf "v${MOLD_VERSION}.tar.gz" \
@@ -34,7 +42,7 @@ RUN wget --progress=dot:giga "https://github.com/rui314/mold/archive/refs/tags/v
&& ninja install \
&& rm -rf /tmp/* /var/tmp/*
ARG CCACHE_VERSION=4.12.1
ARG CCACHE_VERSION=4.12.2
RUN wget --progress=dot:giga "https://github.com/ccache/ccache/releases/download/v${CCACHE_VERSION}/ccache-${CCACHE_VERSION}.tar.gz" \
&& tar xf "ccache-${CCACHE_VERSION}.tar.gz" \
&& cd "ccache-${CCACHE_VERSION}" \
@@ -51,7 +59,7 @@ RUN apt-get update \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
ARG DOXYGEN_VERSION=1.15.0
ARG DOXYGEN_VERSION=1.16.1
RUN wget --progress=dot:giga "https://github.com/doxygen/doxygen/releases/download/Release_${DOXYGEN_VERSION//./_}/doxygen-${DOXYGEN_VERSION}.src.tar.gz" \
&& tar xf "doxygen-${DOXYGEN_VERSION}.src.tar.gz" \
&& cd "doxygen-${DOXYGEN_VERSION}" \
@@ -71,13 +79,13 @@ RUN wget --progress=dot:giga "https://github.com/aras-p/ClangBuildAnalyzer/archi
&& ninja install \
&& rm -rf /tmp/* /var/tmp/*
ARG GIT_CLIFF_VERSION=2.10.1
ARG GIT_CLIFF_VERSION=2.11.0
RUN wget --progress=dot:giga "https://github.com/orhun/git-cliff/releases/download/v${GIT_CLIFF_VERSION}/git-cliff-${GIT_CLIFF_VERSION}-x86_64-unknown-linux-musl.tar.gz" \
&& tar xf git-cliff-${GIT_CLIFF_VERSION}-x86_64-unknown-linux-musl.tar.gz \
&& mv git-cliff-${GIT_CLIFF_VERSION}/git-cliff /usr/local/bin/git-cliff \
&& rm -rf /tmp/* /var/tmp/*
ARG GH_VERSION=2.82.1
ARG GH_VERSION=2.83.2
RUN wget --progress=dot:giga "https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_${TARGETARCH}.tar.gz" \
&& tar xf gh_${GH_VERSION}_linux_${TARGETARCH}.tar.gz \
&& mv gh_${GH_VERSION}_linux_${TARGETARCH}/bin/gh /usr/local/bin/gh \
@@ -92,7 +100,7 @@ RUN apt-get update \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
ARG GDB_VERSION=16.3
ARG GDB_VERSION=17.1
RUN wget --progress=dot:giga "https://sourceware.org/pub/gdb/releases/gdb-${GDB_VERSION}.tar.gz" \
&& tar xf "gdb-${GDB_VERSION}.tar.gz" \
&& cd "gdb-${GDB_VERSION}" \

View File

@@ -97,30 +97,14 @@ Now you should be able to download the prebuilt dependencies (including `xrpl` p
#### Conan lockfile
To achieve reproducible dependencies, we use [Conan lockfile](https://docs.conan.io/2/tutorial/versioning/lockfiles.html).
To achieve reproducible dependencies, we use a [Conan lockfile](https://docs.conan.io/2/tutorial/versioning/lockfiles.html).
The `conan.lock` file in the repository contains a "snapshot" of the current dependencies.
It is implicitly used when running `conan` commands, you don't need to specify it.
You have to update this file every time you add a new dependency or change a revision or version of an existing dependency.
> [!NOTE]
> Conan uses local cache by default when creating a lockfile.
>
> To ensure, that lockfile creation works the same way on all developer machines, you should clear the local cache before creating a new lockfile.
To create a new lockfile, run the following commands in the repository root:
```bash
conan remove '*' --confirm
rm conan.lock
# This ensure that xrplf remote is the first to be consulted
conan remote add --force --index 0 xrplf https://conan.ripplex.io
conan lock create .
```
> [!NOTE]
> If some dependencies are exclusive for some OS, you may need to run the last command for them adding `--profile:all <PROFILE>`.
To update a lockfile, run from the repository root: `./.github/scripts/conan/regenerate_lockfile.sh`
## Building Clio
@@ -191,7 +175,7 @@ Open the `index.html` file in your browser to see the documentation pages.
It is also possible to build Clio using [Docker](https://www.docker.com/) if you don't want to install all the dependencies on your machine.
```sh
docker run -it ghcr.io/xrplf/clio-ci:62369411404eb32b0140603a785ff05e1dc36ce8
docker run -it ghcr.io/xrplf/clio-ci:94da8459ddc30e2f0d88a98cba63a57b2cda3031
git clone https://github.com/XRPLF/clio
cd clio
```

View File

@@ -391,7 +391,7 @@ This document provides a list of all available Clio configuration properties in
- **Type**: double
- **Default value**: `10`
- **Constraints**: The value must be a positive double number.
- **Description**: The number of milliseconds the server waits to shutdown gracefully. If Clio does not shutdown gracefully after the specified value, it will be killed instead.
- **Description**: The number of seconds the server waits to shutdown gracefully. If Clio does not shutdown gracefully after the specified value, it will be killed instead.
### cache.num_diffs
@@ -457,6 +457,14 @@ This document provides a list of all available Clio configuration properties in
- **Constraints**: None
- **Description**: Max allowed difference between the latest sequence in DB and in cache file. If the cache file is too old (contains too low latest sequence) Clio will reject using it.
### cache.file.async_save
- **Required**: True
- **Type**: boolean
- **Default value**: `False`
- **Constraints**: None
- **Description**: When false, Clio waits for cache saving to finish before shutting down. When true, cache saving runs in parallel with other shutdown operations.
### log.channels.[].channel
- **Required**: False

View File

@@ -45,7 +45,7 @@ if [[ "1.14.0" > "$version" ]]; then
ERROR
-----------------------------------------------------------------------------
A minimum of version 1.14 of `which doxygen` is required.
A minimum of version 1.14 of $(which doxygen) is required.
Your version is $version. Please upgrade it.
Your changes may fail CI checks.
@@ -55,26 +55,26 @@ EOF
exit 0
fi
mkdir -p ${DOCDIR} > /dev/null 2>&1
pushd ${DOCDIR} > /dev/null 2>&1
mkdir -p ${DOCDIR} >/dev/null 2>&1
pushd ${DOCDIR} >/dev/null 2>&1
cat ${ROOT}/docs/Doxyfile | \
sed \
-e "s/\${LINT}/YES/" \
-e "s/\${WARN_AS_ERROR}/NO/" \
-e "s!\${SOURCE}!${ROOT}!" \
-e "s/\${USE_DOT}/NO/" \
-e "s/\${EXCLUDES}/impl/" \
| ${DOXYGEN} - 2> ${TMPFILE} 1> /dev/null
cat ${ROOT}/docs/Doxyfile |
sed \
-e "s/\${LINT}/YES/" \
-e "s/\${WARN_AS_ERROR}/NO/" \
-e "s!\${SOURCE}!${ROOT}!" \
-e "s/\${USE_DOT}/NO/" \
-e "s/\${EXCLUDES}/impl/" |
${DOXYGEN} - 2>${TMPFILE} 1>/dev/null
# We don't want to check for default values and typedefs as well as for member variables
OUT=$(cat ${TMPFILE} \
| grep -v "=default" \
| grep -v "\(variable\)" \
| grep -v "\(typedef\)")
OUT=$(cat ${TMPFILE} |
grep -v "=default" |
grep -v "\(variable\)" |
grep -v "\(typedef\)")
rm -rf ${TMPFILE} > /dev/null 2>&1
popd > /dev/null 2>&1
rm -rf ${TMPFILE} >/dev/null 2>&1
popd >/dev/null 2>&1
if [[ ! -z "$OUT" ]]; then
cat <<EOF

View File

@@ -23,10 +23,10 @@ fix_includes() {
file_path_fixed="${file_path}.tmp.fixed"
# Make all includes to be <...> style
sed -E 's|#include "(.*)"|#include <\1>|g' "$file_path" > "$file_path_all_global"
sed -E 's|#include "(.*)"|#include <\1>|g' "$file_path" >"$file_path_all_global"
# Make local includes to be "..." style
sed -E "s|#include <(($main_src_dirs)/.*)>|#include \"\1\"|g" "$file_path_all_global" > "$file_path_fixed"
sed -E "s|#include <(($main_src_dirs)/.*)>|#include \"\1\"|g" "$file_path_all_global" >"$file_path_fixed"
rm "$file_path_all_global"
# Check if the temporary file is different from the original file

View File

@@ -4,7 +4,6 @@ import argparse
import re
from pathlib import Path
PATTERN = r'R"JSON\((.*?)\)JSON"'
@@ -40,6 +39,7 @@ def fix_colon_spacing(cpp_content: str) -> str:
raw_json = match.group(1)
raw_json = re.sub(r'":\n\s*(\[|\{)', r'": \1', raw_json)
return f'R"JSON({raw_json})JSON"'
return re.sub(PATTERN, replace_json, cpp_content, flags=re.DOTALL)
@@ -49,12 +49,12 @@ def fix_indentation(cpp_content: str) -> str:
lines = cpp_content.splitlines()
ends_with_newline = cpp_content.endswith('\n')
ends_with_newline = cpp_content.endswith("\n")
def find_indentation(line: str) -> int:
return len(line) - len(line.lstrip())
for (line_num, (line, next_line)) in enumerate(zip(lines[:-1], lines[1:])):
for line_num, (line, next_line) in enumerate(zip(lines[:-1], lines[1:])):
if "JSON(" in line and ")JSON" not in line:
indent = find_indentation(line)
next_indent = find_indentation(next_line)
@@ -69,7 +69,11 @@ def fix_indentation(cpp_content: str) -> str:
if ")JSON" in lines[i]:
lines[i] = " " * indent + lines[i].lstrip()
break
lines[i] = lines[i][by_how_much:] if by_how_much > 0 else " " * (-by_how_much) + lines[i]
lines[i] = (
lines[i][by_how_much:]
if by_how_much > 0
else " " * (-by_how_much) + lines[i]
)
result = "\n".join(lines)

View File

@@ -4,7 +4,7 @@
#
set -e -o pipefail
if ! command -v gofmt &> /dev/null ; then
if ! command -v gofmt &>/dev/null; then
echo "gofmt not installed or available in the PATH" >&2
exit 1
fi

View File

@@ -1,5 +1,4 @@
#!/bin/sh
#!/bin/bash
# git for-each-ref refs/tags # see which tags are annotated and which are lightweight. Annotated tags are "tag" objects.
# # Set these so your commits and tags are always signed
@@ -7,7 +6,7 @@
# git config tag.gpgsign true
verify_commit_signed() {
if git verify-commit HEAD &> /dev/null; then
if git verify-commit HEAD &>/dev/null; then
:
# echo "HEAD commit seems signed..."
else
@@ -17,7 +16,7 @@ verify_commit_signed() {
}
verify_tag() {
if git describe --exact-match --tags HEAD &> /dev/null; then
if git describe --exact-match --tags HEAD &>/dev/null; then
: # You might be ok to push
# echo "Tag is annotated."
return 0
@@ -28,7 +27,7 @@ verify_tag() {
}
verify_tag_signed() {
if git verify-tag "$version" &> /dev/null ; then
if git verify-tag "$version" &>/dev/null; then
: # ok, I guess we'll let you push
# echo "Tag appears signed"
return 0
@@ -40,11 +39,11 @@ verify_tag_signed() {
}
# Check some things if we're pushing a branch called "release/"
if echo "$PRE_COMMIT_REMOTE_BRANCH" | grep ^refs\/heads\/release\/ &> /dev/null ; then
if echo "$PRE_COMMIT_REMOTE_BRANCH" | grep ^refs\/heads\/release\/ &>/dev/null; then
version=$(git tag --points-at HEAD)
echo "Looks like you're trying to push a $version release..."
echo "Making sure you've signed and tagged it."
if verify_commit_signed && verify_tag && verify_tag_signed ; then
if verify_commit_signed && verify_tag && verify_tag_signed; then
: # Ok, I guess you can push
else
exit 1

View File

@@ -77,7 +77,10 @@ CliArgs::parse(int argc, char const* argv[])
}
if (parsed.contains("version")) {
std::cout << util::build::getClioFullVersionString() << '\n';
std::cout << util::build::getClioFullVersionString() << '\n'
<< "Git commit hash: " << util::build::getGitCommitHash() << '\n'
<< "Git build branch: " << util::build::getGitBuildBranch() << '\n'
<< "Build date: " << util::build::getBuildDate() << '\n';
return Action{Action::Exit{EXIT_SUCCESS}};
}

View File

@@ -91,6 +91,7 @@ ClioApplication::ClioApplication(util::config::ClioConfigDefinition const& confi
{
LOG(util::LogService::info()) << "Clio version: " << util::build::getClioFullVersionString();
signalsHandler_.subscribeToStop([this]() { appStopper_.stop(); });
appStopper_.setOnComplete([this]() { signalsHandler_.notifyGracefulShutdownComplete(); });
}
int
@@ -182,7 +183,7 @@ ClioApplication::run(bool const useNgWebServer)
return EXIT_FAILURE;
}
httpServer->onGet("/metrics", MetricsHandler{adminVerifier});
httpServer->onGet("/metrics", MetricsHandler{adminVerifier, workQueue});
httpServer->onGet("/health", HealthCheckHandler{});
httpServer->onGet("/cache_state", CacheStateHandler{cache});
auto requestHandler = RequestHandler{adminVerifier, handler};

View File

@@ -38,7 +38,18 @@ Stopper::~Stopper()
void
Stopper::setOnStop(std::function<void(boost::asio::yield_context)> cb)
{
util::spawn(ctx_, std::move(cb));
util::spawn(ctx_, [this, cb = std::move(cb)](auto yield) {
cb(yield);
if (onCompleteCallback_)
onCompleteCallback_();
});
}
void
Stopper::setOnComplete(std::function<void()> cb)
{
onCompleteCallback_ = std::move(cb);
}
void

View File

@@ -43,6 +43,7 @@ namespace app {
class Stopper {
boost::asio::io_context ctx_;
std::thread worker_;
std::function<void()> onCompleteCallback_;
public:
/**
@@ -58,6 +59,14 @@ public:
void
setOnStop(std::function<void(boost::asio::yield_context)> cb);
/**
* @brief Set the callback to be called when graceful shutdown completes.
*
* @param cb The callback to be called when shutdown completes.
*/
void
setOnComplete(std::function<void()> cb);
/**
* @brief Stop the application and run the shutdown tasks.
*/

View File

@@ -19,7 +19,10 @@
#include "app/WebHandlers.hpp"
#include "rpc/Errors.hpp"
#include "rpc/WorkQueue.hpp"
#include "util/Assert.hpp"
#include "util/CoroutineGroup.hpp"
#include "util/prometheus/Http.hpp"
#include "web/AdminVerificationStrategy.hpp"
#include "web/SubscriptionContextInterface.hpp"
@@ -31,6 +34,7 @@
#include <boost/asio/spawn.hpp>
#include <boost/beast/http/status.hpp>
#include <functional>
#include <memory>
#include <optional>
#include <string>
@@ -76,8 +80,8 @@ DisconnectHook::operator()(web::ng::Connection const& connection)
dosguard_.get().decrement(connection.ip());
}
MetricsHandler::MetricsHandler(std::shared_ptr<web::AdminVerificationStrategy> adminVerifier)
: adminVerifier_{std::move(adminVerifier)}
MetricsHandler::MetricsHandler(std::shared_ptr<web::AdminVerificationStrategy> adminVerifier, rpc::WorkQueue& workQueue)
: adminVerifier_{std::move(adminVerifier)}, workQueue_{std::ref(workQueue)}
{
}
@@ -86,19 +90,45 @@ MetricsHandler::operator()(
web::ng::Request const& request,
web::ng::ConnectionMetadata& connectionMetadata,
web::SubscriptionContextPtr,
boost::asio::yield_context
boost::asio::yield_context yield
)
{
auto const maybeHttpRequest = request.asHttpRequest();
ASSERT(maybeHttpRequest.has_value(), "Got not a http request in Get");
auto const& httpRequest = maybeHttpRequest->get();
std::optional<web::ng::Response> response;
util::CoroutineGroup coroutineGroup{yield, 1};
auto const onTaskComplete = coroutineGroup.registerForeign(yield);
ASSERT(onTaskComplete.has_value(), "Coroutine group can't be full");
// FIXME(#1702): Using veb server thread to handle prometheus request. Better to post on work queue.
auto maybeResponse = util::prometheus::handlePrometheusRequest(
httpRequest, adminVerifier_->isAdmin(httpRequest, connectionMetadata.ip())
bool const postSuccessful = workQueue_.get().postCoro(
[this, &request, &response, &onTaskComplete = onTaskComplete.value(), &connectionMetadata](
boost::asio::yield_context
) mutable {
auto const maybeHttpRequest = request.asHttpRequest();
ASSERT(maybeHttpRequest.has_value(), "Got not a http request in Get");
auto const& httpRequest = maybeHttpRequest->get();
auto maybeResponse = util::prometheus::handlePrometheusRequest(
httpRequest, adminVerifier_->isAdmin(httpRequest, connectionMetadata.ip())
);
ASSERT(maybeResponse.has_value(), "Got unexpected request for Prometheus");
response = web::ng::Response{std::move(maybeResponse).value(), request};
// notify the coroutine group that the foreign task is done
onTaskComplete();
},
/* isWhiteListed= */ true,
rpc::WorkQueue::Priority::High
);
ASSERT(maybeResponse.has_value(), "Got unexpected request for Prometheus");
return web::ng::Response{std::move(maybeResponse).value(), request};
if (!postSuccessful) {
return web::ng::Response{
boost::beast::http::status::too_many_requests, rpc::makeError(rpc::RippledError::RpcTooBusy), request
};
}
// Put the coroutine to sleep until the foreign task is done
coroutineGroup.asyncWait(yield);
ASSERT(response.has_value(), "Woke up coroutine without setting response");
return std::move(response).value();
}
web::ng::Response

View File

@@ -21,6 +21,7 @@
#include "data/LedgerCacheInterface.hpp"
#include "rpc/Errors.hpp"
#include "rpc/WorkQueue.hpp"
#include "util/log/Logger.hpp"
#include "web/AdminVerificationStrategy.hpp"
#include "web/SubscriptionContextInterface.hpp"
@@ -119,20 +120,23 @@ public:
*/
class MetricsHandler {
std::shared_ptr<web::AdminVerificationStrategy> adminVerifier_;
std::reference_wrapper<rpc::WorkQueue> workQueue_;
public:
/**
* @brief Construct a new MetricsHandler object
*
* @param adminVerifier The AdminVerificationStrategy to use for verifying the connection for admin access.
* @param workQueue The WorkQueue to use for handling the request.
*/
MetricsHandler(std::shared_ptr<web::AdminVerificationStrategy> adminVerifier);
MetricsHandler(std::shared_ptr<web::AdminVerificationStrategy> adminVerifier, rpc::WorkQueue& workQueue);
/**
* @brief The call of the function object.
*
* @param request The request to handle.
* @param connectionMetadata The connection metadata.
* @param yield The yield context.
* @return The response to the request.
*/
web::ng::Response
@@ -140,7 +144,7 @@ public:
web::ng::Request const& request,
web::ng::ConnectionMetadata& connectionMetadata,
web::SubscriptionContextPtr,
boost::asio::yield_context
boost::asio::yield_context yield
);
};
@@ -248,7 +252,7 @@ public:
} catch (std::exception const&) {
return web::ng::Response{
boost::beast::http::status::internal_server_error,
rpc::makeError(rpc::RippledError::rpcINTERNAL),
rpc::makeError(rpc::RippledError::RpcInternal),
request
};
}

View File

@@ -57,7 +57,7 @@ supportedAmendments()
}
bool
lookupAmendment(auto const& allAmendments, std::vector<ripple::uint256> const& ledgerAmendments, std::string_view name)
lookupAmendment(auto const& allAmendments, std::vector<xrpl::uint256> const& ledgerAmendments, std::string_view name)
{
namespace rg = std::ranges;
if (auto const am = rg::find(allAmendments, name, &data::Amendment::name); am != rg::end(allAmendments))
@@ -91,7 +91,7 @@ operator std::string_view() const
}
AmendmentKey::
operator ripple::uint256() const
operator xrpl::uint256() const
{
return Amendment::getAmendmentId(name);
}
@@ -102,14 +102,14 @@ AmendmentCenter::AmendmentCenter(std::shared_ptr<data::BackendInterface> const&
namespace vs = std::views;
rg::copy(
ripple::allAmendments() | vs::transform([&](auto const& p) {
xrpl::allAmendments() | vs::transform([&](auto const& p) {
auto const& [name, support] = p;
return Amendment{
.name = name,
.feature = Amendment::getAmendmentId(name),
.isSupportedByXRPL = support != ripple::AmendmentSupport::Unsupported,
.isSupportedByXRPL = support != xrpl::AmendmentSupport::Unsupported,
.isSupportedByClio = rg::find(supportedAmendments(), name) != rg::end(supportedAmendments()),
.isRetired = support == ripple::AmendmentSupport::Retired
.isRetired = support == xrpl::AmendmentSupport::Retired
};
}),
std::back_inserter(all_)
@@ -146,9 +146,12 @@ AmendmentCenter::isEnabled(AmendmentKey const& key, uint32_t seq) const
bool
AmendmentCenter::isEnabled(boost::asio::yield_context yield, AmendmentKey const& key, uint32_t seq) const
{
if (auto const listAmendments = fetchAmendmentsList(yield, seq); listAmendments)
return lookupAmendment(all_, *listAmendments, key);
try {
if (auto const listAmendments = fetchAmendmentsList(yield, seq); listAmendments)
return lookupAmendment(all_, *listAmendments, key);
} catch (std::runtime_error const&) {
return false; // Some old ledger does not contain Amendments ledger object so do best we can for now
}
return false;
}
@@ -157,13 +160,19 @@ AmendmentCenter::isEnabled(boost::asio::yield_context yield, std::vector<Amendme
{
namespace rg = std::ranges;
if (auto const listAmendments = fetchAmendmentsList(yield, seq); listAmendments) {
std::vector<bool> out;
rg::transform(keys, std::back_inserter(out), [this, &listAmendments](auto const& key) {
return lookupAmendment(all_, *listAmendments, key);
});
try {
if (auto const listAmendments = fetchAmendmentsList(yield, seq); listAmendments) {
std::vector<bool> out;
rg::transform(keys, std::back_inserter(out), [this, &listAmendments](auto const& key) {
return lookupAmendment(all_, *listAmendments, key);
});
return out;
return out;
}
} catch (std::runtime_error const&) {
return std::vector<bool>(
keys.size(), false
); // Some old ledger does not contain Amendments ledger object so do best we can for now
}
return std::vector<bool>(keys.size(), false);
@@ -182,25 +191,25 @@ AmendmentCenter::operator[](AmendmentKey const& key) const
return getAmendment(key);
}
ripple::uint256
xrpl::uint256
Amendment::getAmendmentId(std::string_view name)
{
return ripple::sha512Half(ripple::Slice(name.data(), name.size()));
return xrpl::sha512Half(xrpl::Slice(name.data(), name.size()));
}
std::optional<std::vector<ripple::uint256>>
std::optional<std::vector<xrpl::uint256>>
AmendmentCenter::fetchAmendmentsList(boost::asio::yield_context yield, uint32_t seq) const
{
// the amendments should always be present on the ledger
auto const amendments = backend_->fetchLedgerObject(ripple::keylet::amendments().key, seq, yield);
auto const amendments = backend_->fetchLedgerObject(xrpl::keylet::amendments().key, seq, yield);
if (not amendments.has_value())
throw std::runtime_error("Amendments ledger object must be present in the database");
ripple::SLE const amendmentsSLE{
ripple::SerialIter{amendments->data(), amendments->size()}, ripple::keylet::amendments().key
xrpl::SLE const amendmentsSLE{
xrpl::SerialIter{amendments->data(), amendments->size()}, xrpl::keylet::amendments().key
};
return amendmentsSLE[~ripple::sfAmendments];
return amendmentsSLE[~xrpl::sfAmendments];
}
} // namespace data

View File

@@ -152,6 +152,12 @@ struct Amendments {
REGISTER(fixDirectoryLimit);
REGISTER(fixIncludeKeyletFields);
REGISTER(fixTokenEscrowV1);
REGISTER(LendingProtocol);
REGISTER(MPTokensV2);
REGISTER(PermissionDelegationV1_1);
REGISTER(fixBatchInnerSigs);
REGISTER(fixCleanup3_1_3);
REGISTER(fixCleanup3_2_0);
// Obsolete but supported by libxrpl
REGISTER(CryptoConditionsSuite);
@@ -275,7 +281,7 @@ public:
operator[](AmendmentKey const& key) const final;
private:
[[nodiscard]] std::optional<std::vector<ripple::uint256>>
[[nodiscard]] std::optional<std::vector<xrpl::uint256>>
fetchAmendmentsList(boost::asio::yield_context yield, uint32_t seq) const;
};

View File

@@ -64,7 +64,7 @@ BackendInterface::finishWrites(std::uint32_t const ledgerSequence)
void
BackendInterface::writeLedgerObject(std::string&& key, std::uint32_t const seq, std::string&& blob)
{
ASSERT(key.size() == sizeof(ripple::uint256), "Key must be 256 bits");
ASSERT(key.size() == sizeof(xrpl::uint256), "Key must be 256 bits");
doWriteLedgerObject(std::move(key), seq, std::move(blob));
}
@@ -77,14 +77,14 @@ BackendInterface::hardFetchLedgerRangeNoThrow() const
// *** state data methods
std::optional<Blob>
BackendInterface::fetchLedgerObject(
ripple::uint256 const& key,
xrpl::uint256 const& key,
std::uint32_t const sequence,
boost::asio::yield_context yield
) const
{
auto obj = cache_.get().get(key, sequence);
if (obj) {
LOG(log_.trace()) << "Cache hit - " << ripple::strHex(key);
LOG(log_.trace()) << "Cache hit - " << xrpl::strHex(key);
return obj;
}
@@ -99,7 +99,7 @@ BackendInterface::fetchLedgerObject(
std::optional<std::uint32_t>
BackendInterface::fetchLedgerObjectSeq(
ripple::uint256 const& key,
xrpl::uint256 const& key,
std::uint32_t const sequence,
boost::asio::yield_context yield
) const
@@ -112,14 +112,14 @@ BackendInterface::fetchLedgerObjectSeq(
std::vector<Blob>
BackendInterface::fetchLedgerObjects(
std::vector<ripple::uint256> const& keys,
std::vector<xrpl::uint256> const& keys,
std::uint32_t const sequence,
boost::asio::yield_context yield
) const
{
std::vector<Blob> results;
results.resize(keys.size());
std::vector<ripple::uint256> misses;
std::vector<xrpl::uint256> misses;
for (size_t i = 0; i < keys.size(); ++i) {
auto obj = cache_.get().get(keys[i], sequence);
if (obj) {
@@ -144,25 +144,25 @@ BackendInterface::fetchLedgerObjects(
}
// Fetches the successor to key/index
std::optional<ripple::uint256>
std::optional<xrpl::uint256>
BackendInterface::fetchSuccessorKey(
ripple::uint256 key,
xrpl::uint256 key,
std::uint32_t const ledgerSequence,
boost::asio::yield_context yield
) const
{
auto succ = cache_.get().getSuccessor(key, ledgerSequence);
if (succ) {
LOG(log_.trace()) << "Cache hit - " << ripple::strHex(key);
LOG(log_.trace()) << "Cache hit - " << xrpl::strHex(key);
} else {
LOG(log_.trace()) << "Cache miss - " << ripple::strHex(key);
LOG(log_.trace()) << "Cache miss - " << xrpl::strHex(key);
}
return succ ? succ->key : doFetchSuccessorKey(key, ledgerSequence, yield);
}
std::optional<LedgerObject>
BackendInterface::fetchSuccessorObject(
ripple::uint256 key,
xrpl::uint256 key,
std::uint32_t const ledgerSequence,
boost::asio::yield_context yield
) const
@@ -180,7 +180,7 @@ BackendInterface::fetchSuccessorObject(
BookOffersPage
BackendInterface::fetchBookOffers(
ripple::uint256 const& book,
xrpl::uint256 const& book,
std::uint32_t const ledgerSequence,
std::uint32_t const limit,
boost::asio::yield_context yield
@@ -189,9 +189,9 @@ BackendInterface::fetchBookOffers(
// TODO try to speed this up. This can take a few seconds. The goal is
// to get it down to a few hundred milliseconds.
BookOffersPage page;
ripple::uint256 const bookEnd = ripple::getQualityNext(book);
ripple::uint256 uTipIndex = book;
std::vector<ripple::uint256> keys;
xrpl::uint256 const bookEnd = xrpl::getQualityNext(book);
xrpl::uint256 uTipIndex = book;
std::vector<xrpl::uint256> keys;
auto getMillis = [](auto diff) { return std::chrono::duration_cast<std::chrono::milliseconds>(diff).count(); };
auto begin = std::chrono::system_clock::now();
std::uint32_t numSucc = 0;
@@ -211,17 +211,17 @@ BackendInterface::fetchBookOffers(
uTipIndex = offerDir->key;
while (keys.size() < limit) {
++numPages;
ripple::STLedgerEntry const sle{
ripple::SerialIter{offerDir->blob.data(), offerDir->blob.size()}, offerDir->key
xrpl::STLedgerEntry const sle{
xrpl::SerialIter{offerDir->blob.data(), offerDir->blob.size()}, offerDir->key
};
auto indexes = sle.getFieldV256(ripple::sfIndexes);
auto indexes = sle.getFieldV256(xrpl::sfIndexes);
keys.insert(keys.end(), indexes.begin(), indexes.end());
auto next = sle.getFieldU64(ripple::sfIndexNext);
auto next = sle.getFieldU64(xrpl::sfIndexNext);
if (next == 0u) {
LOG(log_.trace()) << "Next is empty. breaking";
break;
}
auto nextKey = ripple::keylet::page(uTipIndex, next);
auto nextKey = xrpl::keylet::page(uTipIndex, next);
auto nextDir = fetchLedgerObject(nextKey.key, ledgerSequence, yield);
ASSERT(nextDir.has_value(), "Next dir must exist");
offerDir->blob = *nextDir;
@@ -233,7 +233,7 @@ BackendInterface::fetchBookOffers(
auto mid = std::chrono::system_clock::now();
auto objs = fetchLedgerObjects(keys, ledgerSequence, yield);
for (size_t i = 0; i < keys.size() && i < limit; ++i) {
LOG(log_.trace()) << "Key = " << ripple::strHex(keys[i]) << " blob = " << ripple::strHex(objs[i])
LOG(log_.trace()) << "Key = " << xrpl::strHex(keys[i]) << " blob = " << xrpl::strHex(objs[i])
<< " ledgerSequence = " << ledgerSequence;
ASSERT(!objs[i].empty(), "Ledger object can't be empty");
page.offers.push_back({keys[i], objs[i]});
@@ -247,7 +247,7 @@ BackendInterface::fetchBookOffers(
<< ". num pages = " << std::to_string(numPages) << ". Fetching all objects took "
<< std::to_string(getMillis(end - mid))
<< " milliseconds. total time = " << std::to_string(getMillis(end - begin)) << " milliseconds"
<< " book = " << ripple::strHex(book);
<< " book = " << xrpl::strHex(book);
return page;
}
@@ -305,7 +305,7 @@ BackendInterface::setRange(uint32_t min, uint32_t max, bool force)
LedgerPage
BackendInterface::fetchLedgerPage(
std::optional<ripple::uint256> const& cursor,
std::optional<xrpl::uint256> const& cursor,
std::uint32_t const ledgerSequence,
std::uint32_t const limit,
bool outOfOrder,
@@ -314,11 +314,11 @@ BackendInterface::fetchLedgerPage(
{
LedgerPage page;
std::vector<ripple::uint256> keys;
std::vector<xrpl::uint256> keys;
bool reachedEnd = false;
while (keys.size() < limit && !reachedEnd) {
ripple::uint256 const& curCursor = [&]() {
xrpl::uint256 const& curCursor = [&]() {
if (!keys.empty())
return keys.back();
return (cursor ? *cursor : kFIRST_KEY);
@@ -339,11 +339,11 @@ BackendInterface::fetchLedgerPage(
if (!objects[i].empty()) {
page.objects.push_back({keys[i], std::move(objects[i])});
} else if (!outOfOrder) {
LOG(log_.error()) << "Deleted or non-existent object in successor table. key = " << ripple::strHex(keys[i])
LOG(log_.error()) << "Deleted or non-existent object in successor table. key = " << xrpl::strHex(keys[i])
<< " - seq = " << ledgerSequence;
std::stringstream msg;
for (size_t j = 0; j < objects.size(); ++j) {
msg << " - " << ripple::strHex(keys[j]);
msg << " - " << xrpl::strHex(keys[j]);
}
LOG(log_.error()) << msg.str();
@@ -357,12 +357,12 @@ BackendInterface::fetchLedgerPage(
return page;
}
std::optional<ripple::Fees>
std::optional<xrpl::Fees>
BackendInterface::fetchFees(std::uint32_t const seq, boost::asio::yield_context yield) const
{
ripple::Fees fees;
xrpl::Fees fees;
auto key = ripple::keylet::fees().key;
auto key = xrpl::keylet::fees().key;
auto bytes = fetchLedgerObject(key, seq, yield);
if (!bytes) {
@@ -370,17 +370,17 @@ BackendInterface::fetchFees(std::uint32_t const seq, boost::asio::yield_context
return {};
}
ripple::SerialIter it(bytes->data(), bytes->size());
ripple::SLE const sle{it, key};
xrpl::SerialIter it(bytes->data(), bytes->size());
xrpl::SLE const sle{it, key};
// XRPFees amendment introduced new fields for fees calculations.
// New fields are set and the old fields are removed via `set_fees` tx.
// Fallback to old fields if `set_fees` was not yet used to update the fields on this tx.
auto hasNewFields = false;
{
auto const baseFeeXRP = sle.at(~ripple::sfBaseFeeDrops);
auto const reserveBaseXRP = sle.at(~ripple::sfReserveBaseDrops);
auto const reserveIncrementXRP = sle.at(~ripple::sfReserveIncrementDrops);
auto const baseFeeXRP = sle.at(~xrpl::sfBaseFeeDrops);
auto const reserveBaseXRP = sle.at(~xrpl::sfReserveBaseDrops);
auto const reserveIncrementXRP = sle.at(~xrpl::sfReserveIncrementDrops);
if (baseFeeXRP)
fees.base = baseFeeXRP->xrp();
@@ -396,9 +396,9 @@ BackendInterface::fetchFees(std::uint32_t const seq, boost::asio::yield_context
if (not hasNewFields) {
// Fallback to old fields
auto const baseFee = sle.at(~ripple::sfBaseFee);
auto const reserveBase = sle.at(~ripple::sfReserveBase);
auto const reserveIncrement = sle.at(~ripple::sfReserveIncrement);
auto const baseFee = sle.at(~xrpl::sfBaseFee);
auto const reserveBase = sle.at(~xrpl::sfReserveBase);
auto const reserveIncrement = sle.at(~xrpl::sfReserveIncrement);
if (baseFee)
fees.base = baseFee.value();

View File

@@ -192,9 +192,9 @@ public:
*
* @param sequence The sequence number to fetch for
* @param yield The coroutine context
* @return The ripple::LedgerHeader if found; nullopt otherwise
* @return The xrpl::LedgerHeader if found; nullopt otherwise
*/
virtual std::optional<ripple::LedgerHeader>
virtual std::optional<xrpl::LedgerHeader>
fetchLedgerBySequence(std::uint32_t sequence, boost::asio::yield_context yield) const = 0;
/**
@@ -202,10 +202,10 @@ public:
*
* @param hash The hash to fetch for
* @param yield The coroutine context
* @return The ripple::LedgerHeader if found; nullopt otherwise
* @return The xrpl::LedgerHeader if found; nullopt otherwise
*/
virtual std::optional<ripple::LedgerHeader>
fetchLedgerByHash(ripple::uint256 const& hash, boost::asio::yield_context yield) const = 0;
virtual std::optional<xrpl::LedgerHeader>
fetchLedgerByHash(xrpl::uint256 const& hash, boost::asio::yield_context yield) const = 0;
/**
* @brief Fetches the latest ledger sequence.
@@ -231,9 +231,9 @@ public:
* @param pageSize The maximum number of accounts per page
* @param seq The accounts need to exist for this sequence
* @param yield The coroutine context
* @return A vector of ripple::uint256 representing the account roots
* @return A vector of xrpl::uint256 representing the account roots
*/
virtual std::vector<ripple::uint256>
virtual std::vector<xrpl::uint256>
fetchAccountRoots(
std::uint32_t number,
std::uint32_t pageSize,
@@ -275,7 +275,7 @@ public:
* @param yield The coroutine context
* @return Fees if fees are found; nullopt otherwise
*/
std::optional<ripple::Fees>
std::optional<xrpl::Fees>
fetchFees(std::uint32_t seq, boost::asio::yield_context yield) const;
/**
@@ -286,7 +286,7 @@ public:
* @return TransactionAndMetadata if transaction is found; nullopt otherwise
*/
virtual std::optional<TransactionAndMetadata>
fetchTransaction(ripple::uint256 const& hash, boost::asio::yield_context yield) const = 0;
fetchTransaction(xrpl::uint256 const& hash, boost::asio::yield_context yield) const = 0;
/**
* @brief Fetches multiple transactions.
@@ -296,7 +296,7 @@ public:
* @return A vector of TransactionAndMetadata matching the given hashes
*/
virtual std::vector<TransactionAndMetadata>
fetchTransactions(std::vector<ripple::uint256> const& hashes, boost::asio::yield_context yield) const = 0;
fetchTransactions(std::vector<xrpl::uint256> const& hashes, boost::asio::yield_context yield) const = 0;
/**
* @brief Fetches all transactions for a specific account.
@@ -310,7 +310,7 @@ public:
*/
virtual TransactionsAndCursor
fetchAccountTransactions(
ripple::AccountID const& account,
xrpl::AccountID const& account,
std::uint32_t limit,
bool forward,
std::optional<TransactionsCursor> const& txnCursor,
@@ -332,9 +332,9 @@ public:
*
* @param ledgerSequence The ledger sequence to fetch for
* @param yield The coroutine context
* @return Hashes as ripple::uint256 in a vector
* @return Hashes as xrpl::uint256 in a vector
*/
virtual std::vector<ripple::uint256>
virtual std::vector<xrpl::uint256>
fetchAllTransactionHashesInLedger(std::uint32_t ledgerSequence, boost::asio::yield_context yield) const = 0;
/**
@@ -346,7 +346,7 @@ public:
* @return NFT object on success; nullopt otherwise
*/
virtual std::optional<NFT>
fetchNFT(ripple::uint256 const& tokenID, std::uint32_t ledgerSequence, boost::asio::yield_context yield) const = 0;
fetchNFT(xrpl::uint256 const& tokenID, std::uint32_t ledgerSequence, boost::asio::yield_context yield) const = 0;
/**
* @brief Fetches all transactions for a specific NFT.
@@ -360,7 +360,7 @@ public:
*/
virtual TransactionsAndCursor
fetchNFTTransactions(
ripple::uint256 const& tokenID,
xrpl::uint256 const& tokenID,
std::uint32_t limit,
bool forward,
std::optional<TransactionsCursor> const& cursorIn,
@@ -380,11 +380,11 @@ public:
*/
virtual NFTsAndCursor
fetchNFTsByIssuer(
ripple::AccountID const& issuer,
xrpl::AccountID const& issuer,
std::optional<std::uint32_t> const& taxon,
std::uint32_t ledgerSequence,
std::uint32_t limit,
std::optional<ripple::uint256> const& cursorIn,
std::optional<xrpl::uint256> const& cursorIn,
boost::asio::yield_context yield
) const = 0;
@@ -400,9 +400,9 @@ public:
*/
virtual MPTHoldersAndCursor
fetchMPTHolders(
ripple::uint192 const& mptID,
xrpl::uint192 const& mptID,
std::uint32_t const limit,
std::optional<ripple::AccountID> const& cursorIn,
std::optional<xrpl::AccountID> const& cursorIn,
std::uint32_t const ledgerSequence,
boost::asio::yield_context yield
) const = 0;
@@ -419,7 +419,7 @@ public:
* @return The object as a Blob on success; nullopt otherwise
*/
std::optional<Blob>
fetchLedgerObject(ripple::uint256 const& key, std::uint32_t sequence, boost::asio::yield_context yield) const;
fetchLedgerObject(xrpl::uint256 const& key, std::uint32_t sequence, boost::asio::yield_context yield) const;
/**
* @brief Fetches a specific ledger object sequence.
@@ -432,7 +432,7 @@ public:
* @return The sequence in unit32_t on success; nullopt otherwise
*/
std::optional<std::uint32_t>
fetchLedgerObjectSeq(ripple::uint256 const& key, std::uint32_t sequence, boost::asio::yield_context yield) const;
fetchLedgerObjectSeq(xrpl::uint256 const& key, std::uint32_t sequence, boost::asio::yield_context yield) const;
/**
* @brief Fetches all ledger objects by their keys.
@@ -447,7 +447,7 @@ public:
*/
std::vector<Blob>
fetchLedgerObjects(
std::vector<ripple::uint256> const& keys,
std::vector<xrpl::uint256> const& keys,
std::uint32_t sequence,
boost::asio::yield_context yield
) const;
@@ -461,7 +461,7 @@ public:
* @return The object as a Blob on success; nullopt otherwise
*/
virtual std::optional<Blob>
doFetchLedgerObject(ripple::uint256 const& key, std::uint32_t sequence, boost::asio::yield_context yield) const = 0;
doFetchLedgerObject(xrpl::uint256 const& key, std::uint32_t sequence, boost::asio::yield_context yield) const = 0;
/**
* @brief The database-specific implementation for fetching a ledger object sequence.
@@ -473,7 +473,7 @@ public:
*/
virtual std::optional<std::uint32_t>
doFetchLedgerObjectSeq(
ripple::uint256 const& key,
xrpl::uint256 const& key,
std::uint32_t sequence,
boost::asio::yield_context yield
) const = 0;
@@ -488,7 +488,7 @@ public:
*/
virtual std::vector<Blob>
doFetchLedgerObjects(
std::vector<ripple::uint256> const& keys,
std::vector<xrpl::uint256> const& keys,
std::uint32_t sequence,
boost::asio::yield_context yield
) const = 0;
@@ -515,7 +515,7 @@ public:
*/
LedgerPage
fetchLedgerPage(
std::optional<ripple::uint256> const& cursor,
std::optional<xrpl::uint256> const& cursor,
std::uint32_t ledgerSequence,
std::uint32_t limit,
bool outOfOrder,
@@ -531,7 +531,7 @@ public:
* @return The successor on success; nullopt otherwise
*/
std::optional<LedgerObject>
fetchSuccessorObject(ripple::uint256 key, std::uint32_t ledgerSequence, boost::asio::yield_context yield) const;
fetchSuccessorObject(xrpl::uint256 key, std::uint32_t ledgerSequence, boost::asio::yield_context yield) const;
/**
* @brief Fetches the successor key.
@@ -544,8 +544,8 @@ public:
* @param yield The coroutine context
* @return The successor key on success; nullopt otherwise
*/
std::optional<ripple::uint256>
fetchSuccessorKey(ripple::uint256 key, std::uint32_t ledgerSequence, boost::asio::yield_context yield) const;
std::optional<xrpl::uint256>
fetchSuccessorKey(xrpl::uint256 key, std::uint32_t ledgerSequence, boost::asio::yield_context yield) const;
/**
* @brief Database-specific implementation of fetching the successor key
@@ -555,8 +555,8 @@ public:
* @param yield The coroutine context
* @return The successor on success; nullopt otherwise
*/
virtual std::optional<ripple::uint256>
doFetchSuccessorKey(ripple::uint256 key, std::uint32_t ledgerSequence, boost::asio::yield_context yield) const = 0;
virtual std::optional<xrpl::uint256>
doFetchSuccessorKey(xrpl::uint256 key, std::uint32_t ledgerSequence, boost::asio::yield_context yield) const = 0;
/**
* @brief Fetches book offers.
@@ -569,7 +569,7 @@ public:
*/
BookOffersPage
fetchBookOffers(
ripple::uint256 const& book,
xrpl::uint256 const& book,
std::uint32_t ledgerSequence,
std::uint32_t limit,
boost::asio::yield_context yield
@@ -632,7 +632,7 @@ public:
* @param blob r-value string serialization of ledger header.
*/
virtual void
writeLedger(ripple::LedgerHeader const& ledgerHeader, std::string&& blob) = 0;
writeLedger(xrpl::LedgerHeader const& ledgerHeader, std::string&& blob) = 0;
/**
* @brief Writes a new ledger object.

View File

@@ -116,11 +116,11 @@ public:
NFTsAndCursor
fetchNFTsByIssuer(
ripple::AccountID const& issuer,
xrpl::AccountID const& issuer,
std::optional<std::uint32_t> const& taxon,
std::uint32_t const ledgerSequence,
std::uint32_t const limit,
std::optional<ripple::uint256> const& cursorIn,
std::optional<xrpl::uint256> const& cursorIn,
boost::asio::yield_context yield
) const override
{
@@ -130,7 +130,7 @@ public:
if (taxon.has_value()) {
auto r = schema_->selectNFTIDsByIssuerTaxon.bind(issuer);
r.bindAt(1, *taxon);
r.bindAt(2, cursorIn.value_or(ripple::uint256(0)));
r.bindAt(2, cursorIn.value_or(xrpl::uint256(0)));
r.bindAt(3, Limit{limit});
return r;
}
@@ -139,8 +139,8 @@ public:
r.bindAt(
1,
std::make_tuple(
cursorIn.has_value() ? ripple::nft::toUInt32(ripple::nft::getTaxon(*cursorIn)) : 0,
cursorIn.value_or(ripple::uint256(0))
cursorIn.has_value() ? xrpl::nft::toUInt32(xrpl::nft::getTaxon(*cursorIn)) : 0,
cursorIn.value_or(xrpl::uint256(0))
)
);
r.bindAt(2, Limit{limit});
@@ -156,8 +156,8 @@ public:
return {};
}
std::vector<ripple::uint256> nftIDs;
for (auto const [nftID] : extract<ripple::uint256>(idQueryResults))
std::vector<xrpl::uint256> nftIDs;
for (auto const [nftID] : extract<xrpl::uint256>(idQueryResults))
nftIDs.push_back(nftID);
if (nftIDs.empty())
@@ -189,11 +189,11 @@ public:
auto const nftUris = executor_.readEach(yield, selectNFTURIStatements);
for (auto i = 0u; i < nftIDs.size(); i++) {
if (auto const maybeRow = nftInfos[i].template get<uint32_t, ripple::AccountID, bool>();
if (auto const maybeRow = nftInfos[i].template get<uint32_t, xrpl::AccountID, bool>();
maybeRow.has_value()) {
auto [seq, owner, isBurned] = *maybeRow;
NFT nft(nftIDs[i], seq, owner, isBurned);
if (auto const maybeUri = nftUris[i].template get<ripple::Blob>(); maybeUri.has_value())
if (auto const maybeUri = nftUris[i].template get<xrpl::Blob>(); maybeUri.has_value())
nft.uri = *maybeUri;
ret.nfts.push_back(nft);
}
@@ -201,7 +201,7 @@ public:
return ret;
}
std::vector<ripple::uint256>
std::vector<xrpl::uint256>
fetchAccountRoots(
std::uint32_t number,
std::uint32_t pageSize,
@@ -209,8 +209,8 @@ public:
boost::asio::yield_context yield
) const override
{
std::vector<ripple::uint256> liveAccounts;
std::optional<ripple::AccountID> lastItem;
std::vector<xrpl::uint256> liveAccounts;
std::optional<xrpl::AccountID> lastItem;
while (liveAccounts.size() < number) {
Statement const statement = lastItem ? schema_->selectAccountFromToken.bind(*lastItem, Limit{pageSize})
@@ -224,9 +224,9 @@ public:
break;
}
// The results should not contain duplicates, we just filter out deleted accounts
std::vector<ripple::uint256> fullAccounts;
for (auto [account] : extract<ripple::AccountID>(results)) {
fullAccounts.push_back(ripple::keylet::account(account).key);
std::vector<xrpl::uint256> fullAccounts;
for (auto [account] : extract<xrpl::AccountID>(results)) {
fullAccounts.push_back(xrpl::keylet::account(account).key);
lastItem = account;
}
auto const objs = this->doFetchLedgerObjects(fullAccounts, seq, yield);

View File

@@ -43,10 +43,10 @@
* @brief Struct used to keep track of what to write to account_transactions/account_tx tables.
*/
struct AccountTransactionsData {
boost::container::flat_set<ripple::AccountID> accounts;
boost::container::flat_set<xrpl::AccountID> accounts;
std::uint32_t ledgerSequence{};
std::uint32_t transactionIndex{};
ripple::uint256 txHash;
xrpl::uint256 txHash;
/**
* @brief Construct a new AccountTransactionsData object
@@ -54,7 +54,7 @@ struct AccountTransactionsData {
* @param meta The transaction metadata
* @param txHash The transaction hash
*/
AccountTransactionsData(ripple::TxMeta const& meta, ripple::uint256 const& txHash)
AccountTransactionsData(xrpl::TxMeta const& meta, xrpl::uint256 const& txHash)
: accounts(meta.getAffectedAccounts())
, ledgerSequence(meta.getLgrSeq())
, transactionIndex(meta.getIndex())
@@ -71,10 +71,10 @@ struct AccountTransactionsData {
* Gets written to nf_token_transactions table and the like.
*/
struct NFTTransactionsData {
ripple::uint256 tokenID;
xrpl::uint256 tokenID;
std::uint32_t ledgerSequence;
std::uint32_t transactionIndex;
ripple::uint256 txHash;
xrpl::uint256 txHash;
/**
* @brief Construct a new NFTTransactionsData object
@@ -83,7 +83,7 @@ struct NFTTransactionsData {
* @param meta The transaction metadata
* @param txHash The transaction hash
*/
NFTTransactionsData(ripple::uint256 const& tokenID, ripple::TxMeta const& meta, ripple::uint256 const& txHash)
NFTTransactionsData(xrpl::uint256 const& tokenID, xrpl::TxMeta const& meta, xrpl::uint256 const& txHash)
: tokenID(tokenID), ledgerSequence(meta.getLgrSeq()), transactionIndex(meta.getIndex()), txHash(txHash)
{
}
@@ -101,11 +101,11 @@ struct NFTTransactionsData {
* We only set the uri if this is a mint tx, or if we are loading initial state from NFTokenPage objects.
*/
struct NFTsData {
ripple::uint256 tokenID;
xrpl::uint256 tokenID;
std::uint32_t ledgerSequence;
std::optional<std::uint32_t> transactionIndex;
ripple::AccountID owner;
std::optional<ripple::Blob> uri;
xrpl::AccountID owner;
std::optional<xrpl::Blob> uri;
bool isBurned = false;
bool onlyUriChanged = false; // Whether only the URI was changed
@@ -122,10 +122,10 @@ struct NFTsData {
* @param meta The transaction metadata
*/
NFTsData(
ripple::uint256 const& tokenID,
ripple::AccountID const& owner,
ripple::Blob const& uri,
ripple::TxMeta const& meta
xrpl::uint256 const& tokenID,
xrpl::AccountID const& owner,
xrpl::Blob const& uri,
xrpl::TxMeta const& meta
)
: tokenID(tokenID), ledgerSequence(meta.getLgrSeq()), transactionIndex(meta.getIndex()), owner(owner), uri(uri)
{
@@ -141,7 +141,7 @@ struct NFTsData {
* @param meta The transaction metadata
* @param isBurned Whether the NFT is burned
*/
NFTsData(ripple::uint256 const& tokenID, ripple::AccountID const& owner, ripple::TxMeta const& meta, bool isBurned)
NFTsData(xrpl::uint256 const& tokenID, xrpl::AccountID const& owner, xrpl::TxMeta const& meta, bool isBurned)
: tokenID(tokenID)
, ledgerSequence(meta.getLgrSeq())
, transactionIndex(meta.getIndex())
@@ -163,10 +163,10 @@ struct NFTsData {
* @param uri The URI
*/
NFTsData(
ripple::uint256 const& tokenID,
xrpl::uint256 const& tokenID,
std::uint32_t const ledgerSequence,
ripple::AccountID const& owner,
ripple::Blob const& uri
xrpl::AccountID const& owner,
xrpl::Blob const& uri
)
: tokenID(tokenID), ledgerSequence(ledgerSequence), owner(owner), uri(uri)
{
@@ -180,7 +180,7 @@ struct NFTsData {
* @param uri The new URI
*
*/
NFTsData(ripple::uint256 const& tokenID, ripple::TxMeta const& meta, ripple::Blob const& uri)
NFTsData(xrpl::uint256 const& tokenID, xrpl::TxMeta const& meta, xrpl::Blob const& uri)
: tokenID(tokenID)
, ledgerSequence(meta.getLgrSeq())
, transactionIndex(meta.getIndex())
@@ -194,8 +194,8 @@ struct NFTsData {
* @brief Represents an MPT and holder pair
*/
struct MPTHolderData {
ripple::uint192 mptID;
ripple::AccountID holder;
xrpl::uint192 mptID;
xrpl::AccountID holder;
};
/**
@@ -231,25 +231,25 @@ isBookDir(T const& key, R const& object)
if (!isDirNode(object))
return false;
ripple::STLedgerEntry const sle{ripple::SerialIter{object.data(), object.size()}, key};
return !sle[~ripple::sfOwner].has_value();
xrpl::STLedgerEntry const sle{xrpl::SerialIter{object.data(), object.size()}, key};
return !sle[~xrpl::sfOwner].has_value();
}
/**
* @brief Get the book base.
*
* @param key The key to get the book base out of
* @return Book base as ripple::uint256
* @return Book base as xrpl::uint256
*/
template <typename T>
inline ripple::uint256
inline xrpl::uint256
getBookBase(T const& key)
{
static constexpr size_t kEY_SIZE = 24;
ASSERT(key.size() == ripple::uint256::size(), "Invalid key size {}", key.size());
ASSERT(key.size() == xrpl::uint256::size(), "Invalid key size {}", key.size());
ripple::uint256 ret;
xrpl::uint256 ret;
for (size_t i = 0; i < kEY_SIZE; ++i)
ret.data()[i] = key.data()[i];
@@ -257,15 +257,15 @@ getBookBase(T const& key)
}
/**
* @brief Stringify a ripple::uint256.
* @brief Stringify a xrpl::uint256.
*
* @param input The input value
* @return The input value as a string
*/
inline std::string
uint256ToString(ripple::uint256 const& input)
uint256ToString(xrpl::uint256 const& input)
{
return {reinterpret_cast<char const*>(input.data()), ripple::uint256::size()};
return {reinterpret_cast<char const*>(input.data()), xrpl::uint256::size()};
}
/** @brief The ripple epoch start timestamp. Midnight on 1st January 2000. */

View File

@@ -117,22 +117,22 @@ public:
NFTsAndCursor
fetchNFTsByIssuer(
ripple::AccountID const& issuer,
xrpl::AccountID const& issuer,
std::optional<std::uint32_t> const& taxon,
std::uint32_t const ledgerSequence,
std::uint32_t const limit,
std::optional<ripple::uint256> const& cursorIn,
std::optional<xrpl::uint256> const& cursorIn,
boost::asio::yield_context yield
) const override
{
std::vector<ripple::uint256> nftIDs;
std::vector<xrpl::uint256> nftIDs;
if (taxon.has_value()) {
// Keyspace and ScyllaDB uses the same logic for taxon-filtered queries
nftIDs = fetchNFTIDsByTaxon(issuer, *taxon, limit, cursorIn, yield);
} else {
// Amazon Keyspaces Workflow for non-taxon queries
auto const startTaxon = cursorIn.has_value() ? ripple::nft::toUInt32(ripple::nft::getTaxon(*cursorIn)) : 0;
auto const startTokenID = cursorIn.value_or(ripple::uint256(0));
auto const startTaxon = cursorIn.has_value() ? xrpl::nft::toUInt32(xrpl::nft::getTaxon(*cursorIn)) : 0;
auto const startTokenID = cursorIn.value_or(xrpl::uint256(0));
Statement const firstQuery = schema_->selectNFTIDsByIssuerTaxon.bind(issuer);
firstQuery.bindAt(1, startTaxon);
@@ -141,7 +141,7 @@ public:
auto const firstRes = executor_.read(yield, firstQuery);
if (firstRes.has_value()) {
for (auto const [nftID] : extract<ripple::uint256>(*firstRes))
for (auto const [nftID] : extract<xrpl::uint256>(*firstRes))
nftIDs.push_back(nftID);
}
@@ -153,7 +153,7 @@ public:
auto const secondRes = executor_.read(yield, secondQuery);
if (secondRes.has_value()) {
for (auto const [nftID] : extract<ripple::uint256>(*secondRes))
for (auto const [nftID] : extract<xrpl::uint256>(*secondRes))
nftIDs.push_back(nftID);
}
}
@@ -172,9 +172,9 @@ public:
* @param pageSize The maximum number of accounts per page.
* @param seq The accounts need to exist at this ledger sequence.
* @param yield The coroutine context.
* @return A vector of ripple::uint256 representing the account root hashes.
* @return A vector of xrpl::uint256 representing the account root hashes.
*/
std::vector<ripple::uint256>
std::vector<xrpl::uint256>
fetchAccountRoots(
[[maybe_unused]] std::uint32_t number,
[[maybe_unused]] std::uint32_t pageSize,
@@ -187,41 +187,41 @@ public:
}
private:
std::vector<ripple::uint256>
std::vector<xrpl::uint256>
fetchNFTIDsByTaxon(
ripple::AccountID const& issuer,
xrpl::AccountID const& issuer,
std::uint32_t const taxon,
std::uint32_t const limit,
std::optional<ripple::uint256> const& cursorIn,
std::optional<xrpl::uint256> const& cursorIn,
boost::asio::yield_context yield
) const
{
std::vector<ripple::uint256> nftIDs;
std::vector<xrpl::uint256> nftIDs;
Statement const statement = schema_->selectNFTIDsByIssuerTaxon.bind(issuer);
statement.bindAt(1, taxon);
statement.bindAt(2, cursorIn.value_or(ripple::uint256(0)));
statement.bindAt(2, cursorIn.value_or(xrpl::uint256(0)));
statement.bindAt(3, Limit{limit});
auto const res = executor_.read(yield, statement);
if (res.has_value() && res->hasRows()) {
for (auto const [nftID] : extract<ripple::uint256>(*res))
for (auto const [nftID] : extract<xrpl::uint256>(*res))
nftIDs.push_back(nftID);
}
return nftIDs;
}
std::vector<ripple::uint256>
std::vector<xrpl::uint256>
fetchNFTIDsWithoutTaxon(
ripple::AccountID const& issuer,
xrpl::AccountID const& issuer,
std::uint32_t const limit,
std::optional<ripple::uint256> const& cursorIn,
std::optional<xrpl::uint256> const& cursorIn,
boost::asio::yield_context yield
) const
{
std::vector<ripple::uint256> nftIDs;
std::vector<xrpl::uint256> nftIDs;
auto const startTaxon = cursorIn.has_value() ? ripple::nft::toUInt32(ripple::nft::getTaxon(*cursorIn)) : 0;
auto const startTokenID = cursorIn.value_or(ripple::uint256(0));
auto const startTaxon = cursorIn.has_value() ? xrpl::nft::toUInt32(xrpl::nft::getTaxon(*cursorIn)) : 0;
auto const startTokenID = cursorIn.value_or(xrpl::uint256(0));
Statement firstQuery = schema_->selectNFTIDsByIssuerTaxon.bind(issuer);
firstQuery.bindAt(1, startTaxon);
@@ -230,7 +230,7 @@ private:
auto const firstRes = executor_.read(yield, firstQuery);
if (firstRes.has_value()) {
for (auto const [nftID] : extract<ripple::uint256>(*firstRes))
for (auto const [nftID] : extract<xrpl::uint256>(*firstRes))
nftIDs.push_back(nftID);
}
@@ -242,7 +242,7 @@ private:
auto const secondRes = executor_.read(yield, secondQuery);
if (secondRes.has_value()) {
for (auto const [nftID] : extract<ripple::uint256>(*secondRes))
for (auto const [nftID] : extract<xrpl::uint256>(*secondRes))
nftIDs.push_back(nftID);
}
}
@@ -254,7 +254,7 @@ private:
*/
NFTsAndCursor
populateNFTsAndCreateCursor(
std::vector<ripple::uint256> const& nftIDs,
std::vector<xrpl::uint256> const& nftIDs,
std::uint32_t const ledgerSequence,
std::uint32_t const limit,
boost::asio::yield_context yield
@@ -291,11 +291,11 @@ private:
// Combine the results into final NFT objects.
for (auto i = 0u; i < nftIDs.size(); ++i) {
if (auto const maybeRow = nftInfos[i].template get<uint32_t, ripple::AccountID, bool>();
if (auto const maybeRow = nftInfos[i].template get<uint32_t, xrpl::AccountID, bool>();
maybeRow.has_value()) {
auto [seq, owner, isBurned] = *maybeRow;
NFT nft(nftIDs[i], seq, owner, isBurned);
if (auto const maybeUri = nftUris[i].template get<ripple::Blob>(); maybeUri.has_value())
if (auto const maybeUri = nftUris[i].template get<xrpl::Blob>(); maybeUri.has_value())
nft.uri = *maybeUri;
ret.nfts.push_back(nft);
}

View File

@@ -131,7 +131,7 @@ LedgerCache::update(std::vector<etl::model::Object> const& objs, uint32_t seq)
}
std::optional<LedgerObject>
LedgerCache::getSuccessor(ripple::uint256 const& key, uint32_t seq) const
LedgerCache::getSuccessor(xrpl::uint256 const& key, uint32_t seq) const
{
if (disabled_ or not full_)
return {};
@@ -148,7 +148,7 @@ LedgerCache::getSuccessor(ripple::uint256 const& key, uint32_t seq) const
}
std::optional<LedgerObject>
LedgerCache::getPredecessor(ripple::uint256 const& key, uint32_t seq) const
LedgerCache::getPredecessor(xrpl::uint256 const& key, uint32_t seq) const
{
if (disabled_ or not full_)
return {};
@@ -164,7 +164,7 @@ LedgerCache::getPredecessor(ripple::uint256 const& key, uint32_t seq) const
}
std::optional<Blob>
LedgerCache::get(ripple::uint256 const& key, uint32_t seq) const
LedgerCache::get(xrpl::uint256 const& key, uint32_t seq) const
{
if (disabled_)
return {};
@@ -183,7 +183,7 @@ LedgerCache::get(ripple::uint256 const& key, uint32_t seq) const
}
std::optional<Blob>
LedgerCache::getDeleted(ripple::uint256 const& key, uint32_t seq) const
LedgerCache::getDeleted(xrpl::uint256 const& key, uint32_t seq) const
{
if (disabled_)
return std::nullopt;

View File

@@ -54,7 +54,7 @@ public:
Blob blob;
};
using CacheMap = std::map<ripple::uint256, CacheEntry>;
using CacheMap = std::map<xrpl::uint256, CacheEntry>;
private:
// counters for fetchLedgerObject(s) hit rate
@@ -97,7 +97,7 @@ private:
)};
// temporary set to prevent background thread from writing already deleted data. not used when cache is full
std::unordered_set<ripple::uint256, ripple::hardened_hash<>> deletes_;
std::unordered_set<xrpl::uint256, xrpl::HardenedHash<>> deletes_;
public:
void
@@ -107,16 +107,16 @@ public:
update(std::vector<etl::model::Object> const& objs, uint32_t seq) override;
std::optional<Blob>
get(ripple::uint256 const& key, uint32_t seq) const override;
get(xrpl::uint256 const& key, uint32_t seq) const override;
std::optional<Blob>
getDeleted(ripple::uint256 const& key, uint32_t seq) const override;
getDeleted(xrpl::uint256 const& key, uint32_t seq) const override;
std::optional<LedgerObject>
getSuccessor(ripple::uint256 const& key, uint32_t seq) const override;
getSuccessor(xrpl::uint256 const& key, uint32_t seq) const override;
std::optional<LedgerObject>
getPredecessor(ripple::uint256 const& key, uint32_t seq) const override;
getPredecessor(xrpl::uint256 const& key, uint32_t seq) const override;
void
setDisabled() override;

View File

@@ -75,7 +75,7 @@ public:
* @return If found in cache, will return the cached Blob; otherwise nullopt is returned
*/
virtual std::optional<Blob>
get(ripple::uint256 const& key, uint32_t seq) const = 0;
get(xrpl::uint256 const& key, uint32_t seq) const = 0;
/**
* @brief Fetch a recently deleted object by its key and sequence number.
@@ -85,7 +85,7 @@ public:
* @return If found in deleted cache, will return the cached Blob; otherwise nullopt is returned
*/
virtual std::optional<Blob>
getDeleted(ripple::uint256 const& key, uint32_t seq) const = 0;
getDeleted(xrpl::uint256 const& key, uint32_t seq) const = 0;
/**
* @brief Gets a cached successor.
@@ -97,7 +97,7 @@ public:
* @return If found in cache, will return the cached successor; otherwise nullopt is returned
*/
virtual std::optional<LedgerObject>
getSuccessor(ripple::uint256 const& key, uint32_t seq) const = 0;
getSuccessor(xrpl::uint256 const& key, uint32_t seq) const = 0;
/**
* @brief Gets a cached predcessor.
@@ -109,7 +109,7 @@ public:
* @return If found in cache, will return the cached predcessor; otherwise nullopt is returned
*/
virtual std::optional<LedgerObject>
getPredecessor(ripple::uint256 const& key, uint32_t seq) const = 0;
getPredecessor(xrpl::uint256 const& key, uint32_t seq) const = 0;
/**
* @brief Disables the cache.

View File

@@ -30,7 +30,9 @@
namespace data {
LedgerCacheSaver::LedgerCacheSaver(util::config::ClioConfigDefinition const& config, LedgerCacheInterface const& cache)
: cacheFilePath_(config.maybeValue<std::string>("cache.file.path")), cache_(cache)
: cacheFilePath_(config.maybeValue<std::string>("cache.file.path"))
, cache_(cache)
, isAsync_(config.get<bool>("cache.file.async_save"))
{
}
@@ -53,9 +55,12 @@ LedgerCacheSaver::save()
success.has_value()) {
LOG(util::LogService::info()) << "Successfully saved ledger cache in " << durationMs << " ms";
} else {
LOG(util::LogService::error()) << "Error saving LedgerCache to file";
LOG(util::LogService::error()) << "Error saving LedgerCache to file: " << success.error();
}
});
if (not isAsync_) {
waitToFinish();
}
}
void

View File

@@ -53,6 +53,7 @@ class LedgerCacheSaver {
std::optional<std::string> cacheFilePath_;
std::reference_wrapper<LedgerCacheInterface const> cache_;
std::optional<std::thread> savingThread_;
bool isAsync_;
public:
/**

View File

@@ -30,7 +30,7 @@
namespace data {
/**
* @brief A simple cache holding one `ripple::LedgerHeader` to reduce DB lookups.
* @brief A simple cache holding one `xrpl::LedgerHeader` to reduce DB lookups.
*
* Used internally by backend implementations. When a ledger header is
* fetched via `FetchLedgerBySeq` (often triggered by RPC commands),
@@ -46,7 +46,7 @@ public:
* @brief Struct to store ledger header cache entry and the sequence it belongs to
*/
struct CacheEntry {
ripple::LedgerHeader ledger;
xrpl::LedgerHeader ledger;
uint32_t seq{};
/**

View File

@@ -39,7 +39,7 @@ using Blob = std::vector<unsigned char>;
* @brief Represents an object in the ledger.
*/
struct LedgerObject {
ripple::uint256 key;
xrpl::uint256 key;
Blob blob;
bool
@@ -51,7 +51,7 @@ struct LedgerObject {
*/
struct LedgerPage {
std::vector<LedgerObject> objects;
std::optional<ripple::uint256> cursor;
std::optional<xrpl::uint256> cursor;
};
/**
@@ -59,7 +59,7 @@ struct LedgerPage {
*/
struct BookOffersPage {
std::vector<LedgerObject> offers;
std::optional<ripple::uint256> cursor;
std::optional<xrpl::uint256> cursor;
};
/**
@@ -170,9 +170,9 @@ struct TransactionsAndCursor {
* @brief Represents a NFToken.
*/
struct NFT {
ripple::uint256 tokenID;
xrpl::uint256 tokenID;
std::uint32_t ledgerSequence{};
ripple::AccountID owner;
xrpl::AccountID owner;
Blob uri;
bool isBurned{};
@@ -187,9 +187,9 @@ struct NFT {
* @param uri The URI
* @param isBurned Whether the token is burned
*/
NFT(ripple::uint256 const& tokenID,
NFT(xrpl::uint256 const& tokenID,
std::uint32_t ledgerSequence,
ripple::AccountID const& owner,
xrpl::AccountID const& owner,
Blob uri,
bool isBurned)
: tokenID{tokenID}, ledgerSequence{ledgerSequence}, owner{owner}, uri{std::move(uri)}, isBurned{isBurned}
@@ -204,7 +204,7 @@ struct NFT {
* @param owner The owner
* @param isBurned Whether the token is burned
*/
NFT(ripple::uint256 const& tokenID, std::uint32_t ledgerSequence, ripple::AccountID const& owner, bool isBurned)
NFT(xrpl::uint256 const& tokenID, std::uint32_t ledgerSequence, xrpl::AccountID const& owner, bool isBurned)
: NFT(tokenID, ledgerSequence, owner, {}, isBurned)
{
}
@@ -230,7 +230,7 @@ struct NFT {
*/
struct NFTsAndCursor {
std::vector<NFT> nfts;
std::optional<ripple::uint256> cursor;
std::optional<xrpl::uint256> cursor;
};
/**
@@ -238,7 +238,7 @@ struct NFTsAndCursor {
*/
struct MPTHoldersAndCursor {
std::vector<Blob> mptokens;
std::optional<ripple::AccountID> cursor;
std::optional<xrpl::AccountID> cursor;
};
/**
@@ -257,7 +257,7 @@ struct LedgerRange {
*/
struct Amendment {
std::string name;
ripple::uint256 feature;
xrpl::uint256 feature;
bool isSupportedByXRPL = false;
bool isSupportedByClio = false;
bool isRetired = false;
@@ -268,7 +268,7 @@ struct Amendment {
* @param name The name of the amendment
* @return The amendment Id as uint256
*/
static ripple::uint256
static xrpl::uint256
getAmendmentId(std::string_view const name);
/**
@@ -304,7 +304,7 @@ struct AmendmentKey {
operator std::string_view() const;
/** @brief Conversion to uint256 */
operator ripple::uint256() const;
operator xrpl::uint256() const;
/**
* @brief Comparison operators
@@ -315,8 +315,8 @@ struct AmendmentKey {
operator<=>(AmendmentKey const& other) const = default;
};
constexpr ripple::uint256 kFIRST_KEY{"0000000000000000000000000000000000000000000000000000000000000000"};
constexpr ripple::uint256 kLAST_KEY{"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"};
constexpr ripple::uint256 kHI192{"0000000000000000000000000000000000000000000000001111111111111111"};
constexpr xrpl::uint256 kFIRST_KEY{"0000000000000000000000000000000000000000000000000000000000000000"};
constexpr xrpl::uint256 kLAST_KEY{"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"};
constexpr xrpl::uint256 kHI192{"0000000000000000000000000000000000000000000000001111111111111111"};
} // namespace data

View File

@@ -148,7 +148,7 @@ public:
TransactionsAndCursor
fetchAccountTransactions(
ripple::AccountID const& account,
xrpl::AccountID const& account,
std::uint32_t const limit,
bool forward,
std::optional<TransactionsCursor> const& txnCursor,
@@ -169,14 +169,14 @@ public:
auto cursor = txnCursor;
if (cursor) {
statement.bindAt(1, cursor->asTuple());
LOG(log_.debug()) << "account = " << ripple::strHex(account) << " tuple = " << cursor->ledgerSequence
LOG(log_.debug()) << "account = " << xrpl::strHex(account) << " tuple = " << cursor->ledgerSequence
<< cursor->transactionIndex;
} else {
auto const seq = forward ? rng->minSequence : rng->maxSequence;
auto const placeHolder = forward ? 0u : std::numeric_limits<std::uint32_t>::max();
statement.bindAt(1, std::make_tuple(placeHolder, placeHolder));
LOG(log_.debug()) << "account = " << ripple::strHex(account) << " idx = " << seq
LOG(log_.debug()) << "account = " << xrpl::strHex(account) << " idx = " << seq
<< " tuple = " << placeHolder;
}
@@ -191,11 +191,11 @@ public:
return {};
}
std::vector<ripple::uint256> hashes = {};
std::vector<xrpl::uint256> hashes = {};
auto numRows = results.numRows();
LOG(log_.info()) << "num_rows = " << numRows;
for (auto [hash, data] : extract<ripple::uint256, std::tuple<uint32_t, uint32_t>>(results)) {
for (auto [hash, data] : extract<xrpl::uint256, std::tuple<uint32_t, uint32_t>>(results)) {
hashes.push_back(hash);
if (--numRows == 0) {
LOG(log_.debug()) << "Setting cursor";
@@ -221,7 +221,7 @@ public:
}
void
writeLedger(ripple::LedgerHeader const& ledgerHeader, std::string&& blob) override
writeLedger(xrpl::LedgerHeader const& ledgerHeader, std::string&& blob) override
{
executor_.write(schema_->insertLedgerHeader, ledgerHeader.seq, std::move(blob));
@@ -250,7 +250,7 @@ public:
return std::nullopt;
}
std::optional<ripple::LedgerHeader>
std::optional<xrpl::LedgerHeader>
fetchLedgerBySequence(std::uint32_t const sequence, boost::asio::yield_context yield) const override
{
if (auto const lock = ledgerCache_.get(); lock.has_value() && lock->seq == sequence)
@@ -260,7 +260,7 @@ public:
if (res) {
if (auto const& result = res.value(); result) {
if (auto const maybeValue = result.template get<std::vector<unsigned char>>(); maybeValue) {
auto const header = util::deserializeHeader(ripple::makeSlice(*maybeValue));
auto const header = util::deserializeHeader(xrpl::makeSlice(*maybeValue));
ledgerCache_.put(FetchLedgerCache::CacheEntry{header, sequence});
return header;
}
@@ -277,8 +277,8 @@ public:
return std::nullopt;
}
std::optional<ripple::LedgerHeader>
fetchLedgerByHash(ripple::uint256 const& hash, boost::asio::yield_context yield) const override
std::optional<xrpl::LedgerHeader>
fetchLedgerByHash(xrpl::uint256 const& hash, boost::asio::yield_context yield) const override
{
if (auto const res = executor_.read(yield, schema_->selectLedgerByHash, hash); res) {
if (auto const& result = res.value(); result) {
@@ -342,7 +342,7 @@ public:
return fetchTransactions(hashes, yield);
}
std::vector<ripple::uint256>
std::vector<xrpl::uint256>
fetchAllTransactionHashesInLedger(
std::uint32_t const ledgerSequence,
boost::asio::yield_context yield
@@ -363,8 +363,8 @@ public:
return {};
}
std::vector<ripple::uint256> hashes;
for (auto [hash] : extract<ripple::uint256>(result))
std::vector<xrpl::uint256> hashes;
for (auto [hash] : extract<xrpl::uint256>(result))
hashes.push_back(std::move(hash));
auto end = std::chrono::system_clock::now();
@@ -377,7 +377,7 @@ public:
std::optional<NFT>
fetchNFT(
ripple::uint256 const& tokenID,
xrpl::uint256 const& tokenID,
std::uint32_t const ledgerSequence,
boost::asio::yield_context yield
) const override
@@ -386,7 +386,7 @@ public:
if (not res)
return std::nullopt;
if (auto const maybeRow = res->template get<uint32_t, ripple::AccountID, bool>(); maybeRow) {
if (auto const maybeRow = res->template get<uint32_t, xrpl::AccountID, bool>(); maybeRow) {
auto [seq, owner, isBurned] = *maybeRow;
auto result = std::make_optional<NFT>(tokenID, seq, owner, isBurned);
@@ -403,7 +403,7 @@ public:
// one.
auto uriRes = executor_.read(yield, schema_->selectNFTURI, tokenID, ledgerSequence);
if (uriRes) {
if (auto const maybeUri = uriRes->template get<ripple::Blob>(); maybeUri)
if (auto const maybeUri = uriRes->template get<xrpl::Blob>(); maybeUri)
result->uri = *maybeUri;
}
@@ -416,7 +416,7 @@ public:
TransactionsAndCursor
fetchNFTTransactions(
ripple::uint256 const& tokenID,
xrpl::uint256 const& tokenID,
std::uint32_t const limit,
bool const forward,
std::optional<TransactionsCursor> const& cursorIn,
@@ -437,14 +437,14 @@ public:
auto cursor = cursorIn;
if (cursor) {
statement.bindAt(1, cursor->asTuple());
LOG(log_.debug()) << "token_id = " << ripple::strHex(tokenID) << " tuple = " << cursor->ledgerSequence
LOG(log_.debug()) << "token_id = " << xrpl::strHex(tokenID) << " tuple = " << cursor->ledgerSequence
<< cursor->transactionIndex;
} else {
auto const seq = forward ? rng->minSequence : rng->maxSequence;
auto const placeHolder = forward ? 0 : std::numeric_limits<std::uint32_t>::max();
statement.bindAt(1, std::make_tuple(placeHolder, placeHolder));
LOG(log_.debug()) << "token_id = " << ripple::strHex(tokenID) << " idx = " << seq
LOG(log_.debug()) << "token_id = " << xrpl::strHex(tokenID) << " idx = " << seq
<< " tuple = " << placeHolder;
}
@@ -457,11 +457,11 @@ public:
return {};
}
std::vector<ripple::uint256> hashes = {};
std::vector<xrpl::uint256> hashes = {};
auto numRows = results.numRows();
LOG(log_.info()) << "num_rows = " << numRows;
for (auto [hash, data] : extract<ripple::uint256, std::tuple<uint32_t, uint32_t>>(results)) {
for (auto [hash, data] : extract<xrpl::uint256, std::tuple<uint32_t, uint32_t>>(results)) {
hashes.push_back(hash);
if (--numRows == 0) {
LOG(log_.debug()) << "Setting cursor";
@@ -487,15 +487,15 @@ public:
MPTHoldersAndCursor
fetchMPTHolders(
ripple::uint192 const& mptID,
xrpl::uint192 const& mptID,
std::uint32_t const limit,
std::optional<ripple::AccountID> const& cursorIn,
std::optional<xrpl::AccountID> const& cursorIn,
std::uint32_t const ledgerSequence,
boost::asio::yield_context yield
) const override
{
auto const holderEntries = executor_.read(
yield, schema_->selectMPTHolders, mptID, cursorIn.value_or(ripple::AccountID(0)), Limit{limit}
yield, schema_->selectMPTHolders, mptID, cursorIn.value_or(xrpl::AccountID(0)), Limit{limit}
);
auto const& holderResults = holderEntries.value();
@@ -504,10 +504,10 @@ public:
return {};
}
std::vector<ripple::uint256> mptKeys;
std::optional<ripple::AccountID> cursor;
for (auto const [holder] : extract<ripple::AccountID>(holderResults)) {
mptKeys.push_back(ripple::keylet::mptoken(mptID, holder).key);
std::vector<xrpl::uint256> mptKeys;
std::optional<xrpl::AccountID> cursor;
for (auto const [holder] : extract<xrpl::AccountID>(holderResults)) {
mptKeys.push_back(xrpl::keylet::mptoken(mptID, holder).key);
cursor = holder;
}
@@ -526,12 +526,12 @@ public:
std::optional<Blob>
doFetchLedgerObject(
ripple::uint256 const& key,
xrpl::uint256 const& key,
std::uint32_t const sequence,
boost::asio::yield_context yield
) const override
{
LOG(log_.debug()) << "Fetching ledger object for seq " << sequence << ", key = " << ripple::to_string(key);
LOG(log_.debug()) << "Fetching ledger object for seq " << sequence << ", key = " << xrpl::to_string(key);
if (auto const res = executor_.read(yield, schema_->selectObject, key, sequence); res) {
if (auto const result = res->template get<Blob>(); result) {
if (result->size())
@@ -548,12 +548,12 @@ public:
std::optional<std::uint32_t>
doFetchLedgerObjectSeq(
ripple::uint256 const& key,
xrpl::uint256 const& key,
std::uint32_t const sequence,
boost::asio::yield_context yield
) const override
{
LOG(log_.debug()) << "Fetching ledger object for seq " << sequence << ", key = " << ripple::to_string(key);
LOG(log_.debug()) << "Fetching ledger object for seq " << sequence << ", key = " << xrpl::to_string(key);
if (auto const res = executor_.read(yield, schema_->selectObject, key, sequence); res) {
if (auto const result = res->template get<Blob, std::uint32_t>(); result) {
auto [_, seq] = result.value();
@@ -568,7 +568,7 @@ public:
}
std::optional<TransactionAndMetadata>
fetchTransaction(ripple::uint256 const& hash, boost::asio::yield_context yield) const override
fetchTransaction(xrpl::uint256 const& hash, boost::asio::yield_context yield) const override
{
if (auto const res = executor_.read(yield, schema_->selectTransaction, hash); res) {
if (auto const maybeValue = res->template get<Blob, Blob, uint32_t, uint32_t>(); maybeValue) {
@@ -584,15 +584,15 @@ public:
return std::nullopt;
}
std::optional<ripple::uint256>
std::optional<xrpl::uint256>
doFetchSuccessorKey(
ripple::uint256 key,
xrpl::uint256 key,
std::uint32_t const ledgerSequence,
boost::asio::yield_context yield
) const override
{
if (auto const res = executor_.read(yield, schema_->selectSuccessor, key, ledgerSequence); res) {
if (auto const result = res->template get<ripple::uint256>(); result) {
if (auto const result = res->template get<xrpl::uint256>(); result) {
if (*result == kLAST_KEY)
return std::nullopt;
return result;
@@ -607,7 +607,7 @@ public:
}
std::vector<TransactionAndMetadata>
fetchTransactions(std::vector<ripple::uint256> const& hashes, boost::asio::yield_context yield) const override
fetchTransactions(std::vector<xrpl::uint256> const& hashes, boost::asio::yield_context yield) const override
{
if (hashes.empty())
return {};
@@ -649,7 +649,7 @@ public:
std::vector<Blob>
doFetchLedgerObjects(
std::vector<ripple::uint256> const& keys,
std::vector<xrpl::uint256> const& keys,
std::uint32_t const sequence,
boost::asio::yield_context yield
) const override
@@ -690,7 +690,7 @@ public:
std::vector<LedgerObject>
fetchLedgerDiff(std::uint32_t const ledgerSequence, boost::asio::yield_context yield) const override
{
auto const [keys, timeDiff] = util::timed([this, &ledgerSequence, yield]() -> std::vector<ripple::uint256> {
auto const [keys, timeDiff] = util::timed([this, &ledgerSequence, yield]() -> std::vector<xrpl::uint256> {
auto const res = executor_.read(yield, schema_->selectDiff, ledgerSequence);
if (not res) {
LOG(log_.error()) << "Could not fetch ledger diff: " << res.error() << "; ledger = " << ledgerSequence;
@@ -703,8 +703,8 @@ public:
return {};
}
std::vector<ripple::uint256> resultKeys;
for (auto [key] : extract<ripple::uint256>(results))
std::vector<xrpl::uint256> resultKeys;
for (auto [key] : extract<xrpl::uint256>(results))
resultKeys.push_back(key);
return resultKeys;
@@ -877,8 +877,8 @@ public:
// to record the URI and link to the issuer_nf_tokens table.
if (record.uri) {
statements.push_back(schema_->insertIssuerNFT.bind(
ripple::nft::getIssuer(record.tokenID),
static_cast<uint32_t>(ripple::nft::getTaxon(record.tokenID)),
xrpl::nft::getIssuer(record.tokenID),
static_cast<uint32_t>(xrpl::nft::getTaxon(record.tokenID)),
record.tokenID
));
statements.push_back(

View File

@@ -77,14 +77,14 @@ public:
}
void
append(ripple::uint256 const& value) const
append(xrpl::uint256 const& value) const
{
auto const rc = cass_collection_append_bytes(
*this,
static_cast<cass_byte_t const*>(static_cast<unsigned char const*>(value.data())),
ripple::uint256::size()
xrpl::uint256::size()
);
throwErrorIfNeeded(rc, "Bind ripple::uint256");
throwErrorIfNeeded(rc, "Bind xrpl::uint256");
}
};
} // namespace data::cassandra::impl

View File

@@ -62,18 +62,18 @@ extractColumn(CassRow const* row, std::size_t idx)
using UintTupleType = std::tuple<uint32_t, uint32_t>;
using UCharVectorType = std::vector<unsigned char>;
if constexpr (std::is_same_v<DecayedType, ripple::uint256>) {
if constexpr (std::is_same_v<DecayedType, xrpl::uint256>) {
cass_byte_t const* buf = nullptr;
std::size_t bufSize = 0;
auto const rc = cass_value_get_bytes(cass_row_get_column(row, idx), &buf, &bufSize);
throwErrorIfNeeded(rc, "Extract ripple::uint256");
output = ripple::uint256::fromVoid(buf);
} else if constexpr (std::is_same_v<DecayedType, ripple::AccountID>) {
throwErrorIfNeeded(rc, "Extract xrpl::uint256");
output = xrpl::uint256::fromVoid(buf);
} else if constexpr (std::is_same_v<DecayedType, xrpl::AccountID>) {
cass_byte_t const* buf = nullptr;
std::size_t bufSize = 0;
auto const rc = cass_value_get_bytes(cass_row_get_column(row, idx), &buf, &bufSize);
throwErrorIfNeeded(rc, "Extract ripple::AccountID");
output = ripple::AccountID::fromVoid(buf);
throwErrorIfNeeded(rc, "Extract xrpl::AccountID");
output = xrpl::AccountID::fromVoid(buf);
} else if constexpr (std::is_same_v<DecayedType, UCharVectorType>) {
cass_byte_t const* buf = nullptr;
std::size_t bufSize = 0;

View File

@@ -107,15 +107,15 @@ public:
using DecayedType = std::decay_t<Type>;
using UCharVectorType = std::vector<unsigned char>;
using UintTupleType = std::tuple<uint32_t, uint32_t>;
using UintByteTupleType = std::tuple<uint32_t, ripple::uint256>;
using ByteVectorType = std::vector<ripple::uint256>;
using UintByteTupleType = std::tuple<uint32_t, xrpl::uint256>;
using ByteVectorType = std::vector<xrpl::uint256>;
if constexpr (std::is_same_v<DecayedType, ripple::uint256> || std::is_same_v<DecayedType, ripple::uint192>) {
if constexpr (std::is_same_v<DecayedType, xrpl::uint256> || std::is_same_v<DecayedType, xrpl::uint192>) {
auto const rc = bindBytes(value.data(), value.size());
throwErrorIfNeeded(rc, "Bind ripple::base_uint");
} else if constexpr (std::is_same_v<DecayedType, ripple::AccountID>) {
throwErrorIfNeeded(rc, "Bind xrpl::BaseUInt");
} else if constexpr (std::is_same_v<DecayedType, xrpl::AccountID>) {
auto const rc = bindBytes(value.data(), value.size());
throwErrorIfNeeded(rc, "Bind ripple::AccountID");
throwErrorIfNeeded(rc, "Bind xrpl::AccountID");
} else if constexpr (std::is_same_v<DecayedType, UCharVectorType>) {
auto const rc = bindBytes(value.data(), value.size());
throwErrorIfNeeded(rc, "Bind vector<unsigned char>");
@@ -129,7 +129,7 @@ public:
} else if constexpr (std::is_same_v<DecayedType, UintTupleType> ||
std::is_same_v<DecayedType, UintByteTupleType>) {
auto const rc = cass_statement_bind_tuple(*this, idx, Tuple{std::forward<Type>(value)});
throwErrorIfNeeded(rc, "Bind tuple<uint32, uint32> or <uint32_t, ripple::uint256>");
throwErrorIfNeeded(rc, "Bind tuple<uint32, uint32> or <uint32_t, xrpl::uint256>");
} else if constexpr (std::is_same_v<DecayedType, ByteVectorType>) {
auto const rc = cass_statement_bind_collection(*this, idx, Collection{std::forward<Type>(value)});
throwErrorIfNeeded(rc, "Bind collection");

View File

@@ -79,14 +79,14 @@ public:
else if constexpr (std::is_convertible_v<DecayedType, int64_t>) {
auto const rc = cass_tuple_set_int64(*this, idx, std::forward<Type>(value));
throwErrorIfNeeded(rc, "Bind int64");
} else if constexpr (std::is_same_v<DecayedType, ripple::uint256>) {
} else if constexpr (std::is_same_v<DecayedType, xrpl::uint256>) {
auto const rc = cass_tuple_set_bytes(
*this,
idx,
static_cast<cass_byte_t const*>(static_cast<unsigned char const*>(value.data())),
value.size()
);
throwErrorIfNeeded(rc, "Bind ripple::uint256");
throwErrorIfNeeded(rc, "Bind xrpl::uint256");
} else {
// type not supported for binding
static_assert(util::Unsupported<DecayedType>);

View File

@@ -48,7 +48,7 @@ InputFile::readRaw(char* data, size_t size)
return not file_.fail();
}
ripple::uint256
xrpl::uint256
InputFile::hash() const
{
auto sum = shasum_;

View File

@@ -51,7 +51,7 @@ public:
bool
readRaw(char* data, size_t size);
ripple::uint256
xrpl::uint256
hash() const;
};
} // namespace data::impl

View File

@@ -36,17 +36,17 @@
namespace data::impl {
using Hash = ripple::uint256;
using Hash = xrpl::uint256;
using Separator = std::array<char, 16>;
static constexpr Separator kSEPARATOR = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
namespace {
std::expected<std::pair<ripple::uint256, LedgerCache::CacheEntry>, std::string>
std::expected<std::pair<xrpl::uint256, LedgerCache::CacheEntry>, std::string>
readCacheEntry(InputFile& file, size_t i)
{
ripple::uint256 key;
if (not file.readRaw(reinterpret_cast<char*>(key.data()), ripple::base_uint<256>::bytes)) {
xrpl::uint256 key;
if (not file.readRaw(reinterpret_cast<char*>(key.data()), xrpl::BaseUInt<256>::kBytes)) {
return std::unexpected(fmt::format("Failed to read key at index {}", i));
}
@@ -98,7 +98,7 @@ LedgerCacheFile::write(DataView dataView)
file.write(kSEPARATOR);
for (auto const& [k, v] : dataView.map) {
file.write(k.data(), decltype(k)::bytes);
file.write(k.data(), decltype(k)::kBytes);
file.write(v.seq);
file.write(v.blob.size());
file.writeRaw(reinterpret_cast<char const*>(v.blob.data()), v.blob.size());
@@ -106,14 +106,14 @@ LedgerCacheFile::write(DataView dataView)
file.write(kSEPARATOR);
for (auto const& [k, v] : dataView.deleted) {
file.write(k.data(), decltype(k)::bytes);
file.write(k.data(), decltype(k)::kBytes);
file.write(v.seq);
file.write(v.blob.size());
file.writeRaw(reinterpret_cast<char const*>(v.blob.data()), v.blob.size());
}
file.write(kSEPARATOR);
auto const hash = file.hash();
file.write(hash.data(), decltype(hash)::bytes);
file.write(hash.data(), decltype(hash)::kBytes);
try {
std::filesystem::rename(newFilePath, path_);
@@ -190,8 +190,8 @@ LedgerCacheFile::read(uint32_t minLatestSequence)
}
auto const dataHash = file.hash();
ripple::uint256 hashFromFile{};
if (not file.readRaw(reinterpret_cast<char*>(hashFromFile.data()), decltype(hashFromFile)::bytes)) {
xrpl::uint256 hashFromFile{};
if (not file.readRaw(reinterpret_cast<char*>(hashFromFile.data()), decltype(hashFromFile)::kBytes)) {
return std::unexpected{"Error reading hash"};
}

View File

@@ -52,7 +52,7 @@ OutputFile::writeToFile(char const* data, size_t size)
shasum_.update(data, size);
}
ripple::uint256
xrpl::uint256
OutputFile::hash() const
{
auto sum = shasum_;

View File

@@ -57,7 +57,7 @@ public:
void
writeRaw(char const* data, size_t size);
ripple::uint256
xrpl::uint256
hash() const;
private:

View File

@@ -27,16 +27,16 @@
#include <vector>
namespace etl {
std::vector<ripple::uint256>
std::vector<xrpl::uint256>
getMarkers(size_t numMarkers)
{
ASSERT(numMarkers <= 256, "Number of markers must be <= 256. Got: {}", numMarkers);
unsigned char const incr = 256 / numMarkers;
std::vector<ripple::uint256> markers;
std::vector<xrpl::uint256> markers;
markers.reserve(numMarkers);
ripple::uint256 base{0};
xrpl::uint256 base{0};
for (size_t i = 0; i < numMarkers; ++i) {
markers.push_back(base);
base.data()[0] += incr;

View File

@@ -148,7 +148,7 @@ public:
* @param numMarkers Total markers to partition for
* @return The markers
*/
std::vector<ripple::uint256>
std::vector<xrpl::uint256>
getMarkers(size_t numMarkers);
} // namespace etl

View File

@@ -303,7 +303,7 @@ ETLService::loadInitialLedgerIfNeeded()
auto [ledger, timeDiff] = ::util::timed<std::chrono::duration<double>>([this, seq]() {
return extractor_->extractLedgerOnly(seq).and_then(
[this, seq](auto&& data) -> std::optional<ripple::LedgerHeader> {
[this, seq](auto&& data) -> std::optional<xrpl::LedgerHeader> {
// TODO: loadInitialLedger in balancer should be called fetchEdgeKeys or similar
auto res = balancer_->loadInitialLedger(seq, *initialLoadObserver_);
if (not res.has_value() and res.error() == InitialLedgerLoadError::Cancelled) {

View File

@@ -55,7 +55,7 @@ struct LoaderInterface {
* @param data The data to load
* @return Optional ledger header
*/
[[nodiscard]] virtual std::optional<ripple::LedgerHeader>
[[nodiscard]] virtual std::optional<xrpl::LedgerHeader>
loadInitialLedger(model::LedgerData const& data) = 0;
};

View File

@@ -20,17 +20,17 @@
#include "data/DBHelpers.hpp"
#include "util/Assert.hpp"
#include <ripple/protocol/STBase.h>
#include <ripple/protocol/STTx.h>
#include <ripple/protocol/TxMeta.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STBase.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/STObject.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/Serializer.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxFormats.h>
#include <xrpl/protocol/TxMeta.h>
#include <optional>
#include <string>
@@ -44,16 +44,16 @@ namespace etl {
* @return MPT and holder account pair
*/
std::optional<MPTHolderData>
getMPTokenAuthorize(ripple::TxMeta const& txMeta)
getMPTokenAuthorize(xrpl::TxMeta const& txMeta)
{
for (ripple::STObject const& node : txMeta.getNodes()) {
if (node.getFieldU16(ripple::sfLedgerEntryType) != ripple::ltMPTOKEN)
for (xrpl::STObject const& node : txMeta.getNodes()) {
if (node.getFieldU16(xrpl::sfLedgerEntryType) != xrpl::ltMPTOKEN)
continue;
if (node.getFName() == ripple::sfCreatedNode) {
auto const& newMPT = node.peekAtField(ripple::sfNewFields).downcast<ripple::STObject>();
if (node.getFName() == xrpl::sfCreatedNode) {
auto const& newMPT = node.peekAtField(xrpl::sfNewFields).downcast<xrpl::STObject>();
return MPTHolderData{
.mptID = newMPT[ripple::sfMPTokenIssuanceID], .holder = newMPT.getAccountID(ripple::sfAccount)
.mptID = newMPT[xrpl::sfMPTokenIssuanceID], .holder = newMPT.getAccountID(xrpl::sfAccount)
};
}
}
@@ -61,9 +61,9 @@ getMPTokenAuthorize(ripple::TxMeta const& txMeta)
}
std::optional<MPTHolderData>
getMPTHolderFromTx(ripple::TxMeta const& txMeta, ripple::STTx const& sttx)
getMPTHolderFromTx(xrpl::TxMeta const& txMeta, xrpl::STTx const& sttx)
{
if (txMeta.getResultTER() != ripple::tesSUCCESS || sttx.getTxnType() != ripple::TxType::ttMPTOKEN_AUTHORIZE)
if (txMeta.getResultTER() != xrpl::tesSUCCESS || sttx.getTxnType() != xrpl::TxType::ttMPTOKEN_AUTHORIZE)
return {};
return getMPTokenAuthorize(txMeta);
@@ -73,16 +73,16 @@ std::optional<MPTHolderData>
getMPTHolderFromObj(std::string const& key, std::string const& blob)
{
// https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0033-multi-purpose-tokens#2121-mptoken-ledger-identifier
ASSERT(key.size() == ripple::uint256::size(), "The size of the key is expected to fit uint256 exactly");
ASSERT(key.size() == xrpl::uint256::size(), "The size of the key is expected to fit uint256 exactly");
ripple::STLedgerEntry const sle =
ripple::STLedgerEntry(ripple::SerialIter{blob.data(), blob.size()}, ripple::uint256::fromVoid(key.data()));
xrpl::STLedgerEntry const sle =
xrpl::STLedgerEntry(xrpl::SerialIter{blob.data(), blob.size()}, xrpl::uint256::fromVoid(key.data()));
if (sle.getFieldU16(ripple::sfLedgerEntryType) != ripple::ltMPTOKEN)
if (sle.getFieldU16(xrpl::sfLedgerEntryType) != xrpl::ltMPTOKEN)
return {};
auto const mptIssuanceID = sle[ripple::sfMPTokenIssuanceID];
auto const holder = sle.getAccountID(ripple::sfAccount);
auto const mptIssuanceID = sle[xrpl::sfMPTokenIssuanceID];
auto const holder = sle.getAccountID(xrpl::sfAccount);
return MPTHolderData{.mptID = mptIssuanceID, .holder = holder};
}

View File

@@ -22,8 +22,8 @@
#include "data/DBHelpers.hpp"
#include <ripple/protocol/STTx.h>
#include <ripple/protocol/TxMeta.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TxMeta.h>
namespace etl {
@@ -35,7 +35,7 @@ namespace etl {
* @return The MPTIssuanceID and holder pair as a optional
*/
std::optional<MPTHolderData>
getMPTHolderFromTx(ripple::TxMeta const& txMeta, ripple::STTx const& sttx);
getMPTHolderFromTx(xrpl::TxMeta const& txMeta, xrpl::STTx const& sttx);
/**
* @brief Pull MPT data from ledger object via loadInitialLedger.

View File

@@ -47,7 +47,7 @@ namespace etl::model {
* the Registry for its `onTransaction` and `onInitialTransaction` hooks.
* It's a compilation error to list the same transaction type more than once.
*/
template <ripple::TxType... Types>
template <xrpl::TxType... Types>
requires(util::hasNoDuplicates(Types...))
struct Spec {
static constexpr bool kSPEC_TAG = true;
@@ -59,7 +59,7 @@ struct Spec {
* @return true if the transaction was requested; false otherwise
*/
[[nodiscard]] static constexpr bool
wants(ripple::TxType type) noexcept
wants(xrpl::TxType type) noexcept
{
return ((Types == type) || ...);
}
@@ -73,13 +73,13 @@ struct Transaction {
std::string metaRaw;
// unpacked blob and meta
ripple::STTx sttx;
ripple::TxMeta meta;
xrpl::STTx sttx;
xrpl::TxMeta meta;
// commonly used stuff
ripple::uint256 id;
xrpl::uint256 id;
std::string key; // key is the above id as a string of 32 characters
ripple::TxType type;
xrpl::TxType type;
/**
* @brief Compares Transaction objects to each other without considering sttx and meta fields
@@ -113,9 +113,9 @@ struct Object {
Deleted = 3,
};
ripple::uint256 key;
xrpl::uint256 key;
std::string keyRaw;
ripple::Blob data;
xrpl::Blob data;
std::string dataRaw;
std::string successor;
std::string predecessor;
@@ -146,7 +146,7 @@ struct LedgerData {
std::optional<std::vector<BookSuccessor>> successors;
std::optional<std::vector<std::string>> edgeKeys;
ripple::LedgerHeader header;
xrpl::LedgerHeader header;
std::string rawHeader;
uint32_t seq;
@@ -159,8 +159,8 @@ struct LedgerData {
operator==(LedgerData const& other) const
{
auto const serialized = [](auto const& hdr) {
ripple::Serializer ser;
ripple::addRaw(hdr, ser);
xrpl::Serializer ser;
xrpl::addRaw(hdr, ser);
return ser.getString();
};

View File

@@ -49,47 +49,47 @@
namespace etl {
std::pair<std::vector<NFTTransactionsData>, std::optional<NFTsData>>
getNftokenModifyData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx)
getNftokenModifyData(xrpl::TxMeta const& txMeta, xrpl::STTx const& sttx)
{
auto const tokenID = sttx.getFieldH256(ripple::sfNFTokenID);
auto const tokenID = sttx.getFieldH256(xrpl::sfNFTokenID);
// note: sfURI is optional, if it is absent, we will update the uri as empty string
return {
{NFTTransactionsData(sttx.getFieldH256(ripple::sfNFTokenID), txMeta, sttx.getTransactionID())},
NFTsData(tokenID, txMeta, sttx.getFieldVL(ripple::sfURI))
{NFTTransactionsData(sttx.getFieldH256(xrpl::sfNFTokenID), txMeta, sttx.getTransactionID())},
NFTsData(tokenID, txMeta, sttx.getFieldVL(xrpl::sfURI))
};
}
std::pair<std::vector<NFTTransactionsData>, std::optional<NFTsData>>
getNFTokenMintData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx)
getNFTokenMintData(xrpl::TxMeta const& txMeta, xrpl::STTx const& sttx)
{
// To find the minted token ID, we put all tokenIDs referenced in the
// metadata from prior to the tx application into one vector, then all
// tokenIDs referenced in the metadata from after the tx application into
// another, then find the one tokenID that was added by this tx
// application.
std::vector<ripple::uint256> prevIDs;
std::vector<ripple::uint256> finalIDs;
std::vector<xrpl::uint256> prevIDs;
std::vector<xrpl::uint256> finalIDs;
// The owner is not necessarily the issuer, if using authorized minter
// flow. Determine owner from the ledger object ID of the NFTokenPages
// that were changed.
std::optional<ripple::AccountID> owner;
std::optional<xrpl::AccountID> owner;
for (ripple::STObject const& node : txMeta.getNodes()) {
if (node.getFieldU16(ripple::sfLedgerEntryType) != ripple::ltNFTOKEN_PAGE)
for (xrpl::STObject const& node : txMeta.getNodes()) {
if (node.getFieldU16(xrpl::sfLedgerEntryType) != xrpl::ltNFTOKEN_PAGE)
continue;
if (!owner)
owner = ripple::AccountID::fromVoid(node.getFieldH256(ripple::sfLedgerIndex).data());
owner = xrpl::AccountID::fromVoid(node.getFieldH256(xrpl::sfLedgerIndex).data());
if (node.getFName() == ripple::sfCreatedNode) {
ripple::STArray const& toAddNFTs =
node.peekAtField(ripple::sfNewFields).downcast<ripple::STObject>().getFieldArray(ripple::sfNFTokens);
if (node.getFName() == xrpl::sfCreatedNode) {
xrpl::STArray const& toAddNFTs =
node.peekAtField(xrpl::sfNewFields).downcast<xrpl::STObject>().getFieldArray(xrpl::sfNFTokens);
std::ranges::transform(
toAddNFTs,
std::back_inserter(finalIDs),
[](ripple::STObject const& nft) { return nft.getFieldH256(ripple::sfNFTokenID); }
[](xrpl::STObject const& nft) { return nft.getFieldH256(xrpl::sfNFTokenID); }
);
}
// Else it's modified, as there should never be a deleted NFToken page
@@ -104,26 +104,25 @@ getNFTokenMintData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx)
// However, there will always be NFTs listed in the final fields,
// as rippled outputs all fields in final fields even if they were
// not changed.
ripple::STObject const& previousFields =
node.peekAtField(ripple::sfPreviousFields).downcast<ripple::STObject>();
if (!previousFields.isFieldPresent(ripple::sfNFTokens))
xrpl::STObject const& previousFields = node.peekAtField(xrpl::sfPreviousFields).downcast<xrpl::STObject>();
if (!previousFields.isFieldPresent(xrpl::sfNFTokens))
continue;
ripple::STArray const& toAddNFTs = previousFields.getFieldArray(ripple::sfNFTokens);
xrpl::STArray const& toAddNFTs = previousFields.getFieldArray(xrpl::sfNFTokens);
std::ranges::transform(
toAddNFTs,
std::back_inserter(prevIDs),
[](ripple::STObject const& nft) { return nft.getFieldH256(ripple::sfNFTokenID); }
[](xrpl::STObject const& nft) { return nft.getFieldH256(xrpl::sfNFTokenID); }
);
ripple::STArray const& toAddFinalNFTs =
node.peekAtField(ripple::sfFinalFields).downcast<ripple::STObject>().getFieldArray(ripple::sfNFTokens);
xrpl::STArray const& toAddFinalNFTs =
node.peekAtField(xrpl::sfFinalFields).downcast<xrpl::STObject>().getFieldArray(xrpl::sfNFTokens);
std::ranges::transform(
toAddFinalNFTs,
std::back_inserter(finalIDs),
[](ripple::STObject const& nft) { return nft.getFieldH256(ripple::sfNFTokenID); }
[](xrpl::STObject const& nft) { return nft.getFieldH256(xrpl::sfNFTokenID); }
);
}
}
@@ -146,22 +145,21 @@ getNFTokenMintData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx)
return {
{NFTTransactionsData(*diff.first, txMeta, sttx.getTransactionID())},
NFTsData(*diff.first, *owner, sttx.getFieldVL(ripple::sfURI), txMeta)
NFTsData(*diff.first, *owner, sttx.getFieldVL(xrpl::sfURI), txMeta)
};
}
std::pair<std::vector<NFTTransactionsData>, std::optional<NFTsData>>
getNFTokenBurnData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx)
getNFTokenBurnData(xrpl::TxMeta const& txMeta, xrpl::STTx const& sttx)
{
ripple::uint256 const tokenID = sttx.getFieldH256(ripple::sfNFTokenID);
xrpl::uint256 const tokenID = sttx.getFieldH256(xrpl::sfNFTokenID);
std::vector<NFTTransactionsData> const txs = {NFTTransactionsData(tokenID, txMeta, sttx.getTransactionID())};
// Determine who owned the token when it was burned by finding an
// NFTokenPage that was deleted or modified that contains this
// tokenID.
for (ripple::STObject const& node : txMeta.getNodes()) {
if (node.getFieldU16(ripple::sfLedgerEntryType) != ripple::ltNFTOKEN_PAGE ||
node.getFName() == ripple::sfCreatedNode)
for (xrpl::STObject const& node : txMeta.getNodes()) {
if (node.getFieldU16(xrpl::sfLedgerEntryType) != xrpl::ltNFTOKEN_PAGE || node.getFName() == xrpl::sfCreatedNode)
continue;
// NFT burn can result in an NFTokenPage being modified to no longer
@@ -172,30 +170,27 @@ getNFTokenBurnData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx)
// deleted. In this case, we need to look in the PreviousFields.
// Otherwise, the page was not modified prior to deleting and we
// need to look in the FinalFields.
std::optional<ripple::STArray> prevNFTs;
std::optional<xrpl::STArray> prevNFTs;
if (node.isFieldPresent(ripple::sfPreviousFields)) {
ripple::STObject const& previousFields =
node.peekAtField(ripple::sfPreviousFields).downcast<ripple::STObject>();
if (previousFields.isFieldPresent(ripple::sfNFTokens))
prevNFTs = previousFields.getFieldArray(ripple::sfNFTokens);
} else if (node.getFName() == ripple::sfDeletedNode) {
prevNFTs =
node.peekAtField(ripple::sfFinalFields).downcast<ripple::STObject>().getFieldArray(ripple::sfNFTokens);
if (node.isFieldPresent(xrpl::sfPreviousFields)) {
xrpl::STObject const& previousFields = node.peekAtField(xrpl::sfPreviousFields).downcast<xrpl::STObject>();
if (previousFields.isFieldPresent(xrpl::sfNFTokens))
prevNFTs = previousFields.getFieldArray(xrpl::sfNFTokens);
} else if (node.getFName() == xrpl::sfDeletedNode) {
prevNFTs = node.peekAtField(xrpl::sfFinalFields).downcast<xrpl::STObject>().getFieldArray(xrpl::sfNFTokens);
}
if (!prevNFTs)
continue;
auto const nft =
std::find_if(prevNFTs->begin(), prevNFTs->end(), [&tokenID](ripple::STObject const& candidate) {
return candidate.getFieldH256(ripple::sfNFTokenID) == tokenID;
});
auto const nft = std::find_if(prevNFTs->begin(), prevNFTs->end(), [&tokenID](xrpl::STObject const& candidate) {
return candidate.getFieldH256(xrpl::sfNFTokenID) == tokenID;
});
if (nft != prevNFTs->end()) {
return std::make_pair(
txs,
NFTsData(
tokenID, ripple::AccountID::fromVoid(node.getFieldH256(ripple::sfLedgerIndex).data()), txMeta, true
tokenID, xrpl::AccountID::fromVoid(node.getFieldH256(xrpl::sfLedgerIndex).data()), txMeta, true
)
);
}
@@ -207,15 +202,15 @@ getNFTokenBurnData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx)
}
std::pair<std::vector<NFTTransactionsData>, std::optional<NFTsData>>
getNFTokenAcceptOfferData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx)
getNFTokenAcceptOfferData(xrpl::TxMeta const& txMeta, xrpl::STTx const& sttx)
{
// If we have the buy offer from this tx, we can determine the owner
// more easily by just looking at the owner of the accepted NFTokenOffer
// object.
if (sttx.isFieldPresent(ripple::sfNFTokenBuyOffer)) {
if (sttx.isFieldPresent(xrpl::sfNFTokenBuyOffer)) {
auto const affectedBuyOffer =
std::find_if(txMeta.getNodes().begin(), txMeta.getNodes().end(), [&sttx](ripple::STObject const& node) {
return node.getFieldH256(ripple::sfLedgerIndex) == sttx.getFieldH256(ripple::sfNFTokenBuyOffer);
std::find_if(txMeta.getNodes().begin(), txMeta.getNodes().end(), [&sttx](xrpl::STObject const& node) {
return node.getFieldH256(xrpl::sfLedgerIndex) == sttx.getFieldH256(xrpl::sfNFTokenBuyOffer);
});
if (affectedBuyOffer == txMeta.getNodes().end()) {
std::stringstream msg;
@@ -223,13 +218,12 @@ getNFTokenAcceptOfferData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx
throw std::runtime_error(msg.str());
}
ripple::uint256 const tokenID = affectedBuyOffer->peekAtField(ripple::sfFinalFields)
.downcast<ripple::STObject>()
.getFieldH256(ripple::sfNFTokenID);
xrpl::uint256 const tokenID = affectedBuyOffer->peekAtField(xrpl::sfFinalFields)
.downcast<xrpl::STObject>()
.getFieldH256(xrpl::sfNFTokenID);
ripple::AccountID const owner = affectedBuyOffer->peekAtField(ripple::sfFinalFields)
.downcast<ripple::STObject>()
.getAccountID(ripple::sfOwner);
xrpl::AccountID const owner =
affectedBuyOffer->peekAtField(xrpl::sfFinalFields).downcast<xrpl::STObject>().getAccountID(xrpl::sfOwner);
return {
{NFTTransactionsData(tokenID, txMeta, sttx.getTransactionID())}, NFTsData(tokenID, owner, txMeta, false)
};
@@ -237,8 +231,8 @@ getNFTokenAcceptOfferData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx
// Otherwise we have to infer the new owner from the affected nodes.
auto const affectedSellOffer =
std::find_if(txMeta.getNodes().begin(), txMeta.getNodes().end(), [&sttx](ripple::STObject const& node) {
return node.getFieldH256(ripple::sfLedgerIndex) == sttx.getFieldH256(ripple::sfNFTokenSellOffer);
std::find_if(txMeta.getNodes().begin(), txMeta.getNodes().end(), [&sttx](xrpl::STObject const& node) {
return node.getFieldH256(xrpl::sfLedgerIndex) == sttx.getFieldH256(xrpl::sfNFTokenSellOffer);
});
if (affectedSellOffer == txMeta.getNodes().end()) {
std::stringstream msg;
@@ -246,37 +240,29 @@ getNFTokenAcceptOfferData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx
throw std::runtime_error(msg.str());
}
ripple::uint256 const tokenID = affectedSellOffer->peekAtField(ripple::sfFinalFields)
.downcast<ripple::STObject>()
.getFieldH256(ripple::sfNFTokenID);
xrpl::uint256 const tokenID =
affectedSellOffer->peekAtField(xrpl::sfFinalFields).downcast<xrpl::STObject>().getFieldH256(xrpl::sfNFTokenID);
ripple::AccountID const seller = affectedSellOffer->peekAtField(ripple::sfFinalFields)
.downcast<ripple::STObject>()
.getAccountID(ripple::sfOwner);
xrpl::AccountID const seller =
affectedSellOffer->peekAtField(xrpl::sfFinalFields).downcast<xrpl::STObject>().getAccountID(xrpl::sfOwner);
for (ripple::STObject const& node : txMeta.getNodes()) {
if (node.getFieldU16(ripple::sfLedgerEntryType) != ripple::ltNFTOKEN_PAGE ||
node.getFName() == ripple::sfDeletedNode)
for (xrpl::STObject const& node : txMeta.getNodes()) {
if (node.getFieldU16(xrpl::sfLedgerEntryType) != xrpl::ltNFTOKEN_PAGE || node.getFName() == xrpl::sfDeletedNode)
continue;
ripple::AccountID const nodeOwner =
ripple::AccountID::fromVoid(node.getFieldH256(ripple::sfLedgerIndex).data());
xrpl::AccountID const nodeOwner = xrpl::AccountID::fromVoid(node.getFieldH256(xrpl::sfLedgerIndex).data());
if (nodeOwner == seller)
continue;
ripple::STArray const& nfts = [&node] {
if (node.getFName() == ripple::sfCreatedNode) {
return node.peekAtField(ripple::sfNewFields)
.downcast<ripple::STObject>()
.getFieldArray(ripple::sfNFTokens);
xrpl::STArray const& nfts = [&node] {
if (node.getFName() == xrpl::sfCreatedNode) {
return node.peekAtField(xrpl::sfNewFields).downcast<xrpl::STObject>().getFieldArray(xrpl::sfNFTokens);
}
return node.peekAtField(ripple::sfFinalFields)
.downcast<ripple::STObject>()
.getFieldArray(ripple::sfNFTokens);
return node.peekAtField(xrpl::sfFinalFields).downcast<xrpl::STObject>().getFieldArray(xrpl::sfNFTokens);
}();
auto const nft = std::ranges::find_if(nfts, [&tokenID](ripple::STObject const& candidate) {
return candidate.getFieldH256(ripple::sfNFTokenID) == tokenID;
auto const nft = std::ranges::find_if(nfts, [&tokenID](xrpl::STObject const& candidate) {
return candidate.getFieldH256(xrpl::sfNFTokenID) == tokenID;
});
if (nft != nfts.end()) {
return {
@@ -296,15 +282,15 @@ getNFTokenAcceptOfferData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx
// transaction using this feature. This transaction also never returns an
// NFTsData because it does not change the state of an NFT itself.
std::pair<std::vector<NFTTransactionsData>, std::optional<NFTsData>>
getNFTokenCancelOfferData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx)
getNFTokenCancelOfferData(xrpl::TxMeta const& txMeta, xrpl::STTx const& sttx)
{
std::vector<NFTTransactionsData> txs;
for (ripple::STObject const& node : txMeta.getNodes()) {
if (node.getFieldU16(ripple::sfLedgerEntryType) != ripple::ltNFTOKEN_OFFER)
for (xrpl::STObject const& node : txMeta.getNodes()) {
if (node.getFieldU16(xrpl::sfLedgerEntryType) != xrpl::ltNFTOKEN_OFFER)
continue;
ripple::uint256 const tokenID =
node.peekAtField(ripple::sfFinalFields).downcast<ripple::STObject>().getFieldH256(ripple::sfNFTokenID);
xrpl::uint256 const tokenID =
node.peekAtField(xrpl::sfFinalFields).downcast<xrpl::STObject>().getFieldH256(xrpl::sfNFTokenID);
txs.emplace_back(tokenID, txMeta, sttx.getTransactionID());
}
@@ -322,34 +308,34 @@ getNFTokenCancelOfferData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx
// This transaction never returns an NFTokensData because it does not
// change the state of an NFT itself.
std::pair<std::vector<NFTTransactionsData>, std::optional<NFTsData>>
getNFTokenCreateOfferData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx)
getNFTokenCreateOfferData(xrpl::TxMeta const& txMeta, xrpl::STTx const& sttx)
{
return {{NFTTransactionsData(sttx.getFieldH256(ripple::sfNFTokenID), txMeta, sttx.getTransactionID())}, {}};
return {{NFTTransactionsData(sttx.getFieldH256(xrpl::sfNFTokenID), txMeta, sttx.getTransactionID())}, {}};
}
std::pair<std::vector<NFTTransactionsData>, std::optional<NFTsData>>
getNFTDataFromTx(ripple::TxMeta const& txMeta, ripple::STTx const& sttx)
getNFTDataFromTx(xrpl::TxMeta const& txMeta, xrpl::STTx const& sttx)
{
if (txMeta.getResultTER() != ripple::tesSUCCESS)
if (txMeta.getResultTER() != xrpl::tesSUCCESS)
return {{}, {}};
switch (sttx.getTxnType()) {
case ripple::TxType::ttNFTOKEN_MINT:
case xrpl::TxType::ttNFTOKEN_MINT:
return getNFTokenMintData(txMeta, sttx);
case ripple::TxType::ttNFTOKEN_BURN:
case xrpl::TxType::ttNFTOKEN_BURN:
return getNFTokenBurnData(txMeta, sttx);
case ripple::TxType::ttNFTOKEN_ACCEPT_OFFER:
case xrpl::TxType::ttNFTOKEN_ACCEPT_OFFER:
return getNFTokenAcceptOfferData(txMeta, sttx);
case ripple::TxType::ttNFTOKEN_CANCEL_OFFER:
case xrpl::TxType::ttNFTOKEN_CANCEL_OFFER:
return getNFTokenCancelOfferData(txMeta, sttx);
case ripple::TxType::ttNFTOKEN_CREATE_OFFER:
case xrpl::TxType::ttNFTOKEN_CREATE_OFFER:
return getNFTokenCreateOfferData(txMeta, sttx);
case ripple::TxType::ttNFTOKEN_MODIFY:
case xrpl::TxType::ttNFTOKEN_MODIFY:
return getNftokenModifyData(txMeta, sttx);
default:
@@ -361,19 +347,19 @@ std::vector<NFTsData>
getNFTDataFromObj(std::uint32_t const seq, std::string const& key, std::string const& blob)
{
// https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0020-non-fungible-tokens#tokenpage-id-format
ASSERT(key.size() == ripple::uint256::size(), "The size of the key (token) is expected to fit uint256 exactly");
ASSERT(key.size() == xrpl::uint256::size(), "The size of the key (token) is expected to fit uint256 exactly");
auto const sle =
ripple::STLedgerEntry(ripple::SerialIter{blob.data(), blob.size()}, ripple::uint256::fromVoid(key.data()));
xrpl::STLedgerEntry(xrpl::SerialIter{blob.data(), blob.size()}, xrpl::uint256::fromVoid(key.data()));
if (sle.getFieldU16(ripple::sfLedgerEntryType) != ripple::ltNFTOKEN_PAGE)
if (sle.getFieldU16(xrpl::sfLedgerEntryType) != xrpl::ltNFTOKEN_PAGE)
return {};
auto const owner = ripple::AccountID::fromVoid(key.data());
auto const owner = xrpl::AccountID::fromVoid(key.data());
std::vector<NFTsData> nfts;
for (ripple::STObject const& node : sle.getFieldArray(ripple::sfNFTokens))
nfts.emplace_back(node.getFieldH256(ripple::sfNFTokenID), seq, owner, node.getFieldVL(ripple::sfURI));
for (xrpl::STObject const& node : sle.getFieldArray(xrpl::sfNFTokens))
nfts.emplace_back(node.getFieldH256(xrpl::sfNFTokenID), seq, owner, node.getFieldVL(xrpl::sfURI));
return nfts;
}

View File

@@ -41,7 +41,7 @@ namespace etl {
* @return NFT URI change data as a pair of transactions and optional NFTsData
*/
std::pair<std::vector<NFTTransactionsData>, std::optional<NFTsData>>
getNftokenModifyData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx);
getNftokenModifyData(xrpl::TxMeta const& txMeta, xrpl::STTx const& sttx);
/**
* @brief Get the NFT Token mint data from a transaction
@@ -51,7 +51,7 @@ getNftokenModifyData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx);
* @return NFT Token mint data as a pair of transactions and optional NFTsData
*/
std::pair<std::vector<NFTTransactionsData>, std::optional<NFTsData>>
getNFTokenMintData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx);
getNFTokenMintData(xrpl::TxMeta const& txMeta, xrpl::STTx const& sttx);
/**
* @brief Get the NFT Token burn data from a transaction
@@ -61,7 +61,7 @@ getNFTokenMintData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx);
* @return NFT Token burn data as a pair of transactions and optional NFTsData
*/
std::pair<std::vector<NFTTransactionsData>, std::optional<NFTsData>>
getNFTokenBurnData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx);
getNFTokenBurnData(xrpl::TxMeta const& txMeta, xrpl::STTx const& sttx);
/**
* @brief Get the NFT Token accept offer data from a transaction
@@ -71,7 +71,7 @@ getNFTokenBurnData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx);
* @return NFT Token accept offer data as a pair of transactions and optional NFTsData
*/
std::pair<std::vector<NFTTransactionsData>, std::optional<NFTsData>>
getNFTokenAcceptOfferData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx);
getNFTokenAcceptOfferData(xrpl::TxMeta const& txMeta, xrpl::STTx const& sttx);
/**
* @brief Get the NFT Token cancel offer data from a transaction
@@ -81,7 +81,7 @@ getNFTokenAcceptOfferData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx
* @return NFT Token cancel offer data as a pair of transactions and optional NFTsData
*/
std::pair<std::vector<NFTTransactionsData>, std::optional<NFTsData>>
getNFTokenCancelOfferData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx);
getNFTokenCancelOfferData(xrpl::TxMeta const& txMeta, xrpl::STTx const& sttx);
/**
* @brief Get the NFT Token create offer data from a transaction
@@ -91,7 +91,7 @@ getNFTokenCancelOfferData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx
* @return NFT Token create offer data as a pair of transactions and optional NFTsData
*/
std::pair<std::vector<NFTTransactionsData>, std::optional<NFTsData>>
getNFTokenCreateOfferData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx);
getNFTokenCreateOfferData(xrpl::TxMeta const& txMeta, xrpl::STTx const& sttx);
/**
* @brief Pull NFT data from TX via ETLService.
@@ -101,7 +101,7 @@ getNFTokenCreateOfferData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx
* @return NFT transactions data as a pair of transactions and optional NFTsData
*/
std::pair<std::vector<NFTTransactionsData>, std::optional<NFTsData>>
getNFTDataFromTx(ripple::TxMeta const& txMeta, ripple::STTx const& sttx);
getNFTDataFromTx(xrpl::TxMeta const& txMeta, xrpl::STTx const& sttx);
/**
* @brief Pull NFT data from ledger object via loadInitialLedger.

View File

@@ -58,11 +58,11 @@ namespace etl {
* @code{.cpp}
* struct Ext {
* using spec = etl::model::Spec<
* ripple::TxType::ttNFTOKEN_BURN,
* ripple::TxType::ttNFTOKEN_ACCEPT_OFFER,
* ripple::TxType::ttNFTOKEN_CREATE_OFFER,
* ripple::TxType::ttNFTOKEN_CANCEL_OFFER,
* ripple::TxType::ttNFTOKEN_MINT>;
* xrpl::TxType::ttNFTOKEN_BURN,
* xrpl::TxType::ttNFTOKEN_ACCEPT_OFFER,
* xrpl::TxType::ttNFTOKEN_CREATE_OFFER,
* xrpl::TxType::ttNFTOKEN_CANCEL_OFFER,
* xrpl::TxType::ttNFTOKEN_MINT>;
*
* static void
* onInitialTransaction(uint32_t, etl::model::Transaction const&);

View File

@@ -43,24 +43,20 @@
namespace etl::impl {
AsyncGrpcCall::AsyncGrpcCall(
uint32_t seq,
ripple::uint256 const& marker,
std::optional<ripple::uint256> const& nextMarker
)
AsyncGrpcCall::AsyncGrpcCall(uint32_t seq, xrpl::uint256 const& marker, std::optional<xrpl::uint256> const& nextMarker)
{
request_.set_user("ETL");
request_.mutable_ledger()->set_sequence(seq);
if (marker.isNonZero())
request_.set_marker(marker.data(), ripple::uint256::size());
request_.set_marker(marker.data(), xrpl::uint256::size());
nextPrefix_ = nextMarker ? nextMarker->data()[0] : 0x00;
auto const prefix = marker.data()[0];
LOG(log_.debug()) << "Setting up AsyncGrpcCall. marker = " << ripple::strHex(marker)
<< ". prefix = " << ripple::strHex(std::string(1, prefix))
<< ". nextPrefix_ = " << ripple::strHex(std::string(1, nextPrefix_));
LOG(log_.debug()) << "Setting up AsyncGrpcCall. marker = " << xrpl::strHex(marker)
<< ". prefix = " << xrpl::strHex(std::string(1, prefix))
<< ". nextPrefix_ = " << xrpl::strHex(std::string(1, nextPrefix_));
ASSERT(
nextPrefix_ > prefix or nextPrefix_ == 0x00,
@@ -157,7 +153,7 @@ AsyncGrpcCall::call(std::unique_ptr<org::xrpl::rpc::v1::XRPLedgerAPIService::Stu
std::string
AsyncGrpcCall::getMarkerPrefix()
{
return next_->marker().empty() ? std::string{} : ripple::strHex(std::string{next_->marker().data()[0]});
return next_->marker().empty() ? std::string{} : xrpl::strHex(std::string{next_->marker().data()[0]});
}
// this is used to generate edgeKeys - keys that were the last one in the onInitialObjects list

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