Compare commits

..
Author SHA1 Message Date
Ed Hennis a7add7ce15 Merge remote-tracking branch 'XRPLF/develop' into ximinez/acquireAsyncDispatch
* XRPLF/develop: (22 commits)
  chore: Bump version to 3.4.1 and make pkg_release 2
  build: Reduce number of conan logs (8548)
  chore: Fix readability-redundant-lambda-parameter-list (8544)
  fix: Reject Batch inner txs with the wrong wrapper (fixBatchV1_2)
  ci: Update Nexus packaging URL
  fix: Assorted integer-arithmetic hardening in the payment engine and ledger helpers
  fix: Change mpt subscription msg type back to `transaction` (8539)
  chore: Update clang-tidy image to v23 (8536)
  feat: Integrate Permissioned Domain & Credential Checks for Lending Protocol (6517)
  refactor: Group binaries in subdirectories (8535)
  chore: Split multiple-in-one into individual tests (8025)
  refactor: Migrate handlers to rpc-spec (B) (8484)
  build: Use images with Clang 23 except for clang-tidy (8530)
  chore: Update pre-commit hooks and image (8528)
  fix: Fix MPT partial payment overflow (8302)
  build: Use LLVM 23 (8522)
  refactor: Extract escrow lock helpers and paychan test helpers (7882)
  fix: Validate vetoed parameter type in feature RPC (7583)
  refactor: Use CheckEntry everywhere (8349)
  build: Make conan retry with Conan Center's source backups (8524)
  ...
2026-10-09 20:16:11 -04:00
Ed Hennis 1a1924dd30 Merge remote-tracking branch 'XRPLF/develop' into ximinez/acquireAsyncDispatch
* XRPLF/develop: (281 commits)
  refactor: Use NegativeUNLEntry everywhere (8365)
  build: Make clang-tools custom in Nix, to match what's being built (8521)
  refactor: Migrate handlers to rpc-spec (A) (8345)
  test: Declare, not define, entry instantiations in SLEBase test (8357)
  test: Add more tests for granular permissions (8459)
  fix: Enforce that MPT issuance flags are never cleared (8152)
  feat: Allow lending transactions in Batch (8244)
  feat: Add full support for all objects in `ledger_entry` (6319)
  build: Define XRPL_ASAN, XRPL_TSAN, and XRPL_UBSAN compile definitions (8483)
  refactor: Use LedgerHashesEntry everywhere (8369)
  refactor: Use EscrowEntry everywhere (8354)
  chore: Update nix flake file (8479)
  refactor: Use FeeSettingsEntry everywhere (8370)
  fix: Add string type validation for channel_id and signature (7582)
  test: Migrate three beast suites from beast::unit_test to gtest (7993)
  refactor: Build Throw messages with std::format (8474)
  feat: Implement Confidential mpt holder key update (8266)
  fix: Do not block MPToken deletion on unrelated confidential balances (8209)
  fix: Enable the large Number mantissa with MPTokensV2 (8330)
  chore: Add ignore revs for recent style changes (8463)
  ...
2026-10-06 18:52:40 -04:00
Ed Hennis 99859d2458 Fix doxygen style issue 2026-08-05 22:54:41 -04:00
Ed Hennis 7642bc6671 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-08-05 12:17:07 -04:00
Ed Hennis add33d853c Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-07-14 20:13:11 -04:00
Ed Hennis be0baf1b53 Fix new header to use "#pragma once" 2026-07-10 11:41:11 -04:00
Ed Hennis b394730bd0 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-07-09 19:50:02 -04:00
Ed Hennis 8290eb3024 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-05-19 16:53:50 -04:00
Ed Hennis d537684df5 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-05-19 10:15:30 -04:00
Ed Hennis 4085361251 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-05-19 05:16:07 -04:00
Ed Hennis 1de7c130b0 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-05-15 21:43:33 -04:00
Ed Hennis 2a678a1157 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-05-14 20:39:23 -04:00
Ed Hennis 5c254aadf2 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-05-13 22:32:06 -04:00
Ed Hennis ad2db1962e Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-05-13 12:03:54 -04:00
Ed Hennis 4dae405762 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-05-12 19:19:01 -04:00
Ed Hennis b21b3596f8 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-05-12 16:26:24 -04:00
Ed Hennis d648539b62 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-05-11 13:34:26 -04:00
Ed Hennis 50644c6d30 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-05-07 18:10:17 -04:00
Ed Hennis 88c248077e Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-05-07 14:18:43 -04:00
Ed Hennis bad40d7e10 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-05-07 13:28:46 -04:00
Ed Hennis 74d0c375ec Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-05-06 22:34:37 -04:00
Ed Hennis 200ab3f694 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-05-06 14:18:16 -04:00
Ed Hennis a7a4357022 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-05-05 16:46:58 -04:00
Ed Hennis e0230a1e22 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-05-05 10:50:49 -04:00
Ed Hennis 5f1a98397c Merge remote-tracking branch 'XRPLF/develop' into ximinez/acquireAsyncDispatch
* XRPLF/develop:
  ci: Rewrite clang-tidy workflow(s) in a reusable manner (7062)
  chore: Ignore identifier-naming update in git blame (7066)
  refactor: Enable clang-tidy `readability-identifier-naming` check (6571)
2026-05-05 00:26:38 -04:00
Ed Hennis c8ca624974 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-05-01 13:59:18 -04:00
Ed Hennis 4489cda841 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-04-28 16:23:47 -04:00
Ed Hennis 784774005e Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-04-25 14:45:58 -04:00
Ed Hennis 904b39a3d3 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-04-23 15:56:15 -04:00
Ed Hennis eadfabfe4f Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-04-22 23:40:40 -04:00
Ed Hennis d991f81e87 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-04-22 14:49:17 -04:00
Ed Hennis a34a96e233 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-04-22 13:10:48 -04:00
Ed Hennis a3a277518b Merge remote-tracking branch 'XRPLF/develop' into ximinez/acquireAsyncDispatch
* XRPLF/develop:
  chore: Add -fix to clang-tidy invocation (6990)
  chore: Remove empty Taker.h (6984)
  chore: Enable clang-tidy modernize checks (6975)
  ci: Upload clang-tidy git diff (6983)
  fix: Add rounding to Vault invariants (6217) (6955)
2026-04-21 18:54:46 -04:00
Ed Hennis 8438698c54 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-04-20 17:49:51 -04:00
Ed Hennis 0597047d79 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-04-20 15:45:08 -04:00
Ed Hennis 992c6f525d Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-04-20 11:39:10 -04:00
Ed Hennis 9a870c36e2 Merge remote-tracking branch 'XRPLF/develop' into ximinez/acquireAsyncDispatch
* XRPLF/develop:
  chore: Enable clang-tidy include cleaner (6947)
  fix: Change AMMClawback return code to tecNO_PERMISSION (6946)
  ci: [DEPENDABOT] bump actions/upload-pages-artifact from 4.0.0 to 5.0.0 (6927)
  ci: [DEPENDABOT] bump actions/upload-artifact from 7.0.0 to 7.0.1 (6928)
  chore: Enable clang-tidy readability checks (6930)
2026-04-17 18:13:20 -04:00
Ed Hennis a4462e65bc Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-04-16 13:44:42 -04:00
Ed Hennis f0596c0a5d Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-04-15 19:06:33 -04:00
Ed Hennis dd99bc3ce8 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-04-15 14:29:00 -04:00
Ed Hennis 25cd7730e5 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-04-13 20:28:47 -04:00
Ed Hennis 8dcbcb22c2 Merge branch 'develop' into ximinez/acquireAsyncDispatch 2026-04-10 12:12:54 -04:00
Ed Hennis f44dfc89cc refactor: acquireAsync will dispatch a job, not the other way around
- Improve job queue collision checks and logging
    - Improve logging related to ledger acquisition and operating mode
      changes
    - Class "CanProcess" to keep track of processing of distinct items
2026-04-10 10:31:21 -04:00
690 changed files with 18742 additions and 37504 deletions

No files matched your search

+5
View File
@@ -76,6 +76,7 @@ Checks: "-*,
-readability-redundant-nested-if,
-readability-redundant-qualified-alias,
-readability-static-accessed-through-instance,
-readability-trailing-comma,
-readability-trivial-switch,
-readability-uppercase-literal-suffix
"
@@ -92,6 +93,10 @@ CheckOptions:
bugprone-unsafe-functions.ReportMoreUnsafeFunctions: true
bugprone-unused-return-value.CheckedReturnTypes: ::std::error_code;::std::error_condition;::std::errc
# New in clang-tidy 23; disabled until the code is updated
misc-const-correctness.AnalyzeAutoVariables: false
misc-const-correctness.AnalyzeLambdas: false
misc-const-correctness.AnalyzeParameters: false
misc-include-cleaner.IgnoreHeaders: ".*/(detail|impl)/.*;.*fwd\\.h(pp)?;time.h;stdlib.h;sqlite3.h;netinet/in\\.h;sys/resource\\.h;sys/sysinfo\\.h;linux/sysinfo\\.h;__chrono/.*;bits/.*;_abort\\.h;boost/.*;openssl/obj_mac\\.h"
readability-braces-around-statements.ShortStatementLines: 2
-15
View File
@@ -36,18 +36,3 @@ updates:
rust-dependencies:
patterns:
- "*"
- package-ecosystem: uv
directory: /cmake/scripts/codegen
schedule:
interval: weekly
day: monday
time: "04:00"
timezone: Etc/GMT
commit-message:
prefix: "chore: [DEPENDABOT] "
target-branch: develop
groups:
codegen-dependencies:
patterns:
- "*"
+1 -1
View File
@@ -66,7 +66,7 @@ jobs:
- name: Create issue
if: ${{ steps.audit.outcome != 'success' && github.event_name == 'schedule' }}
uses: XRPLF/actions/create-issue@b489c21d53928f7dab4874912fec40e4f6c9e85e
uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712
with:
title: "cargo audit found vulnerabilities"
body_file: /tmp/cargo-audit-issue.md
+1 -1
View File
@@ -53,7 +53,7 @@ jobs:
- name: Create issue
if: ${{ failure() && github.event_name == 'schedule' && github.repository == 'XRPLF/rippled' }}
uses: XRPLF/actions/create-issue@b489c21d53928f7dab4874912fec40e4f6c9e85e
uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712
with:
title: "Releases not merged back into develop"
body_file: ${{ env.ISSUE_FILE }}
+2 -2
View File
@@ -79,7 +79,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@8e98d61f011fd2a67f3fde5f0f075662c099a527
uses: XRPLF/actions/prepare-runner@b3e255d74d785d053e4903da8ac90983cd7d9e82
with:
enable_ccache: false
@@ -108,7 +108,7 @@ jobs:
- name: Upload regenerated snapshot
if: failure()
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: check-tools-${{ runner.os }}-${{ runner.arch }}
path: ${{ matrix.snapshot }}
+1 -1
View File
@@ -14,7 +14,7 @@ on:
jobs:
# Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks.
run-hooks:
uses: XRPLF/actions/.github/workflows/pre-commit.yml@d7f2acb47d9662e1e2f8b1f5feffa6d21cc3290a
uses: XRPLF/actions/.github/workflows/pre-commit.yml@279ec358f4a1be4088be3e024b07916fa97c75b6
with:
runs_on: ubuntu-latest
container: '{ "image": "ghcr.io/xrplf/xrpld/pre-commit:sha-70b8fd3" }'
+1 -1
View File
@@ -47,7 +47,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@8e98d61f011fd2a67f3fde5f0f075662c099a527
uses: XRPLF/actions/prepare-runner@b3e255d74d785d053e4903da8ac90983cd7d9e82
with:
enable_ccache: false
@@ -129,7 +129,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@8e98d61f011fd2a67f3fde5f0f075662c099a527
uses: XRPLF/actions/prepare-runner@b3e255d74d785d053e4903da8ac90983cd7d9e82
with:
enable_ccache: ${{ inputs.ccache_enabled }}
@@ -280,7 +280,7 @@ jobs:
- name: Upload the binary (Linux)
if: ${{ env.PACKAGING_ARTIFACTS_ENABLED == 'true' && runner.os == 'Linux' }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: xrpld-${{ inputs.config_name }}
path: ${{ env.BUILD_DIR }}/xrpld
@@ -294,7 +294,7 @@ jobs:
- name: Upload the validator-keys binary
if: ${{ env.PACKAGING_ARTIFACTS_ENABLED == 'true' && env.VALIDATOR_KEYS_ENABLED == 'true' }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: validator-keys-${{ inputs.config_name }}
path: |
@@ -305,7 +305,7 @@ jobs:
- name: Upload the test binary (Linux)
if: ${{ github.event.repository.visibility == 'public' && runner.os == 'Linux' }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: xrpl_tests-${{ inputs.config_name }}
path: ${{ env.BUILD_DIR }}/xrpl_tests
@@ -321,7 +321,7 @@ jobs:
- name: Upload server definitions
if: ${{ github.event.repository.visibility == 'public' && inputs.config_name == 'ubuntu-gcc-debug-amd64-coverage' }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: server-definitions
path: ${{ env.BUILD_DIR }}/server_definitions.json
+4 -4
View File
@@ -43,7 +43,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@8e98d61f011fd2a67f3fde5f0f075662c099a527
uses: XRPLF/actions/prepare-runner@b3e255d74d785d053e4903da8ac90983cd7d9e82
with:
enable_ccache: false
@@ -109,7 +109,7 @@ jobs:
- name: Upload clang-tidy output
if: ${{ github.event.repository.visibility == 'public' && steps.run_clang_tidy.outcome != 'success' }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
path: ${{ env.OUTPUT_FILE }}
archive: false
@@ -133,7 +133,7 @@ jobs:
- name: Upload clang-tidy diff output
if: ${{ github.event.repository.visibility == 'public' && steps.files_changed.outcome != 'success' }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
path: ${{ env.DIFF_FILE }}
archive: false
@@ -185,7 +185,7 @@ jobs:
- name: Create issue
if: ${{ steps.run_clang_tidy.outcome != 'success' && inputs.create_issue_on_failure }}
uses: XRPLF/actions/create-issue@b489c21d53928f7dab4874912fec40e4f6c9e85e
uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712
with:
title: "Clang-tidy check failed"
body_file: ${{ env.ISSUE_FILE }}
@@ -44,7 +44,7 @@ jobs:
# Every package lands in one directory; the step below picks its own,
# which keeps this independent of the artifact names.
- name: Download package artifacts
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: "*-pkg"
merge-multiple: true
@@ -95,15 +95,11 @@ jobs:
apt-get update -qq
apt-get install -y "./${PACKAGE}"
# Rocky Linux and AlmaLinux pick a mirror from a mirrorlist, and now and
# then get one that serves the repository metadata at a few hundred kB/s,
# which alone outlasts the job's timeout. dnf only abandons a mirror below
# 1000 B/s for 30 s, so raise that floor to fail over to the next one fast.
- name: Install the RPM
if: ${{ inputs.package_type == 'rpm' }}
env:
PACKAGE: ${{ steps.find.outputs.package }}
run: dnf install -y --setopt=minrate=1M --setopt=timeout=10 "./${PACKAGE}"
run: dnf install -y "./${PACKAGE}"
- name: Run xrpld
run: xrpld --version
+9 -9
View File
@@ -100,18 +100,18 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@8e98d61f011fd2a67f3fde5f0f075662c099a527
uses: XRPLF/actions/prepare-runner@b3e255d74d785d053e4903da8ac90983cd7d9e82
with:
enable_ccache: false
- name: Download pre-built xrpld binary
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: ${{ matrix.xrpld_artifact_name }}
path: ${{ env.BUILD_DIR }}
- name: Download pre-built validator-keys binary
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: ${{ matrix.validator_keys_artifact_name }}
path: ${{ env.BUILD_DIR }}
@@ -151,7 +151,7 @@ jobs:
# version starts with a digit and a longer name does not, so that one digit
# is what tells 'xrpld-3.4.1-...' from 'xrpld-assert-3.4.1-...'.
- name: Upload package artifact
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ matrix.xrpld_artifact_name }}-pkg
path: |
@@ -160,7 +160,7 @@ jobs:
if-no-files-found: error
- name: Upload debug symbol artifact
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ matrix.xrpld_artifact_name }}-pkg-debug
path: |
@@ -225,13 +225,13 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@8e98d61f011fd2a67f3fde5f0f075662c099a527
uses: XRPLF/actions/prepare-runner@b3e255d74d785d053e4903da8ac90983cd7d9e82
with:
enable_ccache: false
# Both artifacts, so the debug symbols are published alongside the package.
- name: Download package artifacts
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: ${{ matrix.xrpld_artifact_name }}-pkg*
merge-multiple: true
@@ -287,7 +287,7 @@ jobs:
run: echo "PUSH=${PUSH}" | tee -a "${GITHUB_ENV}"
- name: Download package artifacts
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: "*-pkg"
merge-multiple: true
@@ -295,7 +295,7 @@ jobs:
- name: Download voidstar binary
if: ${{ matrix.target == 'voidstar' }}
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: xrpld-ubuntu-clang-debug-amd64-voidstar
path: ${{ env.CONTEXT }}
+1 -1
View File
@@ -50,7 +50,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@8e98d61f011fd2a67f3fde5f0f075662c099a527
uses: XRPLF/actions/prepare-runner@b3e255d74d785d053e4903da8ac90983cd7d9e82
with:
enable_ccache: false
+1 -1
View File
@@ -68,7 +68,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@8e98d61f011fd2a67f3fde5f0f075662c099a527
uses: XRPLF/actions/prepare-runner@b3e255d74d785d053e4903da8ac90983cd7d9e82
with:
enable_ccache: false
-1
View File
@@ -35,7 +35,6 @@ Version 3.5.0 is not yet released.
- `channel_authorize`: The `channel_id` field now returns an `invalidParams` error if the value is not a string. [#7582](https://github.com/XRPLF/rippled/pull/7582)
- `channel_verify`: The `channel_id` and `signature` fields now return an `invalidParams` error if the value is not a string. [#7582](https://github.com/XRPLF/rippled/pull/7582)
- `account_currencies`, `account_nfts`, `account_offers`: A request with more than one problem may now report a different one of them. An invalid `ledger_hash` or `ledger_index` is reported before an invalid or missing `account`. An invalid `limit` or `marker` is reported before `lgrNotFound` or `actNotFound`, and for `account_offers` also before `actMalformed`. A request with a single problem returns the same error as before. [#8561](https://github.com/XRPLF/rippled/pull/8561)
### Bugfixes in 3.5.0
+1 -1
View File
@@ -42,7 +42,7 @@ if(is_gcc)
# GCC-specific fixes
add_compile_options(-Wno-unknown-pragmas -Wno-subobject-linkage)
# -Wno-subobject-linkage can be removed when we upgrade GCC version to at least 13.3
elseif(is_any_clang)
elseif(is_clang)
# Clang-specific fixes
add_compile_options(-Wno-unknown-warning-option) # Ignore unknown warning options
elseif(is_msvc)
+10 -16
View File
@@ -34,7 +34,7 @@ so tools can filter them and protection rules can target `release/*` and `stagin
- **Branches only move forward.**
`develop`, `staging/X.Y.x`, and `release/X.Y.x` are never rewritten.
- **Cherry-picking only goes from `develop` to a staging branch**,
for fixes that must get into a release after the [code freeze](#release-candidates)
for fixes that must get into a release after the code freeze
(see [Emergency Fixes From `develop`](#emergency-fixes-from-develop)).
- **Security fixes are prepared privately and published with the release that contains them**,
so vulnerabilities are not disclosed prematurely.
@@ -49,7 +49,6 @@ develop staging/X.Y.x & release/X.Y.x
│
├── Tag: X.Y.0-b1
├── Tag: X.Y.0-bN
│ (2 weeks before rc1: freeze on large changes starts)
├── Tag: X.Y.0-rc1 ───────────────┐ (branches created)
│ │
│ (development continues) ├── Fixes
@@ -76,20 +75,16 @@ develop staging/X.Y.x & release/X.Y.x
3. **Branches:** `staging/X.Y.x` and `release/X.Y.x` are created from `develop`
at the commit tagged `X.Y.0-rc1`.
The first RC also kicks off the QE process.
### Freeze on Large Changes
From two weeks before `X.Y.0-rc1` until `X.Y.0` is [merged back](#merging-back-into-develop),
large changes (e.g., big refactors, moving or renaming many files, mass reformatting)
are not merged into `develop`.
4. **Code freeze:** No new features or unrelated changes are pulled from `develop`
into `staging/X.Y.x` or `release/X.Y.x`.
Only critical stabilization fixes go into the line.
5. **No large changes on `develop`:** Until `X.Y.0` is [merged back](#merging-back-into-develop),
large changes (e.g., big refactors, moving or renaming many files, mass reformatting)
are not merged into `develop`,
so that fixes on the line and the merge back don't run into conflicts.
### Release Candidates
After branching, the line is in code freeze:
no new features or unrelated changes are pulled from `develop`
into `staging/X.Y.x` or `release/X.Y.x`.
Only critical stabilization fixes go into the line.
1. Fixes are developed against `staging/X.Y.x`.
2. When ready, a new RC is created on `staging/X.Y.x`,
and `release/X.Y.x` is fast-forwarded to it.
@@ -111,8 +106,7 @@ one right after the other.
2. `release/X.Y.x` is fast-forwarded to `staging/X.Y.x`,
and the release is tagged on it.
3. The release is immediately [merged back into `develop`](#merging-back-into-develop).
For a major-minor release, this lifts the [freeze on large changes](#freeze-on-large-changes)
in `develop`.
For a major-minor release, this lifts the freeze on large changes in `develop`.
### Merging Back Into `develop`
@@ -133,7 +127,7 @@ After the merge, `git log develop..<tag>` must be empty.
### Emergency Fixes From `develop`
If a commit was merged to `develop`
and needs to be included in a release after the [code freeze](#release-candidates):
and needs to be included in a release after the code freeze:
1. Create a PR that cherry-picks the commit onto `staging/X.Y.x`.
2. Leave `develop` as it is, with no reverts.
+3 -11
View File
@@ -9,21 +9,13 @@ include_guard(GLOBAL)
# --------------------------------------------------------------------
# Compiler detection (C++)
# --------------------------------------------------------------------
# is_any_clang is true for both LLVM Clang and AppleClang. Their version numbers
# and feature sets differ, so use is_llvm_clang or is_apple_clang when it matters.
set(is_any_clang FALSE)
set(is_llvm_clang FALSE)
set(is_apple_clang FALSE)
set(is_clang FALSE)
set(is_gcc FALSE)
set(is_msvc FALSE)
set(is_xcode FALSE)
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(is_any_clang TRUE)
set(is_llvm_clang TRUE)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
set(is_any_clang TRUE)
set(is_apple_clang TRUE)
if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") # Clang or AppleClang
set(is_clang TRUE)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(is_gcc TRUE)
elseif(MSVC)
+3 -6
View File
@@ -130,7 +130,7 @@ else()
INTERFACE
-Wall
-Wdeprecated
$<$<BOOL:${is_any_clang}>:-Wno-deprecated-declarations>
$<$<BOOL:${is_clang}>:-Wno-deprecated-declarations>
$<$<BOOL:${wextra}>:-Wextra
-Wno-unused-parameter>
$<$<BOOL:${werr}>:-Werror>
@@ -177,7 +177,7 @@ else()
if(
is_nix_compiler
AND is_linux
AND is_any_clang
AND is_clang
AND CMAKE_CXX_FLAGS MATCHES "stdlib=libstdc"
)
string(
@@ -204,10 +204,7 @@ if(voidstar)
"Antithesis instrumentation requires Linux, aborting..."
)
elseif(
NOT (
is_llvm_clang
AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0
)
NOT (is_clang AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0)
)
message(
FATAL_ERROR
+1 -7
View File
@@ -296,13 +296,7 @@ if(xrpld)
OUT_VAR rpcspec_instantiations
VALUE_TYPE "::json::Value"
VIEW_HEADER "xrpld/rpc/detail/JsonObjectView.hpp"
HANDLERS
account_currencies
account_nfts
account_offers
book_changes
ledger
transaction_entry
HANDLERS book_changes ledger transaction_entry
)
target_sources(xrpld PRIVATE ${rpcspec_instantiations})
+1 -1
View File
@@ -58,7 +58,7 @@ target_link_options(common INTERFACE ${sanitizers_linker_flags})
# This module appends -fsanitize-ignorelist=<path> for Clang builds.
# The ignorelist path contains CMAKE_SOURCE_DIR, so it must be set here, rather than in the Conan profile.
# GCC does not support -fsanitize-ignorelist.
if(is_any_clang)
if(is_clang)
set(ignorelist_path
"${CMAKE_SOURCE_DIR}/sanitizers/suppressions/sanitizer-ignorelist.txt"
)
+5 -2
View File
@@ -23,8 +23,11 @@ if(NOT is_multiconfig)
endif()
endif()
if(is_llvm_clang)
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0)
if(is_clang) # both Clang and AppleClang
if(
"${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang"
AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0
)
message(FATAL_ERROR "This project requires clang 16 or later")
endif()
elseif(is_gcc)
+3 -3
View File
@@ -62,11 +62,11 @@ if(unity)
set(CMAKE_UNITY_BUILD ON CACHE BOOL "Do a unity build")
endif()
if(is_llvm_clang AND is_linux)
if(is_clang AND is_linux)
option(voidstar "Enable Antithesis instrumentation." OFF)
endif()
if(is_gcc OR is_any_clang)
if(is_gcc OR is_clang)
include(ProcessorCount)
ProcessorCount(PROCESSOR_COUNT)
@@ -125,7 +125,7 @@ else()
set(use_mold OFF CACHE BOOL "mold linker, linux only" FORCE)
endif()
if(is_any_clang)
if(is_clang)
option(use_lld "enables detection of lld linker" ON)
else()
set(use_lld OFF CACHE BOOL "try lld linker, clang only" FORCE)
+2 -2
View File
@@ -7,7 +7,7 @@
pcpp>=1.30
# Parser combinator library - used to parse the macro DSL
pyparsing>=3.3.3
pyparsing>=3.0.0
# Template engine - used to generate C++ code from templates
Mako>=1.4.2
Mako>=1.2.2
+6 -6
View File
@@ -1,8 +1,8 @@
# This file was autogenerated by uv via the following command:
# uv pip compile requirements.in --generate-hashes --output-file requirements.txt
mako==1.4.3 \
--hash=sha256:723296007c870bfd6b3f0c3230dba7198096e5269297ebf5e4eff9e7ffa39d4f \
--hash=sha256:cd6537fe88d5fec315c55c2f8529bc4ce7a9a352ad7db3eeaa6a66e2dd4ec37a
mako==1.3.12 \
--hash=sha256:8f61569480282dbf557145ce441e4ba888be453c30989f879f0d652e39f53ea9 \
--hash=sha256:9f778e93289bd410bb35daadeb4fc66d95a746f0b75777b942088b7fd7af550a
# via -r requirements.in
markupsafe==3.0.3 \
--hash=sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f \
@@ -99,7 +99,7 @@ pcpp==1.30 \
--hash=sha256:05fe08292b6da57f385001c891a87f40d6aa7f46787b03e8ba326d20a3297c6e \
--hash=sha256:5af9fbce55f136d7931ae915fae03c34030a3b36c496e72d9636cedc8e2543a1
# via -r requirements.in
pyparsing==3.3.3 \
--hash=sha256:928ae7e20211f3b6f3915a72f06a0cfd29ab9d24279dd6346b6b1a7146397d36 \
--hash=sha256:ece8c00a69cf01b45d0b1dedabb469c90d8caf996d4fda40f147627a122849a4
pyparsing==3.3.2 \
--hash=sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d \
--hash=sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc
# via -r requirements.in
+1 -1
View File
@@ -3,7 +3,7 @@
"requires": [
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1782392402.122708",
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1782392402.420688",
"xrpl-rpc-spec/0.1.23#56e8946f5b3fb949a3732e1a51135ca2%1790977482.197086",
"xrpl-rpc-spec/0.1.21#d536f87a2ae7d313452746cfa3ac4404%1790869005.122975",
"sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1782392403.185447",
"soci/4.0.3#e726491a03468795453f7c83fc924a96%1782392402.679521",
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1782307151.633168",
+1 -1
View File
@@ -40,7 +40,7 @@ class Xrpl(ConanFile):
"nudb/2.0.9",
"openssl/3.6.3",
"soci/4.0.3",
"xrpl-rpc-spec/0.1.23",
"xrpl-rpc-spec/0.1.21",
"zlib/1.3.2",
]
+10 -10
View File
@@ -57,9 +57,9 @@ dependencies = [
[[package]]
name = "cxx"
version = "1.0.205"
version = "1.0.202"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8a02bfeba9074b2bbb39492c9b0908ec854f455a3cccdcde7a1de55e2315e40"
checksum = "13f6de320895f42e6e081abb5c7983bedcf0b6d0ff9323de0d33f620c8ac1199"
dependencies = [
"cc",
"cxx-build",
@@ -72,9 +72,9 @@ dependencies = [
[[package]]
name = "cxx-build"
version = "1.0.205"
version = "1.0.202"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbc2ac76997619d2d888b58ad79488f1c835de41ca4dd3dd7082acf4ecb0a50f"
checksum = "4fde53ca86b9704a943fef0f1e1d836239a6aedca5de3c65fa9f97ec0bd46d39"
dependencies = [
"cc",
"codespan-reporting",
@@ -87,9 +87,9 @@ dependencies = [
[[package]]
name = "cxxbridge-cmd"
version = "1.0.205"
version = "1.0.202"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54a486ed16a3f2a053fe7f5b98db4c1a59846a23e8cb9e49f9d1bd48830d51a2"
checksum = "07bae89236c811fd4d08ed3441759ac4ac98d752cbfd3de341315ba16ad20ec3"
dependencies = [
"clap",
"codespan-reporting",
@@ -101,15 +101,15 @@ dependencies = [
[[package]]
name = "cxxbridge-flags"
version = "1.0.205"
version = "1.0.202"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c72569be94e2283764d334cd285980b747dbe221e27e315484eb6bcd93fa808a"
checksum = "49045042e5fced01b80742aba5508de82aa4f13677ed3fa2b4cda709c40c5918"
[[package]]
name = "cxxbridge-macro"
version = "1.0.205"
version = "1.0.202"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "423e795284a7f7b3f843c956a5322c4bc497b60c2dd1a6339da10313cb18d575"
checksum = "b181252e2e3d3b5d183afbdc033a3958b445eb3e1a0ae65fc3d4f5259f5da6fd"
dependencies = [
"indexmap",
"proc-macro2",
+118
View File
@@ -0,0 +1,118 @@
#pragma once
#include <functional>
#include <mutex>
#include <set>
/**
* RAII class to check if an Item is already being processed on another thread,
* as indicated by it's presence in a Collection.
*
* If the Item is not in the Collection, it will be added under lock in the
* ctor, and removed under lock in the dtor. The object will be considered
* "usable" and evaluate to `true`.
*
* If the Item is in the Collection, no changes will be made to the collection,
* and the CanProcess object will be considered "unusable".
*
* It's up to the caller to decide what "usable" and "unusable" mean. (e.g.
* Process or skip a block of code, or set a flag.)
*
* The current use is to avoid lock contention that would be involved in
* processing something associated with the Item.
*
* Examples:
*
* void IncomingLedgers::acquireAsync(LedgerHash const& hash, ...)
* {
* if (CanProcess check{acquiresMutex_, pendingAcquires_, hash})
* {
* acquire(hash, ...);
* }
* }
*
* bool
* NetworkOPsImp::recvValidation(
* std::shared_ptr<STValidation> const& val,
* std::string const& source)
* {
* CanProcess check(
* validationsMutex_, pendingValidations_, val->getLedgerHash());
* BypassAccept bypassAccept =
* check ? BypassAccept::no : BypassAccept::yes;
* handleNewValidation(app_, val, source, bypassAccept, m_journal);
* }
*
*/
class CanProcess
{
public:
template <class Mutex, class Collection, class Item>
CanProcess(Mutex& mtx, Collection& collection, Item const& item)
: cleanup_(insert(mtx, collection, item))
{
}
~CanProcess()
{
if (cleanup_)
cleanup_();
}
CanProcess(CanProcess const&) = delete;
CanProcess&
operator=(CanProcess const&) = delete;
explicit
operator bool() const
{
return static_cast<bool>(cleanup_);
}
private:
template <bool useIterator, class Mutex, class Collection, class Item>
std::function<void()>
doInsert(Mutex& mtx, Collection& collection, Item const& item)
{
std::unique_lock<Mutex> lock(mtx);
// TODO: Use structured binding once LLVM 16 is the minimum supported
// version. See also: https://github.com/llvm/llvm-project/issues/48582
// https://github.com/llvm/llvm-project/commit/127bf44385424891eb04cff8e52d3f157fc2cb7c
auto const insertResult = collection.insert(item);
auto const it = insertResult.first;
if (!insertResult.second)
return {};
if constexpr (useIterator)
return [&, it]() {
std::unique_lock<Mutex> lock(mtx);
collection.erase(it);
};
else
return [&]() {
std::unique_lock<Mutex> lock(mtx);
collection.erase(item);
};
}
// Generic insert() function doesn't use iterators because they may get
// invalidated
template <class Mutex, class Collection, class Item>
std::function<void()>
insert(Mutex& mtx, Collection& collection, Item const& item)
{
return doInsert<false>(mtx, collection, item);
}
// Specialize insert() for std::set, which does not invalidate iterators for
// insert and erase
template <class Mutex, class Item>
std::function<void()>
insert(Mutex& mtx, std::set<Item>& collection, Item const& item)
{
return doInsert<true>(mtx, collection, item);
}
// If set, then the item is "usable"
std::function<void()> cleanup_;
};
+1 -1
View File
@@ -34,7 +34,7 @@ lz4Compress(void const* in, std::size_t inSize, BufferFactory&& bf)
// data
auto compressed = bf(outCapacity);
auto const compressedSize = LZ4_compress_default(
auto compressedSize = LZ4_compress_default(
reinterpret_cast<char const*>(in),
reinterpret_cast<char*>(compressed),
inSize,
+30 -38
View File
@@ -20,14 +20,12 @@ SharedIntrusive<T>::SharedIntrusive(T* p, TAdoptTag) noexcept : ptr_{p}
template <class T>
SharedIntrusive<T>::SharedIntrusive(SharedIntrusive const& rhs)
: ptr_{
[&] {
auto p = rhs.unsafeGetRawPtr();
if (p)
p->addStrongRef();
return p;
}(),
}
: ptr_{[&] {
auto p = rhs.unsafeGetRawPtr();
if (p)
p->addStrongRef();
return p;
}()}
{
}
@@ -35,14 +33,12 @@ template <class T>
template <class TT>
requires std::convertible_to<TT*, T*>
SharedIntrusive<T>::SharedIntrusive(SharedIntrusive<TT> const& rhs)
: ptr_{
[&] {
auto p = rhs.unsafeGetRawPtr();
if (p)
p->addStrongRef();
return p;
}(),
}
: ptr_{[&] {
auto p = rhs.unsafeGetRawPtr();
if (p)
p->addStrongRef();
return p;
}()}
{
}
@@ -144,14 +140,12 @@ SharedIntrusive<T>::~SharedIntrusive()
template <class T>
template <class TT>
SharedIntrusive<T>::SharedIntrusive(StaticCastTagSharedIntrusive, SharedIntrusive<TT> const& rhs)
: ptr_{
[&] {
auto p = static_cast<T*>(rhs.unsafeGetRawPtr());
if (p)
p->addStrongRef();
return p;
}(),
}
: ptr_{[&] {
auto p = static_cast<T*>(rhs.unsafeGetRawPtr());
if (p)
p->addStrongRef();
return p;
}()}
{
}
@@ -165,14 +159,12 @@ SharedIntrusive<T>::SharedIntrusive(StaticCastTagSharedIntrusive, SharedIntrusiv
template <class T>
template <class TT>
SharedIntrusive<T>::SharedIntrusive(DynamicCastTagSharedIntrusive, SharedIntrusive<TT> const& rhs)
: ptr_{
[&] {
auto p = dynamic_cast<T*>(rhs.unsafeGetRawPtr());
if (p)
p->addStrongRef();
return p;
}(),
}
: ptr_{[&] {
auto p = dynamic_cast<T*>(rhs.unsafeGetRawPtr());
if (p)
p->addStrongRef();
return p;
}()}
{
}
@@ -268,7 +260,7 @@ SharedIntrusive<T>::unsafeReleaseAndStore(T* next)
return;
using enum ReleaseStrongRefAction;
auto const action = prev->releaseStrongRef();
auto action = prev->releaseStrongRef();
switch (action)
{
case NoOp:
@@ -369,7 +361,7 @@ WeakIntrusive<T>::unsafeReleaseNoStore()
return;
using enum ReleaseWeakRefAction;
auto const action = ptr_->releaseWeakRef();
auto action = ptr_->releaseWeakRef();
switch (action)
{
case NoOp:
@@ -588,7 +580,7 @@ SharedWeakUnion<T>::convertToStrong()
auto p = unsafeGetRawPtr();
if (p && p->checkoutStrongRefFromWeak())
{
[[maybe_unused]] auto const action = p->releaseWeakRef();
[[maybe_unused]] auto action = p->releaseWeakRef();
XRPL_ASSERT(
(action == ReleaseWeakRefAction::NoOp),
"xrpl::SharedWeakUnion::convertToStrong : "
@@ -611,7 +603,7 @@ SharedWeakUnion<T>::convertToWeak()
return false;
using enum ReleaseStrongRefAction;
auto const action = p->addWeakReleaseStrongRef();
auto action = p->addWeakReleaseStrongRef();
switch (action)
{
case NoOp:
@@ -678,7 +670,7 @@ SharedWeakUnion<T>::unsafeReleaseNoStore()
if (isStrong())
{
using enum ReleaseStrongRefAction;
auto const strongAction = p->releaseStrongRef();
auto strongAction = p->releaseStrongRef();
switch (strongAction)
{
case NoOp:
@@ -696,7 +688,7 @@ SharedWeakUnion<T>::unsafeReleaseNoStore()
else
{
using enum ReleaseWeakRefAction;
auto const weakAction = p->releaseWeakRef();
auto weakAction = p->releaseWeakRef();
switch (weakAction)
{
case NoOp:
+2 -2
View File
@@ -406,10 +406,10 @@ IntrusiveRefCounts::useCount() const noexcept
inline IntrusiveRefCounts::~IntrusiveRefCounts() noexcept
{
#ifndef NDEBUG
auto const v = refCounts_.load(std::memory_order_acquire);
auto v = refCounts_.load(std::memory_order_acquire);
XRPL_ASSERT(
(!(v & kValueMask)), "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : count must be zero");
auto const t = v & kTagMask;
auto t = v & kTagMask;
XRPL_ASSERT((!t || t == kTagMask), "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : valid tag");
#endif
}
-72
View File
@@ -39,31 +39,6 @@ checkedSub(std::int64_t a, std::int64_t b) noexcept
return a - b;
}
/**
* Multiply two signed 64-bit integers, returning std::nullopt when the exact
* mathematical product is not representable in std::int64_t.
*/
[[nodiscard]] constexpr std::optional<std::int64_t>
checkedMul(std::int64_t a, std::int64_t b) noexcept
{
using L = std::numeric_limits<std::int64_t>;
if (a == 0 || b == 0)
return 0;
if (a > 0)
{
if (b > 0 ? a > L::max() / b : b < L::min() / a)
return std::nullopt;
}
else if (b > 0 ? a < L::min() / b : b < L::max() / a)
{
return std::nullopt;
}
return a * b;
}
static_assert(checkedAdd(0, 0) == 0);
static_assert(checkedAdd(1, -1) == 0);
static_assert(checkedAdd(-5, 2) == -3);
@@ -106,53 +81,6 @@ static_assert(
!checkedSub(std::numeric_limits<std::int64_t>::min(), std::numeric_limits<std::int64_t>::max())
.has_value());
static_assert(checkedMul(0, std::numeric_limits<std::int64_t>::min()) == 0);
static_assert(checkedMul(std::numeric_limits<std::int64_t>::min(), 0) == 0);
static_assert(checkedMul(-1, -1) == 1);
// a > 0, b > 0
static_assert(
checkedMul(std::numeric_limits<std::int64_t>::max(), 1) ==
std::numeric_limits<std::int64_t>::max());
static_assert(
checkedMul(std::numeric_limits<std::int64_t>::max() / 2, 2) ==
std::numeric_limits<std::int64_t>::max() - 1);
static_assert(!checkedMul((std::numeric_limits<std::int64_t>::max() / 2) + 1, 2).has_value());
static_assert(!checkedMul(2, (std::numeric_limits<std::int64_t>::max() / 2) + 1).has_value());
// a > 0, b < 0
static_assert(
checkedMul(std::numeric_limits<std::int64_t>::max(), -1) ==
-std::numeric_limits<std::int64_t>::max());
static_assert(
checkedMul((std::numeric_limits<std::int64_t>::max() / 2) + 1, -2) ==
std::numeric_limits<std::int64_t>::min());
static_assert(!checkedMul((std::numeric_limits<std::int64_t>::max() / 2) + 2, -2).has_value());
static_assert(
checkedMul(1, std::numeric_limits<std::int64_t>::min()) ==
std::numeric_limits<std::int64_t>::min());
static_assert(
checkedMul(2, std::numeric_limits<std::int64_t>::min() / 2) ==
std::numeric_limits<std::int64_t>::min());
static_assert(!checkedMul(2, (std::numeric_limits<std::int64_t>::min() / 2) - 1).has_value());
// a < 0, b > 0
static_assert(
checkedMul(std::numeric_limits<std::int64_t>::min(), 1) ==
std::numeric_limits<std::int64_t>::min());
static_assert(
checkedMul(std::numeric_limits<std::int64_t>::min() / 2, 2) ==
std::numeric_limits<std::int64_t>::min());
static_assert(!checkedMul((std::numeric_limits<std::int64_t>::min() / 2) - 1, 2).has_value());
static_assert(!checkedMul(std::numeric_limits<std::int64_t>::min(), 2).has_value());
// a < 0, b < 0
static_assert(
checkedMul(-(std::numeric_limits<std::int64_t>::max() / 2), -2) ==
std::numeric_limits<std::int64_t>::max() - 1);
static_assert(!checkedMul(std::numeric_limits<std::int64_t>::min() / 2, -2).has_value());
static_assert(
checkedMul(-1, -std::numeric_limits<std::int64_t>::max()) ==
std::numeric_limits<std::int64_t>::max());
static_assert(!checkedMul(std::numeric_limits<std::int64_t>::min(), -1).has_value());
static_assert(!checkedMul(-1, std::numeric_limits<std::int64_t>::min()).has_value());
/**
* Calculate one number divided by another number in percentage.
* The result is rounded up to the next integer, and capped in the range [0,100]
+1 -1
View File
@@ -340,7 +340,7 @@ public:
for (auto const& c : cfg)
{
auto const& a = allocators_.emplace_back(c.extra_, c.alloc_, c.align_);
auto& a = allocators_.emplace_back(c.extra_, c.alloc_, c.align_);
if (a.size() > maxSize_)
maxSize_ = a.size();
+3 -34
View File
@@ -153,24 +153,6 @@ private:
Policy policy,
Callback&& replaceCallback = nullptr);
/**
* canonicalizeImpl variant for callers that already hold `mutex_`.
*
* The unnamed `scoped_lock<MutexType> const&` parameter is proof of
* ownership; this overload does not acquire the lock. Use it from other
* methods (e.g. fetchAndModify) that need to compose canonicalize with
* additional work under a single critical section, without relying on
* recursive-mutex re-entry.
*/
template <class Policy, class Callback = std::nullptr_t>
bool
canonicalizeImpl(
std::scoped_lock<MutexType> const&,
key_type const& key,
CanonicalizeClientPointerType<Policy> data,
Policy policy,
Callback&& replaceCallback = nullptr);
public:
/**
* Replace aliased objects with originals.
@@ -257,6 +239,9 @@ public:
bool
retrieve(key_type const& key, T& data);
MutexType&
peekMutex();
std::vector<key_type>
getKeys() const;
@@ -278,22 +263,6 @@ public:
fetch(key_type const& digest, Handler const& h);
// End CachedSLEs functions.
/**
* Fetch or create an entry and execute a callback while holding the lock.
*
* The entry for the given key is fetched from the cache or created if it
* doesn't exist. The callback is then invoked with a reference to the
* entry while the cache mutex is still held, allowing safe modification
* of the cached object.
*
* @param key The key to fetch or create
* @param callback Function to call with the entry under lock.
* Signature: void(T&)
*/
template <class Callback>
void
fetchAndModify(key_type const& key, Callback&& callback);
private:
SharedPointerType
initialFetch(key_type const& key, std::scoped_lock<MutexType> const& l);
+25 -74
View File
@@ -4,7 +4,6 @@
#include <xrpl/basics/Log.h> // IWYU pragma: keep
#include <xrpl/basics/TaggedCache.h>
#include <xrpl/basics/scope.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <algorithm>
@@ -301,7 +300,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
// Remove from cache, if !valid, remove from map too. Returns true if removed from cache
std::scoped_lock const lock(mutex_);
auto const cit = cache_.find(key);
auto cit = cache_.find(key);
if (cit == cache_.end())
return false;
@@ -336,29 +335,6 @@ template <class Policy, class Callback>
inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
canonicalizeImpl(
key_type const& key,
CanonicalizeClientPointerType<Policy> data,
Policy policy,
Callback&& replaceCallback)
{
std::scoped_lock<MutexType> const lock(mutex_);
return canonicalizeImpl(lock, key, data, policy, std::forward<Callback>(replaceCallback));
}
template <
class Key,
class T,
bool IsKeyCache,
class SharedWeakUnionPointer,
class SharedPointerType,
class Hash,
class KeyEqual,
class Mutex>
template <class Policy, class Callback>
inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
canonicalizeImpl(
std::scoped_lock<MutexType> const&,
key_type const& key,
CanonicalizeClientPointerType<Policy> data,
[[maybe_unused]] Policy policy,
@@ -378,7 +354,9 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
// passing a const argument is a compile error.
constexpr bool replaceCached = std::is_same_v<Policy, detail::ReplaceCached>;
auto const cit = cache_.find(key);
std::scoped_lock const lock(mutex_);
auto cit = cache_.find(key);
if (cit == cache_.end())
{
@@ -393,7 +371,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
Entry& entry = cit->second;
entry.touch(clock_.now());
auto const shouldReplaceCached = [&] {
auto shouldReplaceCached = [&] {
if constexpr (replaceCached)
{
return true;
@@ -422,7 +400,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
return true;
}
auto const cachedData = entry.lock();
auto cachedData = entry.lock();
if (cachedData)
{
@@ -585,7 +563,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
retrieve(key_type const& key, T& data)
{
// retrieve the value of the stored data
auto const entry = fetch(key);
auto entry = fetch(key);
if (!entry)
return false;
@@ -594,6 +572,22 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
return true;
}
template <
class Key,
class T,
bool IsKeyCache,
class SharedWeakUnionPointer,
class SharedPointerType,
class Hash,
class KeyEqual,
class Mutex>
inline auto
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
peekMutex() -> MutexType&
{
return mutex_;
}
template <
class Key,
class T,
@@ -693,7 +687,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
return ret;
}
auto const sle = h();
auto sle = h();
if (!sle)
return {};
@@ -706,49 +700,6 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
}
// End CachedSLEs functions.
template <
class Key,
class T,
bool IsKeyCache,
class SharedWeakUnionPointer,
class SharedPointerType,
class Hash,
class KeyEqual,
class Mutex>
template <class Callback>
inline void
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
fetchAndModify(key_type const& key, Callback&& callback)
{
static_assert(
!IsKeyCache, "fetchAndModify is only supported for value caches, not key-only caches");
static_assert(
std::is_same_v<std::shared_ptr<T>, SharedPointerType> ||
std::is_same_v<intr_ptr::SharedPtr<T>, SharedPointerType>,
"fetchAndModify requires std::shared_ptr<T> or intr_ptr::SharedPtr<T>");
std::scoped_lock<MutexType> const lock(mutex_);
// Same pointer-type dispatch as insert(): the placeholder must have exactly
// SharedPointerType so canonicalizeImpl can write the cached pointer back.
SharedPointerType entry = [] {
if constexpr (std::is_same_v<std::shared_ptr<T>, SharedPointerType>)
{
return std::make_shared<T>();
}
else
{
return intr_ptr::makeShared<T>();
}
}();
canonicalizeImpl(lock, key, entry, detail::ReplaceClient{});
ALWAYS(
entry != nullptr, "xrpl::TaggedCache::fetchAndModify : entry present after canonicalize");
callback(*entry);
}
template <
class Key,
class T,
@@ -762,7 +713,7 @@ inline SharedPointerType
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
initialFetch(key_type const& key, std::scoped_lock<MutexType> const& l)
{
auto const cit = cache_.find(key);
auto cit = cache_.find(key);
if (cit == cache_.end())
return {};
+13 -7
View File
@@ -195,8 +195,7 @@ private:
{
// Local lambda that converts a single hex char to four bits and
// ORs those bits into a uint32_t.
auto const hexCharToUInt =
[](char c, std::uint32_t shift, std::uint32_t& accum) -> ParseResult {
auto hexCharToUInt = [](char c, std::uint32_t shift, std::uint32_t& accum) -> ParseResult {
std::uint32_t nibble = 0xFFu;
if (c < '0' || c > 'f')
return ParseResult::BadChar;
@@ -454,7 +453,7 @@ public:
{
for (int i = kWidth - 1; i >= 0; --i)
{
auto const prev = data_[i];
auto prev = data_[i];
data_[i] = boost::endian::native_to_big(boost::endian::big_to_native(data_[i]) - 1);
if (prev != 0)
@@ -596,16 +595,23 @@ operator<=>(BaseUInt<Bits, Tag> const& lhs, BaseUInt<Bits, Tag> const& rhs)
// note that the underlying data is stored in big endian, even if the
// platform is little endian. This makes the comparison correct.
//
// memcmp compares unsigned bytes in order, and is much faster than a
// byte-at-a-time loop.
return std::memcmp(lhs.data(), rhs.data(), lhs.size()) <=> 0;
// FIXME: use std::lexicographical_compare_three_way once support is
// added to MacOS.
auto const ret = std::mismatch(lhs.cbegin(), lhs.cend(), rhs.cbegin());
// a == b
if (ret.first == lhs.cend())
return std::strong_ordering::equivalent;
return (*ret.first > *ret.second) ? std::strong_ordering::greater : std::strong_ordering::less;
}
template <std::size_t Bits, typename Tag>
[[nodiscard]] constexpr bool
operator==(BaseUInt<Bits, Tag> const& lhs, BaseUInt<Bits, Tag> const& rhs)
{
return std::memcmp(lhs.data(), rhs.data(), lhs.size()) == 0;
return (lhs <=> rhs) == 0; // NOLINT(modernize-use-nullptr)
}
//------------------------------------------------------------------------------
@@ -365,7 +365,7 @@ public:
size() const
{
std::size_t ret = 0;
for (auto const& p : map_)
for (auto& p : map_)
ret += p.size();
return ret;
}
@@ -2536,7 +2536,7 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
return false;
for (auto iter(cbegin()), last(cend()), otherLast(other.cend()); iter != last; ++iter)
{
auto const otherIter(other.find(extract(*iter)));
auto otherIter(other.find(extract(*iter)));
if (otherIter == otherLast)
return false;
}
+1 -1
View File
@@ -68,7 +68,7 @@ struct LexicalCast<Out, std::string_view>
if (first != last && *first == '+')
++first;
auto const ret = std::from_chars(first, last, out);
auto ret = std::from_chars(first, last, out);
return ret.ec == std::errc() && ret.ptr == last;
}
+1 -1
View File
@@ -83,7 +83,7 @@ trimRight(String const& s)
{
using std::begin;
using std::end;
auto const first(begin(s));
auto first(begin(s));
auto last(end(s));
last = trimRight(first, last);
return {first, last};
+1 -1
View File
@@ -32,7 +32,7 @@ public:
Module,
// Match nothing (used internally)
None,
None
};
private:
+1 -1
View File
@@ -24,7 +24,7 @@ enum class Severity : std::uint8_t {
Fatal = 5,
Disabled = 6,
None = Disabled,
None = Disabled
};
/**
+1 -1
View File
@@ -18,7 +18,7 @@ enum class Type : std::uint8_t {
PrefixSha256 = 1,
ThresholdSha256 = 2,
RsaSha256 = 3,
Ed25519Sha256 = 4,
Ed25519Sha256 = 4
};
class Condition
@@ -49,7 +49,7 @@ public:
using namespace der;
auto const p = parsePreamble(s, ec);
auto p = parsePreamble(s, ec);
if (ec)
return nullptr;
+1 -1
View File
@@ -21,7 +21,7 @@ enum class Error {
UnexpectedTag,
LongTag,
LargeSize,
PreimageTooLong,
PreimageTooLong
};
std::error_code
+1 -1
View File
@@ -396,7 +396,7 @@ inline bool
getIfExists<bool>(Section const& section, std::string const& name, bool& v)
{
int intVal = 0;
auto const stat = getIfExists(section, name, intVal);
auto stat = getIfExists(section, name, intVal);
if (stat)
v = bool(intVal);
return stat;
+2 -2
View File
@@ -93,14 +93,14 @@ public:
void
check(std::vector<TxID> accepted, Predicate&& pred)
{
auto const acceptTxid = accepted.begin();
auto acceptTxid = accepted.begin();
auto const ae = accepted.end();
std::sort(acceptTxid, ae);
// We want to remove all tracking entries for transactions that were
// accepted as well as those which match the predicate.
auto const i = removeIfIntersectOrMatch(
auto i = removeIfIntersectOrMatch(
tracker_.begin(),
tracker_.end(),
accepted.begin(),
+9 -10
View File
@@ -779,7 +779,7 @@ Consensus<Adaptor>::peerProposalInternal(
{
// update current position
auto const peerPosIt = currPeerPositions_.find(peerID);
auto peerPosIt = currPeerPositions_.find(peerID);
if (peerPosIt != currPeerPositions_.end())
{
@@ -1110,7 +1110,7 @@ Consensus<Adaptor>::checkLedger(std::unique_ptr<std::stringstream> const& clog)
{
CLOG(clog) << "checkLedger. ";
auto const netLgr = adaptor_.getPrevLedger(prevLedgerID_, previousLedger_, mode_.get());
auto netLgr = adaptor_.getPrevLedger(prevLedgerID_, previousLedger_, mode_.get());
CLOG(clog) << "network ledgerid " << netLgr << ", "
<< "previous ledger " << prevLedgerID_ << ". ";
@@ -1159,8 +1159,8 @@ Consensus<Adaptor>::phaseOpen(std::unique_ptr<std::stringstream> const& clog)
// it is shortly before ledger close time
bool const anyTransactions = adaptor_.hasOpenTransactions();
auto const proposersClosed = currPeerPositions_.size();
auto const proposersValidated = adaptor_.proposersValidated(prevLedgerID_);
auto proposersClosed = currPeerPositions_.size();
auto proposersValidated = adaptor_.proposersValidated(prevLedgerID_);
openTime_.tick(clock_.now());
@@ -1669,7 +1669,7 @@ Consensus<Adaptor>::haveConsensus(std::unique_ptr<std::stringstream> const& clog
// CHECKME: should possibly count unacquired TX sets as disagreeing
int agree = 0, disagree = 0;
auto const ourPosition = result_->position.position();
auto ourPosition = result_->position.position();
// Count number of agreements/disagreements with our position
for (auto const& [nodeId, peerPos] : currPeerPositions_)
@@ -1686,7 +1686,7 @@ Consensus<Adaptor>::haveConsensus(std::unique_ptr<std::stringstream> const& clog
++disagree;
}
}
auto const currentFinished = adaptor_.proposersFinished(previousLedger_, prevLedgerID_);
auto currentFinished = adaptor_.proposersFinished(previousLedger_, prevLedgerID_);
JLOG(j_.debug()) << "Checking for TX consensus: agree=" << agree << ", disagree=" << disagree;
@@ -1812,7 +1812,7 @@ Consensus<Adaptor>::createDisputes(TxSetT const& o, std::unique_ptr<std::strings
<< ". ";
JLOG(j_.debug()) << "createDisputes " << result_->txns.id() << " to " << o.id();
auto const differences = result_->txns.compare(o);
auto differences = result_->txns.compare(o);
int dc = 0;
@@ -1826,7 +1826,7 @@ Consensus<Adaptor>::createDisputes(TxSetT const& o, std::unique_ptr<std::strings
"xrpl::Consensus::createDisputes : has disputed transactions");
TxT const tx = inThisSet ? result_->txns.find(txId) : o.find(txId);
auto const txID = tx.id();
auto txID = tx.id();
if (result_->disputes.find(txID) != result_->disputes.end())
continue;
@@ -1837,8 +1837,7 @@ Consensus<Adaptor>::createDisputes(TxSetT const& o, std::unique_ptr<std::strings
tx,
result_->txns.exists(txID),
std::max(prevProposers_, currPeerPositions_.size()),
j_,
};
j_};
// Update all of the available peer's votes on the disputed transaction
for (auto const& [nodeId, peerPos] : currPeerPositions_)
+8 -16
View File
@@ -145,26 +145,18 @@ struct ConsensusParms
std::map<AvalancheState, AvalancheCutoff> const avalancheCutoffs{
// {state, {time, percent, nextState}},
// Initial state: 50% of nodes must vote yes
{
AvalancheState::Init,
{.consensusTime = 0, .consensusPct = 50, .next = AvalancheState::Mid},
},
{AvalancheState::Init,
{.consensusTime = 0, .consensusPct = 50, .next = AvalancheState::Mid}},
// mid-consensus starts after 50% of the previous round time, and
// requires 65% yes
{
AvalancheState::Mid,
{.consensusTime = 50, .consensusPct = 65, .next = AvalancheState::Late},
},
{AvalancheState::Mid,
{.consensusTime = 50, .consensusPct = 65, .next = AvalancheState::Late}},
// late consensus starts after 85% time, and requires 70% yes
{
AvalancheState::Late,
{.consensusTime = 85, .consensusPct = 70, .next = AvalancheState::Stuck},
},
{AvalancheState::Late,
{.consensusTime = 85, .consensusPct = 70, .next = AvalancheState::Stuck}},
// we're stuck after 2x time, requires 95% yes votes
{
AvalancheState::Stuck,
{.consensusTime = 200, .consensusPct = 95, .next = AvalancheState::Stuck},
},
{AvalancheState::Stuck,
{.consensusTime = 200, .consensusPct = 95, .next = AvalancheState::Stuck}},
};
/**
+3 -3
View File
@@ -59,7 +59,7 @@ enum class ConsensusMode {
* if we entered the round observing, but is used to indicate we did
* have the wrongLedger at some point.
*/
SwitchedLedger,
SwitchedLedger
};
inline std::string
@@ -222,7 +222,7 @@ medianCloseOffset(ConsensusCloseTimes const& times)
// Accumulate weight in time order; the first bin to reach halfWeight is
// the (lower) weighted median. Returns true once that bin is found.
auto const step = [&](time_point t, std::int64_t w) {
auto step = [&](time_point t, std::int64_t w) {
XRPL_ASSERT(tally < halfWeight, "xrpl::medianCloseOffset::step : median not yet found");
tally += w;
if (tally >= halfWeight)
@@ -267,7 +267,7 @@ enum class ConsensusState {
No, ///< We do not have consensus
MovedOn, ///< The network has consensus without us
Expired, ///< Consensus time limit has hard-expired
Yes, ///< We have consensus along with the network
Yes ///< We have consensus along with the network
};
/**
+1 -1
View File
@@ -266,7 +266,7 @@ template <class Tx, class NodeId>
void
DisputedTx<Tx, NodeId>::unVote(NodeId const& peer)
{
auto const it = votes_.find(peer);
auto it = votes_.find(peer);
if (it != votes_.end())
{
+1 -1
View File
@@ -211,7 +211,7 @@ struct Node
void
erase(Node const* child)
{
auto const it = std::ranges::find_if(
auto it = std::ranges::find_if(
children, [child](std::unique_ptr<Node> const& curr) { return curr.get() == child; });
XRPL_ASSERT(it != children.end(), "xrpl::Node::erase : valid input");
std::swap(*it, children.back());
+9 -9
View File
@@ -184,7 +184,7 @@ enum class ValStatus {
/**
* Multiple validations by a validator for different ledgers
*/
Conflicting,
Conflicting
};
inline std::string
@@ -366,7 +366,7 @@ private:
removeTrie(std::scoped_lock<Mutex> const&, NodeID const& nodeID, Validation const& val)
{
{
auto const it = acquiring_.find(std::make_pair(val.seq(), val.ledgerID()));
auto it = acquiring_.find(std::make_pair(val.seq(), val.ledgerID()));
if (it != acquiring_.end())
{
it->second.erase(nodeID);
@@ -375,7 +375,7 @@ private:
}
}
{
auto const it = lastLedger_.find(nodeID);
auto it = lastLedger_.find(nodeID);
if (it != lastLedger_.end() && it->second.id() == val.ledgerID())
{
trie_.remove(it->second);
@@ -443,7 +443,7 @@ private:
// Clear any prior acquiring ledger for this node
if (prior)
{
auto const it = acquiring_.find(*prior);
auto it = acquiring_.find(*prior);
if (it != acquiring_.end())
{
it->second.erase(nodeID);
@@ -455,7 +455,7 @@ private:
checkAcquired(lock);
std::pair<Seq, ID> const valPair{val.seq(), val.ledgerID()};
auto const it = acquiring_.find(valPair);
auto it = acquiring_.find(valPair);
if (it != acquiring_.end())
{
it->second.insert(nodeID);
@@ -529,7 +529,7 @@ private:
}
else
{
auto const cit = typename decltype(current_)::const_iterator{it};
auto cit = typename decltype(current_)::const_iterator{it};
// contains a live record
f(cit->first, cit->second);
++it;
@@ -554,7 +554,7 @@ private:
void
byLedger(std::scoped_lock<Mutex> const&, ID const& ledgerID, Pre&& pre, F&& f)
{
auto const it = byLedger_.find(ledgerID);
auto it = byLedger_.find(ledgerID);
if (it != byLedger_.end())
{
// Update set time since it is being used
@@ -857,7 +857,7 @@ public:
if (!preferred)
{
// fall back to majority over acquiring ledgers
auto const it = std::ranges::max_element(acquiring_, [](auto const& a, auto const& b) {
auto it = std::ranges::max_element(acquiring_, [](auto const& a, auto const& b) {
std::pair<Seq, ID> const& aKey = a.first;
typename HashSet<NodeID>::size_type const& aSize = a.second.size();
std::pair<Seq, ID> const& bKey = b.first;
@@ -937,7 +937,7 @@ public:
return (preferred->first >= minSeq) ? preferred->second : lcl.id();
// Otherwise, rely on peer ledgers
auto const it = std::ranges::max_element(peerCounts, [](auto const& a, auto const& b) {
auto it = std::ranges::max_element(peerCounts, [](auto const& a, auto const& b) {
// Prefer larger counts, then larger ids on ties
// (max_element expects this to return true if a < b)
return std::tie(a.second, a.first) < std::tie(b.second, b.first);
+1 -1
View File
@@ -156,7 +156,7 @@ public:
{
if (!allClosuresDoneCond_.wait_for(lock, wait, [this] { return closureCount_ == 0; }))
{
if (auto const stream = j.error())
if (auto stream = j.error())
stream << name << " waiting for ClosureCounter::join().";
allClosuresDoneCond_.wait(lock, [this] { return closureCount_ == 0; });
}
+2 -2
View File
@@ -37,7 +37,7 @@ enum class HashRouterFlags : std::uint16_t {
PRIVATE6 = 0x2000,
// Used in apply.cpp
PRIVATE7 = 0x4000,
PRIVATE8 = 0x8000,
PRIVATE8 = 0x8000
};
constexpr HashRouterFlags
@@ -221,7 +221,7 @@ public:
/**
* Add a suppression peer and get message's relay status.
* Return pair:
* element 1: true if the peer is added.
* element 1: true if the key is added.
* element 2: optional is seated to the relay time point or
* is unseated if has not relayed yet.
*/
+6 -6
View File
@@ -30,12 +30,12 @@ private:
using namespace std::chrono_literals;
int const maxLimit = std::numeric_limits<int>::max();
auto const add = [this](
JobType jt,
std::string name,
int limit,
std::chrono::milliseconds avgLatency,
std::chrono::milliseconds peakLatency) {
auto add = [this](
JobType jt,
std::string name,
int limit,
std::chrono::milliseconds avgLatency,
std::chrono::milliseconds peakLatency) {
XRPL_ASSERT(!map.contains(jt), "xrpl::JobTypes::JobTypes::add : unique job type input");
[[maybe_unused]] auto const inserted =
+3 -4
View File
@@ -177,13 +177,12 @@ measureDurationAndLog(
std::chrono::duration<Rep, Period> maxDelay,
beast::Journal const& journal)
{
auto const startTime = std::chrono::high_resolution_clock::now();
auto startTime = std::chrono::high_resolution_clock::now();
auto result = func();
auto const endTime = std::chrono::high_resolution_clock::now();
auto const duration =
std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);
auto endTime = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);
if (duration > maxDelay)
{
JLOG(journal.warn()) << actionDescription << " took " << duration.count() << " ms";
+1 -1
View File
@@ -95,7 +95,7 @@ private:
ArraySeparator,
MemberSeparator,
Comment,
Error,
Error
};
class Token
+1 -1
View File
@@ -26,7 +26,7 @@ enum class ValueType {
String, ///< UTF-8 string value
Boolean, ///< bool value
Array, ///< array value (ordered list)
Object, ///< object value (collection of name/value pairs).
Object ///< object value (collection of name/value pairs).
};
/**
+1 -1
View File
@@ -165,7 +165,7 @@ public:
beast::Journal j)
{
// Ask implementation what to do
auto const actions = doVoting(
auto actions = doVoting(
lastClosedLedger->rules(),
lastClosedLedger->parentCloseTime(),
getEnabledAmendments(*lastClosedLedger),
+1 -1
View File
@@ -50,7 +50,7 @@ enum ApplyFlags : std::uint32_t {
// afterward, so signature-presence checks (e.g. Batch signer matching)
// are skipped at proposal-creation time (On-Chain Cosigner spec
// §5.3.1.2).
TapProposal = 0x2000,
TapProposal = 0x2000
};
constexpr ApplyFlags
+1 -2
View File
@@ -20,8 +20,7 @@ constexpr std::chrono::seconds kLedgerPossibleTimeResolutions[] = {
std::chrono::seconds{30},
std::chrono::seconds{60},
std::chrono::seconds{90},
std::chrono::seconds{120},
};
std::chrono::seconds{120}};
/**
* Initial resolution of ledger close time.
+2 -2
View File
@@ -35,7 +35,7 @@ public:
{
std::scoped_lock const lock(mutex_);
auto const it = map_.find(seq);
auto it = map_.find(seq);
if ((it == map_.end()) || it->second)
{
@@ -88,7 +88,7 @@ public:
std::unique_lock<std::mutex> lock(mutex_);
do
{
auto const it = map_.find(seq);
auto it = map_.find(seq);
if (it == map_.end())
{
+3 -3
View File
@@ -164,7 +164,7 @@ getCandidateLedger(LedgerIndex requested)
areCompatible(
ReadView const& validLedger,
ReadView const& testLedger,
beast::Journal::Stream const& s,
beast::Journal::Stream& s,
char const* reason);
[[nodiscard]] bool
@@ -172,7 +172,7 @@ areCompatible(
UInt256 const& validHash,
LedgerIndex validIndex,
ReadView const& testLedger,
beast::Journal::Stream const& s,
beast::Journal::Stream& s,
char const* reason);
//------------------------------------------------------------------------------
@@ -185,7 +185,7 @@ areCompatible(
dirLink(
ApplyView& view,
AccountID const& owner,
SLE::pointer const& object,
SLE::pointer& object,
SF_UINT64 const& node = sfOwnerNode);
/**
+4 -8
View File
@@ -30,17 +30,13 @@ public:
static constexpr size_t kInitialBufferSize = kilobytes(256);
RawStateTable()
: monotonicResource_{
std::make_unique<boost::container::pmr::monotonic_buffer_resource>(
kInitialBufferSize),
}
: monotonicResource_{std::make_unique<boost::container::pmr::monotonic_buffer_resource>(
kInitialBufferSize)}
, items_{monotonicResource_.get()} {};
RawStateTable(RawStateTable const& rhs)
: monotonicResource_{
std::make_unique<boost::container::pmr::monotonic_buffer_resource>(
kInitialBufferSize),
}
: monotonicResource_{std::make_unique<boost::container::pmr::monotonic_buffer_resource>(
kInitialBufferSize)}
, items_{rhs.items_, monotonicResource_.get()}
, dropsDestroyed_{rhs.dropsDestroyed_} {};
+165 -86
View File
@@ -2,6 +2,7 @@
#include <xrpl/basics/Log.h>
#include <xrpl/basics/Number.h>
#include <xrpl/basics/contract.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/beast/utility/Zero.h>
#include <xrpl/ledger/ApplyView.h>
@@ -28,6 +29,7 @@
#include <expected>
#include <functional>
#include <optional>
#include <stdexcept>
#include <tuple>
#include <utility>
@@ -222,7 +224,7 @@ getAMMOfferStartWithTakerGets(
if (nTakerGetsConstraint < *nTakerGets)
nTakerGets = nTakerGetsConstraint;
auto const getAmounts = [&pool, &tfee](Number const& nTakerGetsProposed) {
auto getAmounts = [&pool, &tfee](Number const& nTakerGetsProposed) {
// Round downward to minimize the offer and to maximize the quality.
// This has the most impact when takerGets is integral.
auto const takerGets =
@@ -290,7 +292,7 @@ getAMMOfferStartWithTakerPays(
if (nTakerPaysConstraint < *nTakerPays)
nTakerPays = nTakerPaysConstraint;
auto const getAmounts = [&pool, &tfee](Number const& nTakerPaysProposed) {
auto getAmounts = [&pool, &tfee](Number const& nTakerPaysProposed) {
// Round downward to minimize the offer and to maximize the quality.
// This has the most impact when takerPays is integral.
auto const takerPays =
@@ -311,11 +313,11 @@ getAMMOfferStartWithTakerPays(
* is equal to LOB quality (in this case AMM offer quality is
* better than LOB quality) or AMM offer is equal to LOB quality
* (in this case SPQ is better than LOB quality).
* The economically coarser integral offer side is calculated first. The
* result is rounded down, which makes the offer quality better. Calculating
* takerPays first instead would round down takerGets when that is the coarser
* side, giving worse quality than LOB quality, and the offer might fail to
* generate.
* Pre-amendment code calculates takerPays first. If takerGets is the
* economically coarser integral side, it is rounded down, which results in
* worse offer quality than LOB quality, and the offer might fail to generate.
* Post-amendment code calculates the economically coarser integral offer side
* first. The result is rounded down, which makes the offer quality better.
* It might not be possible to match either SPQ or AMM offer to LOB
* quality. This generally happens at higher fees.
* @param pool AMM pool balances
@@ -329,8 +331,69 @@ changeSpotPriceQuality(
TAmounts<TIn, TOut> const& pool,
Quality const& quality,
std::uint16_t tfee,
Rules const& rules,
beast::Journal j)
{
if (!rules.enabled(fixAMMv1_1))
{
// Finds takerPays (i) and takerGets (o) such that given pool
// composition poolGets(I) and poolPays(O): (O - o) / (I + i) = quality.
// Where takerGets is calculated as the swapAssetIn (see below).
// The above equation produces the quadratic equation:
// i^2*(1-fee) + i*I*(2-fee) + I^2 - I*O/quality,
// which is solved for i, and o is found with swapAssetIn().
auto const f = feeMult(tfee); // 1 - fee
auto const& a = f;
auto const b = pool.in * (1 + f);
Number const c = pool.in * pool.in - pool.in * pool.out * quality.rate();
auto const res = b * b - 4 * a * c;
if (res < 0)
{
return std::nullopt; // LCOV_EXCL_LINE
}
if (auto const nTakerPaysPropose = (-b + root2(res)) / (2 * a); nTakerPaysPropose > 0)
{
auto const nTakerPays = [&] {
// The fee might make the AMM offer quality less than CLOB
// quality. Therefore, AMM offer has to satisfy this constraint:
// o / i >= q. Substituting o with swapAssetIn() gives: i <= O /
// q - I / (1 - fee).
auto const nTakerPaysConstraint = pool.out * quality.rate() - pool.in / f;
if (nTakerPaysPropose > nTakerPaysConstraint)
return nTakerPaysConstraint;
return nTakerPaysPropose;
}();
if (nTakerPays <= 0)
{
JLOG(j.trace()) << "changeSpotPriceQuality calc failed: " << to_string(pool.in)
<< " " << to_string(pool.out) << " " << quality << " " << tfee;
return std::nullopt;
}
auto const takerPays =
toAmount<TIn>(getAsset(pool.in), nTakerPays, Number::RoundingMode::Upward);
// should not fail
auto amounts = TAmounts<TIn, TOut>{takerPays, swapAssetIn(pool, takerPays, tfee)};
if (Quality{amounts} < quality &&
!withinRelativeDistance(Quality{amounts}, quality, Number(1, -7)))
{
JLOG(j.error()) << "changeSpotPriceQuality failed: " << to_string(pool.in) << " "
<< to_string(pool.out) << " "
<< " " << quality << " " << tfee << " " << to_string(amounts.in)
<< " " << to_string(amounts.out);
Throw<std::runtime_error>("changeSpotPriceQuality failed");
}
JLOG(j.trace()) << "changeSpotPriceQuality succeeded: " << to_string(pool.in) << " "
<< to_string(pool.out) << " "
<< " " << quality << " " << tfee << " " << to_string(amounts.in) << " "
<< to_string(amounts.out);
return amounts;
}
JLOG(j.trace()) << "changeSpotPriceQuality calc failed: " << to_string(pool.in) << " "
<< to_string(pool.out) << " " << quality << " " << tfee;
return std::nullopt;
}
auto amounts = [&] {
bool const inIntegral = getAsset(pool.in).integral();
bool const outIntegral = getAsset(pool.out).integral();
@@ -396,49 +459,57 @@ template <typename TIn, typename TOut>
TOut
swapAssetIn(TAmounts<TIn, TOut> const& pool, TIn const& assetIn, std::uint16_t tfee)
{
// set rounding to always favor the amm. Clip to zero.
// calculate:
// pool.out -
// (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)),
// and explicitly set the rounding modes
// Favoring the amm means we should:
// minimize:
// pool.out -
// (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)),
// maximize:
// (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)),
// (pool.in * pool.out)
// minimize:
// (pool.in + assetIn * feeMult(tfee)),
// minimize:
// assetIn * feeMult(tfee)
// feeMult is: (1-fee), fee is tfee/100000
// minimize:
// 1-fee
// maximize:
// fee
SaveNumberRoundMode const _{Number::getround()};
if (auto const& rules = getCurrentTransactionRules(); rules && rules->enabled(fixAMMv1_1))
{
// set rounding to always favor the amm. Clip to zero.
// calculate:
// pool.out -
// (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)),
// and explicitly set the rounding modes
// Favoring the amm means we should:
// minimize:
// pool.out -
// (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)),
// maximize:
// (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)),
// (pool.in * pool.out)
// minimize:
// (pool.in + assetIn * feeMult(tfee)),
// minimize:
// assetIn * feeMult(tfee)
// feeMult is: (1-fee), fee is tfee/100000
// minimize:
// 1-fee
// maximize:
// fee
SaveNumberRoundMode const _{Number::getround()};
Number::setround(Number::RoundingMode::Upward);
auto const numerator = pool.in * pool.out;
auto const fee = getFee(tfee);
Number::setround(Number::RoundingMode::Upward);
auto const numerator = pool.in * pool.out;
auto const fee = getFee(tfee);
Number::setround(Number::RoundingMode::Downward);
auto const denom = pool.in + assetIn * (1 - fee);
Number::setround(Number::RoundingMode::Downward);
auto const denom = pool.in + assetIn * (1 - fee);
if (denom.signum() <= 0)
return toAmount<TOut>(getAsset(pool.out), 0);
if (denom.signum() <= 0)
return toAmount<TOut>(getAsset(pool.out), 0);
Number::setround(Number::RoundingMode::Upward);
auto const ratio = numerator / denom;
Number::setround(Number::RoundingMode::Upward);
auto const ratio = numerator / denom;
Number::setround(Number::RoundingMode::Downward);
auto const swapOut = pool.out - ratio;
Number::setround(Number::RoundingMode::Downward);
auto const swapOut = pool.out - ratio;
if (swapOut.signum() < 0)
return toAmount<TOut>(getAsset(pool.out), 0);
if (swapOut.signum() < 0)
return toAmount<TOut>(getAsset(pool.out), 0);
return toAmount<TOut>(getAsset(pool.out), swapOut, Number::RoundingMode::Downward);
return toAmount<TOut>(getAsset(pool.out), swapOut, Number::RoundingMode::Downward);
}
return toAmount<TOut>(
getAsset(pool.out),
pool.out - (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)),
Number::RoundingMode::Downward);
}
/**
@@ -455,49 +526,57 @@ template <typename TIn, typename TOut>
TIn
swapAssetOut(TAmounts<TIn, TOut> const& pool, TOut const& assetOut, std::uint16_t tfee)
{
// set rounding to always favor the amm. Clip to zero.
// calculate:
// ((pool.in * pool.out) / (pool.out - assetOut) - pool.in) /
// (1-tfee/100000)
// maximize:
// ((pool.in * pool.out) / (pool.out - assetOut) - pool.in)
// maximize:
// (pool.in * pool.out) / (pool.out - assetOut)
// maximize:
// (pool.in * pool.out)
// minimize
// (pool.out - assetOut)
// minimize:
// (1-tfee/100000)
// maximize:
// tfee/100000
SaveNumberRoundMode const _{Number::getround()};
Number::setround(Number::RoundingMode::Upward);
auto const numerator = pool.in * pool.out;
Number::setround(Number::RoundingMode::Downward);
auto const denom = pool.out - assetOut;
if (denom.signum() <= 0)
if (auto const& rules = getCurrentTransactionRules(); rules && rules->enabled(fixAMMv1_1))
{
return toMaxAmount<TIn>(getAsset(pool.in));
// set rounding to always favor the amm. Clip to zero.
// calculate:
// ((pool.in * pool.out) / (pool.out - assetOut) - pool.in) /
// (1-tfee/100000)
// maximize:
// ((pool.in * pool.out) / (pool.out - assetOut) - pool.in)
// maximize:
// (pool.in * pool.out) / (pool.out - assetOut)
// maximize:
// (pool.in * pool.out)
// minimize
// (pool.out - assetOut)
// minimize:
// (1-tfee/100000)
// maximize:
// tfee/100000
SaveNumberRoundMode const _{Number::getround()};
Number::setround(Number::RoundingMode::Upward);
auto const numerator = pool.in * pool.out;
Number::setround(Number::RoundingMode::Downward);
auto const denom = pool.out - assetOut;
if (denom.signum() <= 0)
{
return toMaxAmount<TIn>(getAsset(pool.in));
}
Number::setround(Number::RoundingMode::Upward);
auto const ratio = numerator / denom;
auto const numerator2 = ratio - pool.in;
auto const fee = getFee(tfee);
Number::setround(Number::RoundingMode::Downward);
auto const feeMult = 1 - fee;
Number::setround(Number::RoundingMode::Upward);
auto const swapIn = numerator2 / feeMult;
if (swapIn.signum() < 0)
return toAmount<TIn>(getAsset(pool.in), 0);
return toAmount<TIn>(getAsset(pool.in), swapIn, Number::RoundingMode::Upward);
}
Number::setround(Number::RoundingMode::Upward);
auto const ratio = numerator / denom;
auto const numerator2 = ratio - pool.in;
auto const fee = getFee(tfee);
Number::setround(Number::RoundingMode::Downward);
auto const feeMult = 1 - fee;
Number::setround(Number::RoundingMode::Upward);
auto const swapIn = numerator2 / feeMult;
if (swapIn.signum() < 0)
return toAmount<TIn>(getAsset(pool.in), 0);
return toAmount<TIn>(getAsset(pool.in), swapIn, Number::RoundingMode::Upward);
return toAmount<TIn>(
getAsset(pool.in),
((pool.in * pool.out) / (pool.out - assetOut) - pool.in) / feeMult(tfee),
Number::RoundingMode::Upward);
}
/**
@@ -791,8 +870,8 @@ deleteAMMAccount(Sandbox& view, Asset const& asset, Asset const& asset2, beast::
*/
void
initializeFeeAuctionVote(
ApplyView const& view,
SLE::pointer const& ammSle,
ApplyView& view,
SLE::pointer& ammSle,
AccountID const& account,
Asset const& lptAsset,
std::uint16_t tfee);
@@ -814,7 +893,7 @@ std::expected<bool, TER>
verifyAndAdjustLPTokenBalance(
Sandbox& sb,
STAmount const& lpTokens,
SLE::pointer const& ammSle,
SLE::pointer& ammSle,
AccountID const& account);
} // namespace xrpl
+31 -125
View File
@@ -7,10 +7,10 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/VaultHelpers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Asset.h>
#include <xrpl/protocol/LedgerFormats.h> // IWYU pragma: keep
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/Rules.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STAmount.h>
@@ -31,9 +31,9 @@ namespace xrpl {
/**
* Broker cover preclaim precision guard (fixCleanup3_2_0).
*
* Prevents a silent sub-ULP no-op where a deposit, withdrawal, or clawback
* amount is so small that it rounds to zero at sfCoverAvailable's scale.
* Without this guard, both the pseudo trust-line and sfCoverAvailable would
* Prevents a "silent sub-ULP no-op" where a deposit, withdrawal, or clawback
* amount is so small that it rounds to zero at `sfCoverAvailable`'s scale.
* Without this guard, both the pseudo trust-line and `sfCoverAvailable` would
* identically absorb the rounded zero, resulting in a successful transaction
* (tesSUCCESS) where no funds actually moved.
*
@@ -44,8 +44,8 @@ namespace xrpl {
* @param j Journal for logging.
* @param logPrefix Transactor name for log diagnostics.
*
* @return tecPRECISION_LOSS if the request rounds to zero at cover scale.
* tesSUCCESS if the amendment is disabled or the request is safely supra-ULP.
* @return `tecPRECISION_LOSS` if the request rounds to zero at cover scale.
* `tesSUCCESS` if the amendment is disabled or the request is safely supra-ULP.
*/
[[nodiscard]] TER
canApplyToBrokerCover(
@@ -56,82 +56,6 @@ canApplyToBrokerCover(
beast::Journal j,
std::string_view logPrefix);
namespace detail {
/**
* Return a LoanBroker's posterior live cover exponent after applying an
* unrounded delta.
*/
[[nodiscard]] int
getPosteriorBrokerCoverScale(SLE::ConstRef vault, SLE::ConstRef broker, Number const& delta);
/**
* Round a cover outflow delta (cover withdraw, cover clawback, the
* broker-side decrease of a default's cover credit) at the LoanBroker's
* posterior live exponent. Safe to round the delta directly for an outflow:
* amount on the posterior grid of CoverAvailable always leaves CoverAvailable
* minus amount representable, since the posterior grid is exactly the grid
* CoverAvailable itself will canonicalize to after the subtraction.
*/
[[nodiscard]] STAmount
roundToPosteriorBrokerCoverScale(
SLE::ConstRef vault,
SLE::ConstRef broker,
STAmount const& delta,
Number::RoundingMode roundingMode);
} // namespace detail
/**
* Round a cover debit (cover withdraw, cover clawback, the broker-side
* decrease of a default's cover credit): amount is the non-negative
* magnitude leaving CoverAvailable. Negates so the posterior is computed for
* CoverAvailable minus amount, then negates the result back to a
* non-negative magnitude, per roundToPosteriorBrokerCoverScale's outflow
* rationale above. Magnitude in, magnitude out -- unlike the vault-side
* outflow dispatcher (clampVaultOutflow), which takes and returns a negative
* delta; callers on each side already hold the value in that side's native
* form.
*/
[[nodiscard]] STAmount
debitToPosteriorBrokerCoverScale(
SLE::ConstRef vault,
SLE::ConstRef broker,
STAmount const& amount,
Number::RoundingMode roundingMode);
/**
* Round a cover inflow (cover deposit, LoanPay's fee redirect into cover)
* into CoverAvailable by flooring the sum rather than the delta:
* credit = floor16(CoverAvailable + raw) - CoverAvailable, never finer
* than the Vault's base exponent (-Scale). See
* creditToPosteriorAvailableScale's doc for why the sum, not the delta,
* must be floored; the same reasoning applies to CoverAvailable.
*/
[[nodiscard]] STAmount
creditToPosteriorBrokerCoverScale(
SLE::ConstRef vault,
SLE::ConstRef broker,
Number const& raw,
Number::RoundingMode roundingMode);
/**
* Check whether amount is an admissible optional cover inflow.
*
* Legacy and CashBasis Vaults always succeed. A LoanBroker attached to a
* FixedPrecision Vault must remain at the Vault's base scale after applying
* the rounded amount, and its posterior CoverAvailable must stay within the
* Open zone.
*
* LoanPay's fee redirect into cover is a mandatory inflow and does not call
* this check, so it can push CoverAvailable past the Open zone limit this
* check enforces. Once that happens, every subsequent LoanBrokerCoverDeposit
* returns tecLIMIT_EXCEEDED until the owner withdraws cover back under the
* limit; LoanBrokerCoverWithdraw and LoanBrokerCoverClawback are unaffected.
*/
[[nodiscard]] TER
checkOptionalBrokerCoverInflow(SLE::ConstRef vault, SLE::ConstRef broker, STAmount const& amount);
// Lending protocol has dependencies, so capture them here.
bool
checkLendingProtocolDependencies(Rules const& rules, STTx const& tx);
@@ -140,13 +64,13 @@ checkLendingProtocolDependencies(Rules const& rules, STTx const& tx);
* The accounts and asset that LoanManage::defaultLoan's fixCleanup3_4_0
* freeze/lock exemption applies to.
*
* defaultLoan moves funds from the LoanBroker pseudo-account to the Vault
* pseudo-account via accountSend. Since neither is the vault asset's
* `defaultLoan` moves funds from the LoanBroker pseudo-account to the Vault
* pseudo-account via `accountSend`. Since neither is the vault asset's
* issuer, this is a third-party transfer that transits through the issuer in
* two hops (broker -> issuer, issuer -> vault; see
* directSendNoLimitIOU/directSendNoLimitMPT), so the exemption must cover
* `directSendNoLimitIOU`/`directSendNoLimitMPT`), so the exemption must cover
* both the issuer/broker and issuer/vault pairs, not a direct broker/vault
* pair. asset scopes it further to the vault's own currency/MPT issuance,
* pair. `asset` scopes it further to the vault's own currency/MPT issuance,
* so an unrelated one the same accounts happen to hold is still protected.
*/
struct LoanDefaultFreezeExemptAccounts
@@ -164,10 +88,10 @@ struct LoanDefaultFreezeExemptAccounts
* @param view Ledger view used to resolve the Loan -> LoanBroker -> Vault
* chain.
* @param tx The transaction under invariant review.
* @return The exempt accounts and asset if tx is a ttLOAN_MANAGE
* transaction with the tfLoanDefault flag set, fixCleanup3_4_0 is
* @return The exempt accounts and asset if `tx` is a `ttLOAN_MANAGE`
* transaction with the `tfLoanDefault` flag set, `fixCleanup3_4_0` is
* enabled, and the loan/broker/vault objects it references can all be
* resolved; std::nullopt otherwise.
* resolved; `std::nullopt` otherwise.
*/
[[nodiscard]] std::optional<LoanDefaultFreezeExemptAccounts>
getLoanDefaultFreezeExemptAccounts(ReadView const& view, STTx const& tx);
@@ -338,38 +262,20 @@ getAssetsTotalScale(SLE::ConstRef vaultSle)
return scale(vaultSle->at(sfAssetsTotal), vaultSle->at(sfAsset));
}
/**
* Apply a signed delta to a LoanBroker's DebtTotal: on FixedPrecision Vaults,
* add the exact delta (DebtTotal moves by exactly the same amount as the
* Vault's AssetsDeployed, never re-rounded); on Legacy/CashBasis Vaults,
* round through adjustImpreciseNumber at vaultScale. Shared by LoanSet
* (origination) and LoanPay (payment, where delta is negative).
*
* @param brokerSle The LoanBroker whose DebtTotal is adjusted.
* @param vaultSle The LoanBroker's Vault.
* @param delta The signed change to DebtTotal.
* @param vaultScale The Vault scale the caller captured before changing
* AssetsTotal. Legacy/CashBasis round DebtTotal at that scale, not at
* the scale after this transaction's AssetsTotal change. Unused on
* FixedPrecision Vaults.
*/
void
adjustBrokerDebtTotal(
SLE::Ref brokerSle,
SLE::ConstRef vaultSle,
Number const& delta,
int vaultScale);
/**
* Minimum required broker cover, rounded up.
*
* DebtTotal is a broker-level aggregate, never rounded at an individual
* loan's scale. Legacy and CashBasis Vaults round at the live AssetsTotal
* exponent. FixedPrecision Vaults round at the Vault's base exponent
* (-Scale, or 0 for integral assets).
*/
Number
minimumBrokerCover(Number const& debtTotal, TenthBips32 coverRateMinimum, SLE::ConstRef vaultSle);
// Compute the minimum required broker cover, rounded consistently.
// DebtTotal is a broker-level aggregate maintained at vault scale, so the
// rounding must also use vault scale — never an individual loan's scale.
inline Number
minimumBrokerCover(Number const& debtTotal, TenthBips32 coverRateMinimum, SLE::ConstRef vaultSle)
{
XRPL_ASSERT(
vaultSle && vaultSle->getType() == ltVAULT, "xrpl::minimumBrokerCover : valid Vault sle");
NumberRoundModeGuard const mg(Number::RoundingMode::Upward);
return roundToAsset(
vaultSle->at(sfAsset),
tenthBipsOfValue(debtTotal, coverRateMinimum),
getAssetsTotalScale(vaultSle));
}
TER
checkLoanGuards(
@@ -473,10 +379,10 @@ loanPaymentDeltas(LoanPaymentParts const& parts);
} // namespace cash_basis
// Public dispatchers: pick cash_basis:: if the Vault's LEVersion
// (VaultHelpers::getVaultVersion) is CashBasis or later (CashBasis or
// FixedPrecision), else instant_recognition::. These are the only entry
// points transactors call.
// Public dispatchers: pick cash_basis:: if featureLendingProtocolV1_1 is
// enabled AND the Vault's LEVersion (VaultHelpers::getVaultVersion) is
// VaultVersion::CashBasis, else instant_recognition::. These are the only entry points
// transactors call.
AccountingDeltas
loanOriginationDeltas(
SLE::ConstRef vaultSle,
+4 -25
View File
@@ -312,22 +312,12 @@ checkCreateMPT(
//
//------------------------------------------------------------------------------
/**
* MaximumAmount doesn't exceed 2**63-1
*/
// MaximumAmount doesn't exceed 2**63-1
std::int64_t
maxMPTAmount(SLE const& sleIssuance);
/**
* std::nullopt if the issuance doesn't exist.
*/
std::optional<std::int64_t>
maxMPTAmount(ReadView const& view, MPTID const& mptID);
/**
* OutstandingAmount may overflow and available amount might be negative.
* But available amount is always <= |MaximumAmount - OutstandingAmount|.
*/
// OutstandingAmount may overflow and available amount might be negative.
// But available amount is always <= |MaximumAmount - OutstandingAmount|.
std::int64_t
availableMPTAmount(SLE const& sleIssuance);
@@ -341,12 +331,7 @@ availableMPTAmount(ReadView const& view, MPTID const& mptID);
* directSendNoFee transactions that bypass the payment engine.
* 2. **accountSend & Payment Engine (Overflow: Yes):** A temporary overflow
* check when `OutstandingAmount > UINT64_MAX`. This higher threshold is used
* for `accountSend` and payments processed via the payment engine, whose
* reverse pass may issue before it redeems.
*
* In both cases a single `sendAmount > MaximumAmount` is rejected. Such a send
* can never settle: redemptions within the transaction are bounded by the
* outstanding amount, so the final OutstandingAmount would exceed the cap.
* for `accountSend` and payments processed via the payment engine.
*/
bool
isMPTOverflow(
@@ -368,12 +353,6 @@ issuerFundsToSelfIssue(ReadView const& view, MPTIssue const& issue);
/**
* Facilitate tracking of MPT sold by an issuer owning MPT sell offer.
* See ApplyView::issuerSelfDebitHookMPT().
*
* `amount` may be 0. BookStep removes an offer whose fee-adjusted funded
* output is 0, but other clips (for example MaximumAmount via limitStepIn)
* can still consume a zero slice of a funded remainder. The hook must
* accept 0: first call still snapshots origBalance; a zero debit adds
* nothing to selfDebit.
*/
void
issuerSelfDebitHookMPT(ApplyView& view, MPTIssue const& issue, std::uint64_t amount);
+21 -108
View File
@@ -1,17 +1,10 @@
#pragma once
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/STObject.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxFormats.h>
#include <cstdint>
#include <optional>
namespace xrpl::proposal {
@@ -38,21 +31,30 @@ proposalOwnerCount(STObject const& proposedTx)
}
/**
* Whether the proposed transaction is independently submittable through the
* ordinary multi-sign path: not a proposal transaction itself, not a
* pseudo-transaction, not itself flagged as someone else's inner batch
* transaction, and — if it is a Batch — every one of its own inner
* transactions carries a TransactionType and is neither a proposal, a
* pseudo-transaction, nor a nested Batch. A Batch inner transaction cannot
* lack a TransactionType, be pseudo, or be a nested Batch (STTx construction
* rejects a typeless inner and an inner Batch, and preflight0 rejects the
* pseudo/tfInnerBatchTxn combination), but those guards live outside this
* feature, so they are checked again here rather than relied upon.
* Whether the proposed transaction is itself a proposal transaction, which
* would nest one proposal inside another.
*
* TODO: cover ttTRANSACTION_PROPOSAL_SIGN once that transaction exists.
* TODO: cover ttTRANSACTION_PROPOSAL_SIGN and ttTRANSACTION_PROPOSAL_CANCEL
* once those transactions exist.
*/
inline bool
isProposalTx(STObject const& proposedTx)
{
return proposedTx.getFieldU16(sfTransactionType) == ttTRANSACTION_PROPOSAL_CREATE;
}
/**
* Whether the proposed transaction is independently submittable through the
* ordinary multi-sign path: not a nested proposal, not a pseudo-transaction,
* not itself flagged as someone else's inner batch transaction, and — if it
* is a Batch — none of its own inner transactions is a nested proposal or a
* pseudo-transaction either. A Batch inner transaction cannot itself be
* pseudo (preflight0 rejects the pseudo/tfInnerBatchTxn combination
* generically), but that guard lives outside this feature, so it is checked
* again here rather than relied upon.
*/
bool
isValidProposalTxnType(STObject const& proposedTx);
isValidProposal(STObject const& proposedTx);
/**
* Whether the proposed transaction carries any signature field.
@@ -82,93 +84,4 @@ hasEmptySigningPubKey(STObject const& proposedTx)
proposedTx.getFieldVL(sfSigningPubKey).empty();
}
/**
* Whether the proposal is terminal (On-Chain Cosigner spec §4.5). A terminal proposal
* stops accepting signatures and anyone may delete it. An already signed
* payload can still execute after Expiration, because the Ticket reservation
* compares payloads only; a passed LastLedgerSequence does stop it.
*
* A proposal is terminal when either:
* - its Expiration has passed (the parent ledger closed at or after it), or
* - the proposed transaction carries a LastLedgerSequence and the current
* ledger sequence is strictly greater than it. This mirrors the ordinary
* transactor's tefMAX_LEDGER rule: at view.seq() == LastLedgerSequence the
* payload can still be submitted in the current ledger, so the proposal is
* still live.
*
* @param view The ledger the deciding transaction is being applied to.
* @param expiration The proposal's Expiration field.
* @param proposedTx The proposal's ProposedTransaction field.
*/
bool
isTerminal(
ReadView const& view,
std::optional<std::uint32_t> expiration,
STObject const& proposedTx);
/**
* Delete a TransactionProposal ledger entry.
*
* Removes the entry from its Owner's directory, releases the reserve the
* proposal holds against the Owner, and erases the entry. Shared by every
* deletion path the spec defines (On-Chain Cosigner spec §4.5): automatic cleanup when the
* proposed transaction's TicketSequence is consumed, and the
* TransactionProposalCancel / TransactionProposalSign cleanup paths once
* those transactions exist.
*
* The release goes through decreaseOwnerCountForObject, so it follows the
* sfSponsor an entry created with reserve sponsorship carries: the reserve is
* returned to whoever was holding it, the Owner or that sponsor.
*
* @param view The apply view for making changes
* @param sleProposal The TransactionProposal ledger entry to delete
* @param j Journal for logging
* @return tesSUCCESS, tecINTERNAL for an invalid entry, or tefBAD_LEDGER if
* the ledger contradicts the entry
*/
TER
deleteProposal(ApplyView& view, SLE::pointer const& sleProposal, beast::Journal j);
/**
* Whether tx carries the same payload as a proposal's stored
* ProposedTransaction (On-Chain Cosigner spec §4.2.1).
*
* The payload is the signing payload: the fields the collected signatures
* commit to. Compared is every field except those flagged kNotSigning
* (TxnSignature, Signers, BatchSigners, CounterpartySignature,
* SponsorSignature, Signature, MasterSignature) and SigningPubKey, which is
* stored empty and filled only if the target signs with its own key. So the
* completed transaction matches no matter which mix of collected or
* off-ledger signatures it carries, and any change to a non-signature field
* results in a false-return value.
*
* Signature (PaymentChannelClaim and the XChain attestation transactions)
* is deliberately not compared: it is outside the account's own TxnSignature
* even for an ordinary submission, so a proposal cannot bind it more tightly
* than the signatures it collects do, and those transactors still validate a
* substituted value exactly as they would for an ordinary submission.
* MasterSignature appears in no transaction format.
*
* @param proposedTx The proposal's ProposedTransaction field.
* @param tx The transaction to compare, typically an STTx.
*/
bool
payloadMatches(STObject const& proposedTx, STObject const& tx);
/**
* Whether tx may consume its Ticket.
*
* While a proposal keyed to the Ticket exists, the target's Ticket is
* reserved: only the proposal's own proposed transaction may spend it
* (On-Chain Cosigner spec §4.2.1), so that unrelated target-account activity cannot
* invalidate the proposal while signatures are being collected.
* TransactionProposalCancel is not allowed through: it deletes the
* reservation without consuming the ticket.
*
* @param view The ledger containing the Ticket and any reservation.
* @param tx The transaction attempting to consume that ticket.
*/
bool
canConsumeTicket(ReadView const& view, STTx const& tx);
} // namespace xrpl::proposal
+29 -352
View File
@@ -1,12 +1,10 @@
#pragma once
#include <xrpl/basics/Number.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Asset.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/Rules.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/TER.h>
@@ -14,237 +12,11 @@
#include <cstdint>
#include <expected>
#include <optional>
#include <string_view>
namespace xrpl {
class STTx;
/**
* @brief Return the Vault's current assets total.
*
* FixedPrecision Vaults return AssetsAvailable plus AssetsDeployed, with no
* rounding to the asset's 16-digit precision: the sum is exact at Number's
* active 19-digit mantissa width (the large mantissa range, enabled by
* featureSingleAssetVault or featureLendingProtocol), rounds Downward regardless of the
* caller's ambient mode beyond that, and is not rounded to match the cached
* sfAssetsTotal field. Legacy and CashBasis Vaults return the stored
* AssetsTotal.
*
* @param vault The vault SLE.
* @return The current assets total.
*/
[[nodiscard]] Number
getAssetsTotal(SLE::ConstRef vault);
/**
* @brief A change to a FixedPrecision Vault's balances.
*/
struct VaultBalanceChange
{
/**
* Signed change to AssetsAvailable. Must be the exact amount moved on the
* Vault pseudo-account in the same transaction. Absent means no cash
* moved; adjustVaultBalances then uses zero of the Vault's own asset.
*/
std::optional<STAmount> cash = std::nullopt;
/**
* Signed change to AssetsDeployed: open Loan principal, exact.
*/
Number deployed = 0;
/**
* Signed change to scheduled, unpaid interest (YieldUnrealized), exact.
*/
Number yield = 0;
/**
* Signed change to impaired principal (LossUnrealized), exact.
*/
Number loss = 0;
};
/**
* @brief Apply a balance change to a FixedPrecision Vault. The only writer of
* AssetsAvailable, AssetsDeployed, AssetsTotal, YieldUnrealized and
* LossUnrealized on these Vaults after creation.
*
* @param vault The vault SLE. Must be FixedPrecision.
* @param change The balance change to apply.
* @param j Journal for logging the fatal (tefBAD_LEDGER) case.
*
* @return tesSUCCESS; tecLIMIT_EXCEEDED if LossUnrealized would exceed
* AssetsDeployed; tefBAD_LEDGER if AssetsAvailable, AssetsDeployed,
* LossUnrealized or YieldUnrealized would become negative.
*/
[[nodiscard]] TER
adjustVaultBalances(SLE::Ref vault, VaultBalanceChange const& change, beast::Journal j);
/**
* @brief Apply a signed cash movement to a Vault of any version. FixedPrecision
* Vaults go through adjustVaultBalances; Legacy and CashBasis Vaults add the
* amount to both AssetsTotal and AssetsAvailable.
*
* @param vault The vault SLE.
* @param delta Signed change to AssetsAvailable; the exact amount moved on the
* Vault pseudo-account.
* @param j Journal passed through to adjustVaultBalances.
*
* @return tesSUCCESS, or the adjustVaultBalances error for FixedPrecision Vaults.
*/
[[nodiscard]] TER
adjustVaultCash(SLE::Ref vault, STAmount const& delta, beast::Journal j);
/**
* Return the Vault's current live exponent.
*
* Legacy and CashBasis Vaults use the exponent of AssetsTotal. FixedPrecision
* Vaults use max(base exponent, exponent of AssetsTotal): the grid is never
* finer than -Scale and coarsens once AssetsTotal outgrows 16 digits there.
*/
[[nodiscard]] int
getVaultScale(SLE::ConstRef vault);
/**
* Return the Vault's base exponent.
*
* Legacy and CashBasis Vaults use their current live exponent. FixedPrecision
* Vaults use -Scale, or 0 for integral assets.
*/
[[nodiscard]] int
getVaultBaseScale(SLE::ConstRef vault);
/**
* Round an amount at the Vault's posterior live exponent.
*/
[[nodiscard]] STAmount
roundToPosteriorVaultScale(
SLE::ConstRef vault,
STAmount const& amount,
Number::RoundingMode roundingMode);
namespace detail {
/**
* Return the Vault's posterior live exponent after applying an unrounded delta.
*/
[[nodiscard]] int
getPosteriorVaultScale(SLE::ConstRef vault, STAmount const& delta);
/**
* Shared grid-floor core of getVaultScale / getPosteriorVaultScale /
* getPosteriorBrokerCoverScale: baseScale when reference is zero, otherwise
* max(baseScale, scale(reference, asset)), rounded Downward regardless of
* the caller's ambient rounding mode.
*/
[[nodiscard]] int
liveScale(Number const& reference, Asset const& asset, int baseScale);
/**
* Shared core of getPosteriorVaultScale and getPosteriorBrokerCoverScale:
* the exponent reference + delta would have under version's live-scale rule
* (floored at baseScale for FixedPrecision, unbounded for Legacy/CashBasis).
*
* @param version The Vault's LEVersion.
* @param asset The Vault's underlying asset.
* @param baseScale The Vault's base exponent; unused outside the
* FixedPrecision case.
* @param reference The balance the delta is applied to (AssetsAvailable,
* AssetsTotal, or a LoanBroker's CoverAvailable).
* @param delta The unrounded change to reference.
*/
[[nodiscard]] int
posteriorAssetScale(
VaultVersion version,
Asset const& asset,
int baseScale,
Number const& reference,
Number const& delta);
/**
* Shared core of creditToPosteriorAvailableScale and
* creditToPosteriorBrokerCoverScale: floors reference + raw at scale and
* returns the difference from reference, so the delta applied is exactly
* what moves reference onto the floored sum. See
* creditToPosteriorAvailableScale's doc for why the sum, not raw alone,
* must be floored. raw is the exact amount; it is not rounded on its own
* before being added to reference.
*/
[[nodiscard]] STAmount
creditToPosteriorScale(
Asset const& asset,
Number const& reference,
int atScale,
Number const& raw,
Number::RoundingMode roundingMode);
} // namespace detail
/**
* Round a FixedPrecision cash inflow (LoanPay's credit, LoanManage's
* default cover credit) into AssetsAvailable, never AssetsTotal, which is
* a derived cache, by flooring the sum rather than the delta:
* credit equals floor16(AssetsAvailable + raw) minus AssetsAvailable, never
* finer than the Vault's base exponent (-Scale).
*
* Flooring only the delta at its own posterior grid is not enough: the sum
* can still need a 17th digit when AssetsAvailable is off the coarser grid
* right after crossing a power of ten. Example at Scale 6: AssetsAvailable
* equals 9999999999.999999 (16 digits already) and a credit of 0.000011
* floors to 0.00001 on its own (finer) grid, but 9999999999.999999 plus
* 0.00001 equals 10000000000.000009, which still needs 17 digits. Flooring
* the sum instead, floor16(9999999999.999999 + 0.000011) minus
* 9999999999.999999, is exact by construction, since STAmount's own
* 16-digit canonical form of the sum is what gets subtracted from.
*
* raw is taken as an exact Number: rounding it to 16 digits before adding
* it to AssetsAvailable could drop a tail that moves the floored sum.
*/
[[nodiscard]] STAmount
creditToPosteriorAvailableScale(
SLE::ConstRef vault,
Number const& raw,
Number::RoundingMode roundingMode);
/**
* Open-zone capacity ceiling: 9 * 10^(15 + baseScale).
*
* Defined only for FixedPrecision Vaults, where this is 9 * 10^(15 - P).
*/
[[nodiscard]] Number
getVaultOpenLimit(SLE::ConstRef vault);
/**
* Check whether amount is an admissible optional inflow.
*
* Legacy and CashBasis Vaults always succeed. FixedPrecision Vaults must
* remain at their base scale after applying the rounded amount, and the
* posterior capacity (AssetsTotal + YieldUnrealized + rounded amount) must
* stay within the Open zone.
*
* The amount is rounded toward zero at the posterior live exponent.
*/
[[nodiscard]] TER
checkOptionalVaultInflow(SLE::ConstRef vault, STAmount const& amount);
/**
* Open-zone capacity after adding roundedAmount: AssetsTotal + YieldUnrealized
* + roundedAmount, computed TowardsZero regardless of the caller's ambient
* rounding mode. Defined only for FixedPrecision Vaults.
*
* Shared by checkOptionalVaultInflow and LoanSet's loan-origination capacity
* check, which pair this formula with different scale checks (posterior vs.
* current), so only the capacity formula itself -- not the whole check -- is
* shared here.
*
* @param vault The vault SLE. Must be FixedPrecision.
* @param roundedAmount The amount to add, already rounded to the relevant
* posterior or base scale by the caller.
*/
[[nodiscard]] Number
vaultOpenZoneCapacity(SLE::ConstRef vault, Number const& roundedAmount);
/**
* From the perspective of a vault, return the number of shares to give
* depositor when they offer a fixed amount of assets. Note, since shares are
@@ -274,93 +46,31 @@ assetsToSharesDeposit(SLE::ConstRef vault, SLE::ConstRef issuance, STAmount cons
sharesToAssetsDeposit(SLE::ConstRef vault, SLE::ConstRef issuance, STAmount const& shares);
/**
* Adjusts a requested asset change (delta) to match the decimal scale of the
* updated total vault assets. This ensures sfAssetsTotal, sfAssetsAvailable,
* Adjusts a requested asset change (`delta`) to match the decimal scale of the
* updated total vault assets. This ensures `sfAssetsTotal`, `sfAssetsAvailable`,
* and the actual asset transfer change by the exact same representable amount.
*
* Rounding strategy:
* - Legacy/CashBasis debits (withdrawals): rounds down the magnitude of delta
* on the new scale to prevent paying out more than requested.
* - Legacy/CashBasis credits: floors the resulting total asset balance and
* returns the difference from the current total.
* - FixedPrecision credits only (VaultDeposit): rounds the delta toward zero
* at the scale getAssetsTotal (AssetsAvailable + AssetsDeployed, derived,
* not the stored AssetsTotal cache) would have after applying delta.
* FixedPrecision outflows (VaultWithdraw, VaultClawback) never call this;
* they use clampVaultOutflow instead.
* - Debits (withdrawals): Rounds down `|delta|` on the new scale to prevent
* paying out more than requested.
* - Credits (deposits): Floors the resulting total asset balance and returns the
* difference from the current total. This prevents crediting the vault with
* more assets than the user deposited.
*
* Key rules:
* - The returned magnitude never exceeds the magnitude of delta.
* - Returns tecPRECISION_LOSS if the change is smaller than 1 ULP of the target scale
* - The returned magnitude never exceeds `|delta|`.
* - Returns `tecPRECISION_LOSS` if the change is smaller than 1 ULP of the target scale
* (prevents share operations when totals cannot change).
* - For integer assets (XRP, MPT), rounding is a no-op.
*
* @param vault The vault ledger entry.
* @param delta The requested signed change to sfAssetsTotal.
* @return The rounded, positive magnitude, or tecPRECISION_LOSS if the
* @return The rounded, positive magnitude, or `tecPRECISION_LOSS` if the
* change is below representable precision.
*/
[[nodiscard]] std::expected<STAmount, TER>
clampToAssetsTotalScale(SLE::ConstRef vault, STAmount const& delta);
/**
* Outflow clamp dispatcher for VaultWithdraw and VaultClawback: rounds a
* negative delta to the scale appropriate for the Vault's version -- for
* FixedPrecision, at AssetsAvailable's own posterior scale (the balance the
* cash actually leaves); for Legacy/CashBasis, clampToAssetsTotalScale --
* so both call sites share one dispatch point. Same tecPRECISION_LOSS and
* integral-asset and magnitude-never-exceeds-delta rules as
* clampToAssetsTotalScale.
*
* @param vault The vault ledger entry.
* @param delta The requested signed outflow (negative).
* @return The rounded, positive magnitude, or tecPRECISION_LOSS if the
* change is below representable precision.
*/
[[nodiscard]] std::expected<STAmount, TER>
clampVaultOutflow(SLE::ConstRef vault, STAmount const& delta);
/**
* Returns the Vault's base exponent for asset at scale, before a Vault
* object exists to read it from: 0 for an integral asset, -scale otherwise.
* Used by VaultCreate::preclaim, which only has the proposed Scale field,
* not yet a Vault SLE; getVaultBaseScale is the post-creation equivalent.
*
* @param asset The (prospective) Vault's underlying asset.
* @param scale The (prospective) Vault's sfScale value, ignored for
* integral assets.
*/
[[nodiscard]] int
vaultBaseScale(Asset const& asset, std::uint8_t scale);
/**
* Returns true iff value is exactly representable both as an STAmount of
* asset and on the base grid at baseScale (no precision lost rounding
* TowardsZero at baseScale). Returns false, rather than throwing, for a value
* out of range for the asset. Shared representability check for
* VaultCreate::preclaim, VaultSet::preclaim and LoanBrokerSet::preclaim's
* AssetsMaximum / DebtMaximum / cover-rate field checks.
*
* @param asset The vault's underlying asset.
* @param value The value to check.
* @param baseScale The vault's base exponent (see vaultBaseScale /
* getVaultBaseScale).
*/
[[nodiscard]] bool
isOnVaultBaseGrid(Asset const& asset, Number const& value, int baseScale);
/**
* Checks that a requested AssetsMaximum is exactly representable on the
* Vault's base grid, otherwise associateAsset would silently round the cap
* the owner asked for. Used by VaultSet::preclaim on an existing Vault.
*
* @param vault The vault ledger entry.
* @param amount The requested AssetsMaximum.
* @return tesSUCCESS, or tecPRECISION_LOSS if amount is not representable.
*/
[[nodiscard]] TER
checkAssetsMaximum(SLE::ConstRef vault, Number const& amount);
/**
* Controls whether to truncate shares instead of rounding.
*/
@@ -388,24 +98,21 @@ enum class WaiveUnrealizedLoss : bool { No = false, Yes = true };
assetsTotalForWithdrawal(SLE::ConstRef vault, WaiveUnrealizedLoss waive);
/**
* Reject a cash outflow that is dust (see debitIsNonZeroDust) or whose check
* overflows Number, which is easy to hit with a large Scale.
* Returns true if debiting `amount` from `total` (the current value of a
* vault's sfAssetsTotal or sfAssetsAvailable) would canonicalize to the
* same STAmount value. This happens when `amount` is non-zero but too small
* to change the stored total at STAmount's precision. Shares would still
* move, so the ValidVault invariant would fail after apply; callers use
* this to reject the transaction upfront instead.
*
* @param vault The vault SLE.
* @param amount The amount to debit.
* @param j Journal for the debug log.
* @param name Transaction name used as the log prefix.
*
* @return tesSUCCESS; tecPRECISION_LOSS if amount is dust; tecPATH_DRY if the
* check overflows. Overflow means the transaction cannot apply, but
* ledger state is still consistent.
* @param asset The vault's underlying asset, used to canonicalize both
* sides the same way the ledger will when the field is stored.
* @param total The field's current value.
* @param amount The amount to debit. Zero always returns false; that case
* is rejected separately.
*/
[[nodiscard]] TER
checkDebitNotDust(
SLE::ConstRef vault,
Number const& amount,
beast::Journal j,
std::string_view name);
[[nodiscard]] bool
debitIsNonZeroDust(Asset const& asset, Number const& total, Number const& amount);
/**
* From the perspective of a vault, return the number of shares to demand from
@@ -451,7 +158,7 @@ sharesToAssetsWithdraw(
WaiveUnrealizedLoss waive = WaiveUnrealizedLoss::No);
/**
* Returns true iff account holds all of the vault's outstanding shares,
* Returns true iff `account` holds all of the vault's outstanding shares —
* i.e. is the sole remaining shareholder. Returns false if the account
* holds no shares or fewer than the total outstanding.
*
@@ -464,13 +171,11 @@ sharesToAssetsWithdraw(
isSoleShareholder(ReadView const& view, AccountID const& account, SLE::ConstRef issuance);
/**
* Resolves a Vault's LEVersion.
*
* LEVersion is the single point every accounting and rounding helper
* should call to decide which protocol a Vault follows. It is written
* at VaultCreate and is not updated afterwards, so a Vault created
* under an older amendment keeps that behaviour after later amendments
* activate. Absent sfLEVersion resolves to VaultVersion::Legacy.
* Resolves a Vault's LEVersion, the single point every accounting touch
* point should call to determine which recognition model (instant interest
* recognition vs. cash-basis) a Vault uses. Vaults created before featureLendingProtocolV1_1
* activated never have sfLEVersion set, which resolves here to
* VaultVersion::Legacy.
*
* @param vault The vault SLE.
*
@@ -480,34 +185,6 @@ isSoleShareholder(ReadView const& view, AccountID const& account, SLE::ConstRef
[[nodiscard]] VaultVersion
getVaultVersion(SLE::ConstRef vault);
/**
* Decodes an already-extracted sfLEVersion value with the same range check as
* getVaultVersion. Usable from contexts, such as an invariant's ledger-entry
* snapshot, that keep the field value but not the owning SLE.
*
* @param leVersion The value of sfLEVersion, or nullopt if absent.
*
* @return The decoded LEVersion, or VaultVersion::Legacy if absent.
*/
[[nodiscard]] VaultVersion
decodeVaultVersion(std::optional<std::uint8_t> leVersion);
/**
* Resolves which LEVersion a newly-created Vault should get under the
* currently active amendments. This is the only place that decides Vault
* version policy; VaultCreate calls it instead of checking amendments
* directly.
*
* @param rules The active ledger rules.
*
* @return VaultVersion::FixedPrecision once featureLendingProtocolV1_1,
* featureLendingProtocolV1_2 and fixCleanup3_4_0 are all enabled;
* VaultVersion::CashBasis
* once featureLendingProtocolV1_1 is enabled; VaultVersion::Legacy otherwise.
*/
[[nodiscard]] VaultVersion
getVaultDefaultVersion(Rules const& rules);
/**
* Resolves the VaultKind of a vault SLE. Returns VaultKind::ClosedEnded when
* sfVaultKind is present and equal to that value; anything else (including an
+1 -1
View File
@@ -20,7 +20,7 @@ enum class NodeObjectType : std::uint32_t {
Ledger = 1,
AccountNode = 3,
TransactionNode = 4,
Dummy = 512, // an invalid or missing object
Dummy = 512 // an invalid or missing object
};
/**
+1 -1
View File
@@ -28,7 +28,7 @@ enum class Status {
Unknown = 3,
BackendError = 4,
CustomCode = 100,
CustomCode = 100
};
/**
+2 -2
View File
@@ -429,7 +429,7 @@ Livecache<Allocator>::insert(Endpoint const& ep)
XRPL_ASSERT(
ep.hops <= (tuning::kMaxHops + 1),
"xrpl::peer_finder::Livecache::insert : maximum input hops");
auto const result = cache_.emplace(ep.address, ep);
auto result = cache_.emplace(ep.address, ep);
Element& e(result.first->second);
if (result.second)
{
@@ -497,7 +497,7 @@ Livecache<Allocator>::HopsT::shuffle()
std::ranges::copy(list, std::back_inserter(v));
std::shuffle(v.begin(), v.end(), defaultPrng());
list.clear();
for (auto const& e : v)
for (auto& e : v)
list.push_back(e);
}
}
+4 -4
View File
@@ -194,7 +194,7 @@ public:
"Port not specified for address:" + remoteAddress.toString());
}
auto const result(fixed_.emplace(
auto result(fixed_.emplace(
std::piecewise_construct,
std::forward_as_tuple(remoteAddress),
std::make_tuple(std::ref(clock))));
@@ -439,7 +439,7 @@ public:
// Mark fixed slot success
if (slot->fixed() && !slot->inbound())
{
auto const iter(fixed_.find(slot->remoteEndpoint()));
auto iter(fixed_.find(slot->remoteEndpoint()));
if (iter == fixed_.end())
{
logicError(
@@ -485,7 +485,7 @@ public:
// Count how many more outbound attempts to make
//
auto const needed(counts_.attemptsNeeded());
auto needed(counts_.attemptsNeeded());
if (needed == 0)
return none;
@@ -903,7 +903,7 @@ public:
// Mark fixed slot failure
if (slot->fixed() && !slot->inbound() && slot->state() != Slot::State::Active)
{
auto const iter(fixed_.find(slot->remoteEndpoint()));
auto iter(fixed_.find(slot->remoteEndpoint()));
if (iter == fixed_.end())
{
logicError(
+1 -1
View File
@@ -144,7 +144,7 @@ enum ErrorCodeI {
RpcEntryNotFound = 98,
RpcUnexpectedLedgerType = 99,
RpcLast = RpcUnexpectedLedgerType, // rpcLAST should always equal the last code.
RpcLast = RpcUnexpectedLedgerType // rpcLAST should always equal the last code.
};
/**
+2
View File
@@ -40,6 +40,8 @@ struct LedgerHeader
// If validated is false, it means "not yet validated."
// Once validated is true, it will never be set false at a later time.
// NOTE: If you are accessing this directly, you are probably doing it
// wrong. Use LedgerMaster::isValidated().
// VFALCO TODO Make this not mutable
bool mutable validated = false;
bool accepted = false;
-2
View File
@@ -26,7 +26,6 @@ class STTx;
* greater than the maximum value of uint16.
*/
// Macro-generated, complex
// NOLINTBEGIN(readability-trailing-comma) the macro supplies the trailing comma
// NOLINTNEXTLINE(cppcoreguidelines-use-enum-class)
enum GranularPermissionType : std::uint32_t {
#pragma push_macro("GRANULAR_PERMISSION")
@@ -39,7 +38,6 @@ enum GranularPermissionType : std::uint32_t {
#undef GRANULAR_PERMISSION
#pragma pop_macro("GRANULAR_PERMISSION")
};
// NOLINTEND(readability-trailing-comma)
class Permission
{
+8 -30
View File
@@ -311,46 +311,24 @@ constexpr std::uint8_t kVaultStrategyFirstComeFirstServe = 1;
* Default IOU scale factor for a Vault
*/
constexpr std::uint8_t kVaultDefaultIouScale = 6;
/**
* Maximum Scale for a Vault created before featureLendingProtocolV1_2.
* Chosen so 1 IOU can always convert to shares:
* 10^19 > maxMPTokenAmount (2^64-1) > 10^18.
* Maximum scale factor for a Vault. The number is chosen to ensure that
* 1 IOU can be always converted to shares.
* 10^19 > maxMPTokenAmount (2^64-1) > 10^18
*/
constexpr std::uint8_t kLegacyVaultMaximumIouScale = 18;
constexpr std::uint8_t kVaultMaximumIouScale = 18;
/**
* Maximum Scale for a Vault created under featureLendingProtocolV1_2.
*/
constexpr std::uint8_t kFixedPrecisionVaultMaximumIouScale = 10;
/**
* Vault ledger-entry schema versions, persisted as sfLEVersion.
*
* LEVersion records which protocol a Vault was created under so later
* amendments can change the rules for new Vaults without rewriting
* existing ones. VaultCreate writes it from the then-active lending
* amendments; later transactions do not update it. A Vault created
* under an older amendment keeps that amendment's behaviour for its
* lifetime, even after a newer lending amendment activates.
*
* Absent sfLEVersion is implicit Legacy (version 0): instant interest
* recognition and a dynamic AssetsTotal scale. CashBasis (V1.1) uses
* cash-basis recognition on the same dynamic scale. FixedPrecision
* (V1.2) keeps cash-basis recognition and adds the lifetime base grid.
* Vault ledger-entry schema versions. Assigned to newly created
* Vaults once featureLendingProtocolV1_1 is enabled. Vaults created before
* activation are left without LEVersion (implicit legacy version 0,
* instant interest recognition).
*/
enum class VaultVersion : uint8_t {
Legacy = 0,
CashBasis,
FixedPrecision,
};
// Code compares VaultVersion values with < and >= (e.g. "CashBasis or later"),
// so each later version must stay numerically larger than the one before.
static_assert(
VaultVersion::Legacy < VaultVersion::CashBasis &&
VaultVersion::CashBasis < VaultVersion::FixedPrecision);
/**
* Vault kind. Distinguishes closed-ended vaults from the default open-ended
* kind. Persisted as sfVaultKind (UINT8); absent means OpenEnded.
+2 -4
View File
@@ -284,10 +284,8 @@ public:
auto const [minV, maxV] = std::minmax(q1.value_, q2.value_);
auto const mantissa = [](std::uint64_t rate) { return rate & ~(255ull << (64 - 8)); };
auto const exponent = [](std::uint64_t rate) {
return static_cast<int>(rate >> (64 - 8)) - 100;
};
auto mantissa = [](std::uint64_t rate) { return rate & ~(255ull << (64 - 8)); };
auto exponent = [](std::uint64_t rate) { return static_cast<int>(rate >> (64 - 8)) - 100; };
auto const minVMantissa = mantissa(minV);
auto const maxVMantissa = mantissa(maxV);
-15
View File
@@ -766,21 +766,6 @@ roundToAsset(
return roundToScale(ret, scale);
}
/**
* Check whether an arbitrary precision Number can be converted to an STAmount
* of a given Asset without exceeding the asset's range.
*
* Use this before `roundToAsset` or `STAmount{asset, value}` on unchecked
* input, since those throw for out-of-range values, e.g. XRP above
* `STAmount::kMaxNativeN`.
*
* @param asset The relevant asset
* @param value The value to be checked
* @return true if the value is in range for the asset; false otherwise.
*/
[[nodiscard]] bool
isRepresentable(Asset const& asset, Number const& value);
//------------------------------------------------------------------------------
inline bool
+1 -1
View File
@@ -29,7 +29,7 @@ struct JsonOptions
DisableApiPriorV2 = 0b0000'0010,
// IMPORTANT `All` must be union of all of the above; see also operator~
All = IncludeDate | DisableApiPriorV2, // 0b0000'0011
All = IncludeDate | DisableApiPriorV2 // 0b0000'0011
};
constexpr JsonOptions(UnderlyingT v) noexcept : value(v)
+1 -1
View File
@@ -440,7 +440,7 @@ private:
// These values are carefully chosen to do the right thing if passed
// to SField::shouldInclude (bool)
OmitSigningFields = false,
WithAllFields = true,
WithAllFields = true
};
void
+1 -1
View File
@@ -36,7 +36,7 @@ enum class TxnSql : char {
Held = 'H',
Validated = 'V',
Included = 'I',
Unknown = 'U',
Unknown = 'U'
};
class STTx final : public STObject, public CountedObject<STTx>
+1 -1
View File
@@ -250,7 +250,7 @@ public:
bool
getBitString(BaseUInt<Bits, Tag>& data, int offset) const
{
auto const success = (offset + (Bits / 8)) <= data_.size();
auto success = (offset + (Bits / 8)) <= data_.size();
if (success)
memcpy(data.begin(), &data_.front() + offset, (Bits / 8));
return success;
+1 -1
View File
@@ -32,7 +32,7 @@ enum class SignatureRole {
/**
* The sponsor's signature, in sfSponsorSignature.
*/
Sponsor,
Sponsor
};
/**
+2 -4
View File
@@ -51,7 +51,7 @@ enum TELcodes : TERUnderlyingType {
telWRONG_NETWORK,
telREQUIRES_NETWORK_ID,
telNETWORK_ID_MAKES_TX_NON_CANONICAL,
telENV_RPC_FAILED,
telENV_RPC_FAILED
};
//------------------------------------------------------------------------------
@@ -231,8 +231,6 @@ enum TERcodes : TERUnderlyingType {
terNO_DELEGATE_PERMISSION, // Delegate does not have permission
terLOCKED, // MPT is locked
terNO_PERMISSION, // No permission but retry
terTICKET_RESERVED, // Ticket is reserved and cannot be consumed
// until the reservation is released
};
//------------------------------------------------------------------------------
@@ -249,7 +247,7 @@ enum TEScodes : TERUnderlyingType {
// Implications:
// - Applied
// - Forwarded
tesSUCCESS = 0,
tesSUCCESS = 0
};
//------------------------------------------------------------------------------
+1 -3
View File
@@ -319,9 +319,7 @@ inline FlagMap const&
getUniversalFlags()
{
static FlagMap const flags = {
{"tfFullyCanonicalSig", tfFullyCanonicalSig},
{"tfInnerBatchTxn", tfInnerBatchTxn},
};
{"tfFullyCanonicalSig", tfFullyCanonicalSig}, {"tfInnerBatchTxn", tfInnerBatchTxn}};
return flags;
}
+1 -1
View File
@@ -427,7 +427,7 @@ mulDivU(Source1 value, Dest mul, Source2 div)
static_cast<std::uint64_t>(value.value()),
static_cast<std::uint64_t>(mul.value()));
auto const quotient = product / div.value();
auto quotient = product / div.value();
if (quotient > kMax)
return std::nullopt;
+1 -1
View File
@@ -236,7 +236,7 @@ enum class AttestationMatch {
// all of the fields match, except the dst field
MatchExceptDst,
// all of the fields match
Match,
Match
};
struct XChainClaimAttestation
+20 -13
View File
@@ -1,6 +1,5 @@
#pragma once
#include <xrpl/basics/MathUtilities.h>
#include <xrpl/basics/Number.h>
#include <xrpl/basics/contract.h>
#include <xrpl/beast/utility/Zero.h>
@@ -70,13 +69,7 @@ public:
constexpr XRPAmount
operator*(value_type const& rhs) const
{
if (auto const result = checkedMul(drops_, rhs))
return XRPAmount{*result};
// Not reached in constant evaluation: an overflowing constant
// expression fails to compile instead.
XRPAmount product{*this};
product *= rhs;
return product;
return XRPAmount{drops_ * rhs};
}
friend constexpr XRPAmount
@@ -89,23 +82,37 @@ public:
XRPAmount&
operator+=(XRPAmount const& other)
{
return *this += other.drops();
drops_ += other.drops();
return *this;
}
XRPAmount&
operator-=(XRPAmount const& other)
{
return *this -= other.drops();
drops_ -= other.drops();
return *this;
}
XRPAmount&
operator+=(value_type const& rhs);
operator+=(value_type const& rhs)
{
drops_ += rhs;
return *this;
}
XRPAmount&
operator-=(value_type const& rhs);
operator-=(value_type const& rhs)
{
drops_ -= rhs;
return *this;
}
XRPAmount&
operator*=(value_type const& rhs);
operator*=(value_type const& rhs)
{
drops_ *= rhs;
return *this;
}
XRPAmount
operator-() const
+3 -3
View File
@@ -119,13 +119,13 @@ inplaceBigintDivRem(std::span<uint64_t> numerator, std::uint64_t divisor)
// LCOV_EXCL_STOP
}
auto const toU128 = [](std::uint64_t high, std::uint64_t low) -> unsigned __int128 {
auto toU128 = [](std::uint64_t high, std::uint64_t low) -> unsigned __int128 {
unsigned __int128 const high128 = high;
unsigned __int128 const low128 = low;
return ((high128 << 64) | low128);
};
auto const divRe64 = [](unsigned __int128 num,
std::uint64_t denom) -> std::tuple<std::uint64_t, std::uint64_t> {
auto divRe64 = [](unsigned __int128 num,
std::uint64_t denom) -> std::tuple<std::uint64_t, std::uint64_t> {
unsigned __int128 const denom128 = denom;
unsigned __int128 const d = num / denom128;
unsigned __int128 const r = num - (denom128 * d);
+1 -2
View File
@@ -17,7 +17,6 @@
XRPL_FEATURE(Cosign, Supported::No, VoteBehavior::DefaultNo)
XRPL_FEATURE(SmartEscrow, Supported::No, VoteBehavior::DefaultNo)
// Requires LendingProtocolV1_1. New vaults take FixedPrecision plus cash-basis.
XRPL_FEATURE(LendingProtocolV1_2, Supported::No, VoteBehavior::DefaultNo)
XRPL_FIX (Cleanup3_5_0, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(ConfidentialMPTKeyRotation, Supported::No, VoteBehavior::DefaultNo)
@@ -61,6 +60,7 @@ XRPL_FIX (InnerObjTemplate2, Supported::Yes, VoteBehavior::DefaultNo
XRPL_FIX (EnforceNFTokenTrustline, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FIX (ReducedOffersV2, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(NFTokenMintOffer, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FIX (AMMv1_1, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FIX (PreviousTxnID, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FIX (XChainRewardRounding, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FIX (EmptyDID, Supported::Yes, VoteBehavior::DefaultNo)
@@ -106,7 +106,6 @@ XRPL_RETIRE_FIX(1623)
XRPL_RETIRE_FIX(1781)
XRPL_RETIRE_FIX(AmendmentMajorityCalc)
XRPL_RETIRE_FIX(AMMOverflowOffer)
XRPL_RETIRE_FIX(AMMv1_1)
XRPL_RETIRE_FIX(CheckThreading)
XRPL_RETIRE_FIX(DisallowIncomingV1)
XRPL_RETIRE_FIX(InnerObjTemplate)
@@ -514,8 +514,6 @@ LEDGER_ENTRY(ltVAULT, 0x0084, Vault, vault, ({
{sfAssetsAvailable, SoeDefault},
{sfAssetsMaximum, SoeDefault},
{sfLossUnrealized, SoeDefault},
{sfYieldUnrealized, SoeDefault},
{sfAssetsDeployed, SoeDefault},
{sfShareMPTID, SoeRequired},
{sfWithdrawalPolicy, SoeRequired},
{sfScale, SoeDefault},
@@ -240,8 +240,6 @@ TYPED_SFIELD(sfPrincipalRequested, NUMBER, 14)
TYPED_SFIELD(sfTotalValueOutstanding, NUMBER, 15, SField::kSmdNeedsAsset | SField::kSmdDefault)
TYPED_SFIELD(sfPeriodicPayment, NUMBER, 16)
TYPED_SFIELD(sfManagementFeeOutstanding, NUMBER, 17, SField::kSmdNeedsAsset | SField::kSmdDefault)
TYPED_SFIELD(sfYieldUnrealized, NUMBER, 18, SField::kSmdNeedsAsset | SField::kSmdDefault)
TYPED_SFIELD(sfAssetsDeployed, NUMBER, 19, SField::kSmdNeedsAsset | SField::kSmdDefault)
// 32-bit signed (common)
TYPED_SFIELD(sfLoanScale, INT32, 1)
@@ -1175,20 +1175,6 @@ TRANSACTION(ttTRANSACTION_PROPOSAL_CREATE, 95, TransactionProposalCreate,
{sfExpiration, SoeRequired},
}))
// ttTRANSACTION_PROPOSAL_SIGN arrives in a later PR and takes the next unassigned type.
/** This transaction deletes a TransactionProposal, releasing its owner's
reserve. While the proposal is live only its Owner or its target account
may cancel; once it is terminal anyone may (On-Chain Cosigner spec §7). */
#if TRANSACTION_INCLUDE
# include <xrpl/tx/transactors/proposal/TransactionProposalCancel.h>
#endif
TRANSACTION(ttTRANSACTION_PROPOSAL_CANCEL, 94, TransactionProposalCancel,
({.amendment = featureCosign}),
({
{sfProposalID, SoeRequired},
}))
/** This system-generated transaction type is used to update the status of the various amendments.
For details, see: https://xrpl.org/amendments.html
+1 -1
View File
@@ -24,7 +24,7 @@ enum class TokenType : std::uint8_t {
AccountPublic = 35,
AccountSecret = 34,
FamilyGenerator = 41, // unused
FamilySeed = 33,
FamilySeed = 33
};
template <class T>
@@ -242,54 +242,6 @@ public:
return this->sle_->isFieldPresent(sfLossUnrealized);
}
/**
* @brief Get sfYieldUnrealized (SoeDefault)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_NUMBER::type::value_type>
getYieldUnrealized() const
{
if (hasYieldUnrealized())
return this->sle_->at(sfYieldUnrealized);
return std::nullopt;
}
/**
* @brief Check if sfYieldUnrealized is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasYieldUnrealized() const
{
return this->sle_->isFieldPresent(sfYieldUnrealized);
}
/**
* @brief Get sfAssetsDeployed (SoeDefault)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_NUMBER::type::value_type>
getAssetsDeployed() const
{
if (hasAssetsDeployed())
return this->sle_->at(sfAssetsDeployed);
return std::nullopt;
}
/**
* @brief Check if sfAssetsDeployed is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasAssetsDeployed() const
{
return this->sle_->isFieldPresent(sfAssetsDeployed);
}
/**
* @brief Get sfShareMPTID (SoeRequired)
* @return The field value.
@@ -619,28 +571,6 @@ public:
return *this;
}
/**
* @brief Set sfYieldUnrealized (SoeDefault)
* @return Reference to this builder for method chaining.
*/
VaultBuilder&
setYieldUnrealized(std::decay_t<typename SF_NUMBER::type::value_type> const& value)
{
object_[sfYieldUnrealized] = value;
return *this;
}
/**
* @brief Set sfAssetsDeployed (SoeDefault)
* @return Reference to this builder for method chaining.
*/
VaultBuilder&
setAssetsDeployed(std::decay_t<typename SF_NUMBER::type::value_type> const& value)
{
object_[sfAssetsDeployed] = value;
return *this;
}
/**
* @brief Set sfShareMPTID (SoeRequired)
* @return Reference to this builder for method chaining.
@@ -1,131 +0,0 @@
// This file is auto-generated. Do not edit.
#pragma once
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/STParsedJSON.h>
#include <xrpl/protocol/jss.h>
#include <xrpl/protocol_autogen/TransactionBase.h>
#include <xrpl/protocol_autogen/TransactionBuilderBase.h>
#include <xrpl/json/json_value.h>
#include <stdexcept>
#include <optional>
namespace xrpl::transactions {
class TransactionProposalCancelBuilder;
/**
* @brief Transaction: TransactionProposalCancel
*
* Type: ttTRANSACTION_PROPOSAL_CANCEL (94)
* Delegable: Delegation::NotDelegable
* Amendment: featureCosign
* Privileges: Privilege::NoPriv
*
* Immutable wrapper around STTx providing type-safe field access.
* Use TransactionProposalCancelBuilder to construct new transactions.
*/
class TransactionProposalCancel : public TransactionBase
{
public:
static constexpr xrpl::TxType txType = ttTRANSACTION_PROPOSAL_CANCEL;
/**
* @brief Construct a TransactionProposalCancel transaction wrapper from an existing STTx object.
* @throws std::runtime_error if the transaction type doesn't match.
*/
explicit TransactionProposalCancel(std::shared_ptr<STTx const> tx)
: TransactionBase(std::move(tx))
{
// Verify transaction type
if (tx_->getTxnType() != txType)
{
throw std::runtime_error("Invalid transaction type for TransactionProposalCancel");
}
}
// Transaction-specific field getters
/**
* @brief Get sfProposalID (SoeRequired)
* @return The field value.
*/
[[nodiscard]]
SF_UINT256::type::value_type
getProposalID() const
{
return this->tx_->at(sfProposalID);
}
};
/**
* @brief Builder for TransactionProposalCancel transactions.
*
* Provides a fluent interface for constructing transactions with method chaining.
* Uses STObject internally for flexible transaction construction.
* Inherits common field setters from TransactionBuilderBase.
*/
class TransactionProposalCancelBuilder : public TransactionBuilderBase<TransactionProposalCancelBuilder>
{
public:
/**
* @brief Construct a new TransactionProposalCancelBuilder with required fields.
* @param account The account initiating the transaction.
* @param proposalID The sfProposalID field value.
* @param sequence Optional sequence number for the transaction.
* @param fee Optional fee for the transaction.
*/
TransactionProposalCancelBuilder(SF_ACCOUNT::type::value_type account,
std::decay_t<typename SF_UINT256::type::value_type> const& proposalID, std::optional<SF_UINT32::type::value_type> sequence = std::nullopt,
std::optional<SF_AMOUNT::type::value_type> fee = std::nullopt
)
: TransactionBuilderBase<TransactionProposalCancelBuilder>(ttTRANSACTION_PROPOSAL_CANCEL, account, sequence, fee)
{
setProposalID(proposalID);
}
/**
* @brief Construct a TransactionProposalCancelBuilder from an existing STTx object.
* @param tx The existing transaction to copy from.
* @throws std::runtime_error if the transaction type doesn't match.
*/
TransactionProposalCancelBuilder(std::shared_ptr<STTx const> tx)
{
if (tx->getTxnType() != ttTRANSACTION_PROPOSAL_CANCEL)
{
throw std::runtime_error("Invalid transaction type for TransactionProposalCancelBuilder");
}
object_ = *tx;
}
/**
* @brief Transaction-specific field setters
*/
/**
* @brief Set sfProposalID (SoeRequired)
* @return Reference to this builder for method chaining.
*/
TransactionProposalCancelBuilder&
setProposalID(std::decay_t<typename SF_UINT256::type::value_type> const& value)
{
object_[sfProposalID] = value;
return *this;
}
/**
* @brief Build and return the TransactionProposalCancel wrapper.
* @param publicKey The public key for signing.
* @param secretKey The secret key for signing.
* @return The constructed transaction wrapper.
*/
TransactionProposalCancel
build(PublicKey const& publicKey, SecretKey const& secretKey)
{
sign(publicKey, secretKey);
return TransactionProposalCancel{std::make_shared<STTx>(std::move(object_))};
}
};
} // namespace xrpl::transactions
+28 -37
View File
@@ -46,10 +46,9 @@ inline constexpr std::uint32_t kSqliteTuningCutoff = 10'000'000;
inline constexpr auto kLgrDbName{"ledger.db"};
inline constexpr std::array<char const*, 5> kLgrDbInit{
{
"BEGIN TRANSACTION;",
{"BEGIN TRANSACTION;",
"CREATE TABLE IF NOT EXISTS Ledgers ( \
"CREATE TABLE IF NOT EXISTS Ledgers ( \
LedgerHash CHARACTER(64) PRIMARY KEY, \
LedgerSeq BIGINT UNSIGNED, \
PrevHash CHARACTER(64), \
@@ -61,14 +60,12 @@ inline constexpr std::array<char const*, 5> kLgrDbInit{
AccountSetHash CHARACTER(64), \
TransSetHash CHARACTER(64) \
);",
"CREATE INDEX IF NOT EXISTS SeqLedger ON Ledgers(LedgerSeq);",
"CREATE INDEX IF NOT EXISTS SeqLedger ON Ledgers(LedgerSeq);",
// Old table and indexes no longer needed
"DROP TABLE IF EXISTS Validations;",
// Old table and indexes no longer needed
"DROP TABLE IF EXISTS Validations;",
"END TRANSACTION;",
},
};
"END TRANSACTION;"}};
////////////////////////////////////////////////////////////////////////////////
@@ -76,10 +73,9 @@ inline constexpr std::array<char const*, 5> kLgrDbInit{
inline constexpr auto kTxDbName{"transaction.db"};
inline constexpr std::array<char const*, 8> kTxDbInit{
{
"BEGIN TRANSACTION;",
{"BEGIN TRANSACTION;",
"CREATE TABLE IF NOT EXISTS Transactions ( \
"CREATE TABLE IF NOT EXISTS Transactions ( \
TransID CHARACTER(64) PRIMARY KEY, \
TransType CHARACTER(24), \
FromAcct CHARACTER(35), \
@@ -89,62 +85,57 @@ inline constexpr std::array<char const*, 8> kTxDbInit{
RawTxn BLOB, \
TxnMeta BLOB \
);",
"CREATE INDEX IF NOT EXISTS TxLgrIndex ON \
"CREATE INDEX IF NOT EXISTS TxLgrIndex ON \
Transactions(LedgerSeq);",
"CREATE TABLE IF NOT EXISTS AccountTransactions ( \
"CREATE TABLE IF NOT EXISTS AccountTransactions ( \
TransID CHARACTER(64), \
Account CHARACTER(64), \
LedgerSeq BIGINT UNSIGNED, \
TxnSeq INTEGER \
);",
"CREATE INDEX IF NOT EXISTS AcctTxIDIndex ON \
"CREATE INDEX IF NOT EXISTS AcctTxIDIndex ON \
AccountTransactions(TransID);",
"CREATE INDEX IF NOT EXISTS AcctTxIndex ON \
"CREATE INDEX IF NOT EXISTS AcctTxIndex ON \
AccountTransactions(Account, LedgerSeq, TxnSeq, TransID);",
"CREATE INDEX IF NOT EXISTS AcctLgrIndex ON \
"CREATE INDEX IF NOT EXISTS AcctLgrIndex ON \
AccountTransactions(LedgerSeq, Account, TransID);",
"END TRANSACTION;",
},
};
"END TRANSACTION;"}};
////////////////////////////////////////////////////////////////////////////////
inline constexpr auto kWalletDbName{"wallet.db"};
inline constexpr std::array<char const*, 6> kWalletDbInit{
{
"BEGIN TRANSACTION;",
{"BEGIN TRANSACTION;",
// A node's identity must be persisted, including
// for clustering purposes. This table holds one
// entry: the server's unique identity, but the
// value can be overriden by specifying a node
// identity in the config file using a [node_seed]
// entry.
"CREATE TABLE IF NOT EXISTS NodeIdentity ( \
// A node's identity must be persisted, including
// for clustering purposes. This table holds one
// entry: the server's unique identity, but the
// value can be overriden by specifying a node
// identity in the config file using a [node_seed]
// entry.
"CREATE TABLE IF NOT EXISTS NodeIdentity ( \
PublicKey CHARACTER(53), \
PrivateKey CHARACTER(52) \
);",
// Peer reservations
"CREATE TABLE IF NOT EXISTS PeerReservations ( \
// Peer reservations
"CREATE TABLE IF NOT EXISTS PeerReservations ( \
PublicKey CHARACTER(53) UNIQUE NOT NULL, \
Description CHARACTER(64) NOT NULL \
);",
// Validator Manifests
"CREATE TABLE IF NOT EXISTS ValidatorManifests ( \
// Validator Manifests
"CREATE TABLE IF NOT EXISTS ValidatorManifests ( \
RawData BLOB NOT NULL \
);",
"CREATE TABLE IF NOT EXISTS PublisherManifests ( \
"CREATE TABLE IF NOT EXISTS PublisherManifests ( \
RawData BLOB NOT NULL \
);",
"END TRANSACTION;",
},
};
"END TRANSACTION;"}};
} // namespace xrpl
+2 -2
View File
@@ -50,8 +50,8 @@ struct LedgerRange
enum class DelegateType {
Actor, ///< Another account signed and submitted transactions on behalf of this account (this
///< account is the owner/delegator).
Authorizer, ///< This account signed and submitted transactions on behalf of another account
///< (this account is the signer/delegatee).
Authorizer ///< This account signed and submitted transactions on behalf of another account
///< (this account is the signer/delegatee).
};
struct DelegateFilter
Loaded 100 of 690 files, more files were not shown because too many files have changed in this diff. Show more