Compare commits

..

43 Commits

Author SHA1 Message Date
Bart
e2e537b3bb fix: Change Tuning::bookOffers minimum limit to 1 (#6812)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-04-10 14:38:46 +00:00
Ed Hennis
a873250019 chore: Make pre-commit line ending conversions work on Windows (#6832) (#6833) 2026-04-10 10:12:52 +00:00
Gregory Tsipenyuk
56c9d1d497 fix: Add description for terLOCKED error (#6811) 2026-04-08 20:56:19 +00:00
yinyiqian1
d52dd29d20 fix: Address AI reviewer comments for Permission Delegation (#6675) 2026-04-08 20:22:19 +00:00
Mayukha Vadari
7793b5f10b refactor: Combine AMMHelpers and AMMUtils (#6733) 2026-04-08 17:38:33 +00:00
Gregory Tsipenyuk
dfcad69155 feat: Add MPT support to DEX (#5285) 2026-04-08 16:17:37 +00:00
Pratik Mankawde
6d1a5be8d2 fix: Handle WSClient write failure when server closes WebSocket (#6671)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 19:15:40 +00:00
Ayaz Salikhov
b0fe2ec58a ci: Change conditions for uploading artifacts in public/private/org repos (#6734) 2026-04-07 14:32:13 +00:00
Bart
c00ed673a8 refactor: Rename non-functional uses of ripple(d) to xrpl(d) (#6676)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-04-07 13:00:17 +00:00
Mayukha Vadari
f239256d87 refactor: Move more helper files into libxrpl/ledger/helpers (#6731)
Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com>
2026-04-06 22:36:32 +00:00
Mayukha Vadari
00761dbb67 fix: Minor RPC fixes (#6730) 2026-04-06 22:15:16 +00:00
Zhiyuan Wang
077e03ff33 fix: Prevent deletion of MPTokens with active escrow (#6635)
Co-authored-by: Bart <bthomee@users.noreply.github.com>
2026-04-06 17:51:46 +00:00
Vito Tumas
7d524a03b8 fix: Clamp VaultClawback to assetsAvailable for zero-amount clawback (#6646) 2026-04-06 15:13:03 +00:00
Vito Tumas
c0ee813666 fix: Add assorted Lending Protocol fixes (#6678)
Co-authored-by: Shawn Xie <35279399+shawnxie999@users.noreply.github.com>
2026-04-03 17:41:45 +00:00
Mayukha Vadari
8e05416211 fix: Change variable signedness and correctly handle std::optional (#6657) 2026-04-03 15:16:50 +00:00
Mayukha Vadari
81555d5456 refactor: Reorganize RPC handler files (#6628) 2026-04-02 23:46:17 +00:00
Ayaz Salikhov
6b55c4cdc8 chore: Update XRPLF/actions (#6713) 2026-04-02 21:34:20 +00:00
yinyiqian1
3414a1776b docs: Add explanatory comment to checkFee (#6631) 2026-04-02 20:48:35 +00:00
yinyiqian1
6d9ed125f3 fix: Decouple reserve from fee in delegate payment (#6568) 2026-04-02 20:48:00 +00:00
Vito Tumas
02fa55df8d fix: Check trustline limits for share-denominated vault withdrawals (#6645) 2026-04-01 19:31:45 +00:00
Valentin Balaschenko
6e2452207d fix: Remove fatal assertion on Linux thread name truncation (#6690) 2026-04-01 16:56:45 +00:00
Alex Kremer
29e49abd3c chore: Enable clang-tidy coreguidelines checks (#6698)
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2026-04-01 15:46:14 +00:00
Ayaz Salikhov
ae21f53e4d ci: Allow uploading artifacts for XRPLF org (#6702) 2026-04-01 13:37:35 +00:00
Vito Tumas
bee1056faa fix: Enforce aggregate MaximumAmount in multi-send MPT (#6644)
Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com>
2026-04-01 13:35:13 +00:00
Ayaz Salikhov
b6aa4a8fde chore: Use nudb recipe from the upstream (#6701) 2026-04-01 10:33:02 +00:00
Mayukha Vadari
a9afd2c116 fix: Fix previous ledger size typo in RCLConsensus (#6696) 2026-03-31 19:56:30 +00:00
Alex Kremer
2502befb42 chore: Enable clang-tidy misc checks (#6655) 2026-03-31 17:29:45 +00:00
Ayaz Salikhov
c3fae847f3 ci: Use pull_request_target to check for signed commits (#6697) 2026-03-31 17:14:41 +00:00
Bart
7f53351920 chore: Remove unnecessary clang-format off/on directives (#6682)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-03-31 15:38:04 +00:00
Pratik Mankawde
bb95a7d6cd fix: Fix Workers::stop() race between m_allPaused and m_runningTaskCount (#6574)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-31 15:06:04 +00:00
Ayaz Salikhov
5c8dfe5456 ci: Only publish docs in public repos (#6687) 2026-03-30 17:15:40 +00:00
Alex Kremer
ab8c168e3b chore: Enable remaining clang-tidy performance checks (#6648)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-30 17:08:47 +00:00
Jingchen
3a477e4d01 refactor: Address PR comments after the modularisation PRs (#6389)
Signed-off-by: JCW <a1q123456@users.noreply.github.com>
Co-authored-by: Bart <bthomee@users.noreply.github.com>
2026-03-30 15:22:38 +00:00
Alex Kremer
96bfc32fe2 chore: Fix clang-tidy header filter (#6686) 2026-03-30 14:59:53 +00:00
dependabot[bot]
de671863e2 ci: [DEPENDABOT] bump actions/deploy-pages from 4.0.5 to 5.0.0 (#6684)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-30 14:09:57 +00:00
dependabot[bot]
e0cabb9f8c ci: [DEPENDABOT] bump codecov/codecov-action from 5.5.3 to 6.0.0 (#6685)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-30 13:57:32 +00:00
Pratik Mankawde
3d9c545f59 fix: Guard Coro::resume() against completed coroutines (#6608)
Signed-off-by: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-27 18:52:18 +00:00
Vito Tumas
9b944ee8c2 refactor: Split LoanInvariant into LoanBrokerInvariant and LoanInvariant (#6674) 2026-03-27 18:35:42 +00:00
Ayaz Salikhov
509677abfd ci: Don't publish docs on release branches (#6673) 2026-03-26 14:11:37 +00:00
Jingchen
addc1e8e25 refactor: Make function naming in ServiceRegistry consistent (#6390)
Signed-off-by: JCW <a1q123456@users.noreply.github.com>
Co-authored-by: Ed Hennis <ed@ripple.com>
2026-03-26 14:11:16 +00:00
Valentin Balaschenko
faf69da4b0 chore: Shorten job names to stay within Linux 15-char thread limit (#6669) 2026-03-26 14:10:51 +00:00
Vito Tumas
76e3b4fb0f fix: Improve loan invariant message (#6668) 2026-03-26 12:40:26 +00:00
Ayaz Salikhov
e8bdbf975a ci: Upload artifacts only in public repositories (#6670) 2026-03-26 12:37:37 +00:00
453 changed files with 38151 additions and 6232 deletions

View File

@@ -1,7 +1,7 @@
--- ---
name: Feature Request name: Feature Request
about: Suggest a new feature for the rippled project about: Suggest a new feature for the xrpld project
title: "[Title with short description] (Version: [rippled version])" title: "[Title with short description] (Version: [xrpld version])"
labels: Feature Request labels: Feature Request
assignees: "" assignees: ""
--- ---

View File

@@ -1,14 +1,14 @@
# Levelization # Levelization
Levelization is the term used to describe efforts to prevent rippled from Levelization is the term used to describe efforts to prevent xrpld from
having or creating cyclic dependencies. having or creating cyclic dependencies.
rippled code is organized into directories under `src/xrpld`, `src/libxrpl` (and xrpld code is organized into directories under `src/xrpld`, `src/libxrpl` (and
`src/test`) representing modules. The modules are intended to be `src/test`) representing modules. The modules are intended to be
organized into "tiers" or "levels" such that a module from one level can organized into "tiers" or "levels" such that a module from one level can
only include code from lower levels. Additionally, a module only include code from lower levels. Additionally, a module
in one level should never include code in an `impl` or `detail` folder of any level in one level should never include code in an `impl` or `detail` folder of any level
other than it's own. other than its own.
The codebase is split into two main areas: The codebase is split into two main areas:
@@ -22,7 +22,7 @@ levelization violations they find (by moving files or individual
classes). At the very least, don't make things worse. classes). At the very least, don't make things worse.
The table below summarizes the _desired_ division of modules, based on the current The table below summarizes the _desired_ division of modules, based on the current
state of the rippled code. The levels are numbered from state of the xrpld code. The levels are numbered from
the bottom up with the lower level, lower numbered, more independent the bottom up with the lower level, lower numbered, more independent
modules listed first, and the higher level, higher numbered modules with modules listed first, and the higher level, higher numbered modules with
more dependencies listed later. more dependencies listed later.
@@ -72,10 +72,10 @@ that `test` code should _never_ be included in `xrpl` or `xrpld` code.)
The [levelization](generate.py) script takes no parameters, The [levelization](generate.py) script takes no parameters,
reads no environment variables, and can be run from any directory, reads no environment variables, and can be run from any directory,
as long as it is in the expected location in the rippled repo. as long as it is in the expected location in the xrpld repo.
It can be run at any time from within a checked out repo, and will It can be run at any time from within a checked out repo, and will
do an analysis of all the `#include`s in do an analysis of all the `#include`s in
the rippled source. The only caveat is that it runs much slower the xrpld source. The only caveat is that it runs much slower
under Windows than in Linux. It hasn't yet been tested under MacOS. under Windows than in Linux. It hasn't yet been tested under MacOS.
It generates many files of [results](results): It generates many files of [results](results):

View File

@@ -34,6 +34,8 @@ run from the repository root.
6. `.github/scripts/rename/config.sh`: This script will rename the config from 6. `.github/scripts/rename/config.sh`: This script will rename the config from
`rippled.cfg` to `xrpld.cfg`, and updating the code accordingly. The old `rippled.cfg` to `xrpld.cfg`, and updating the code accordingly. The old
filename will still be accepted. filename will still be accepted.
7. `.github/scripts/rename/docs.sh`: This script will rename any lingering
references of `ripple(d)` to `xrpl(d)` in code, comments, and documentation.
You can run all these scripts from the repository root as follows: You can run all these scripts from the repository root as follows:
@@ -44,4 +46,5 @@ You can run all these scripts from the repository root as follows:
./.github/scripts/rename/binary.sh . ./.github/scripts/rename/binary.sh .
./.github/scripts/rename/namespace.sh . ./.github/scripts/rename/namespace.sh .
./.github/scripts/rename/config.sh . ./.github/scripts/rename/config.sh .
./.github/scripts/rename/docs.sh .
``` ```

View File

@@ -29,7 +29,7 @@ if [ ! -d "${DIRECTORY}" ]; then
echo "Error: Directory '${DIRECTORY}' does not exist." echo "Error: Directory '${DIRECTORY}' does not exist."
exit 1 exit 1
fi fi
pushd ${DIRECTORY} pushd "${DIRECTORY}"
# Remove the binary name override added by the cmake.sh script. # Remove the binary name override added by the cmake.sh script.
${SED_COMMAND} -z -i -E 's@\s+# For the time being.+"rippled"\)@@' cmake/XrplCore.cmake ${SED_COMMAND} -z -i -E 's@\s+# For the time being.+"rippled"\)@@' cmake/XrplCore.cmake
@@ -49,6 +49,7 @@ ${SED_COMMAND} -i -E 's@ripple/xrpld@XRPLF/rippled@g' BUILD.md
${SED_COMMAND} -i -E 's@XRPLF/xrpld@XRPLF/rippled@g' BUILD.md ${SED_COMMAND} -i -E 's@XRPLF/xrpld@XRPLF/rippled@g' BUILD.md
${SED_COMMAND} -i -E 's@xrpld \(`xrpld`\)@xrpld@g' BUILD.md ${SED_COMMAND} -i -E 's@xrpld \(`xrpld`\)@xrpld@g' BUILD.md
${SED_COMMAND} -i -E 's@XRPLF/xrpld@XRPLF/rippled@g' CONTRIBUTING.md ${SED_COMMAND} -i -E 's@XRPLF/xrpld@XRPLF/rippled@g' CONTRIBUTING.md
${SED_COMMAND} -i -E 's@XRPLF/xrpld@XRPLF/rippled@g' docs/build/install.md
popd popd
echo "Processing complete." echo "Processing complete."

View File

@@ -38,7 +38,7 @@ if [ ! -d "${DIRECTORY}" ]; then
echo "Error: Directory '${DIRECTORY}' does not exist." echo "Error: Directory '${DIRECTORY}' does not exist."
exit 1 exit 1
fi fi
pushd ${DIRECTORY} pushd "${DIRECTORY}"
# Rename the files. # Rename the files.
find cmake -type f -name 'Rippled*.cmake' -exec bash -c 'mv "${1}" "${1/Rippled/Xrpl}"' - {} \; find cmake -type f -name 'Rippled*.cmake' -exec bash -c 'mv "${1}" "${1/Rippled/Xrpl}"' - {} \;

View File

@@ -28,7 +28,7 @@ if [ ! -d "${DIRECTORY}" ]; then
echo "Error: Directory '${DIRECTORY}' does not exist." echo "Error: Directory '${DIRECTORY}' does not exist."
exit 1 exit 1
fi fi
pushd ${DIRECTORY} pushd "${DIRECTORY}"
# Add the xrpld.cfg to the .gitignore. # Add the xrpld.cfg to the .gitignore.
if ! grep -q 'xrpld.cfg' .gitignore; then if ! grep -q 'xrpld.cfg' .gitignore; then
@@ -52,16 +52,15 @@ for DIRECTORY in "${DIRECTORIES[@]}"; do
find "${DIRECTORY}" -type f \( -name "*.h" -o -name "*.hpp" -o -name "*.ipp" -o -name "*.cpp" -o -name "*.cmake" -o -name "*.txt" -o -name "*.cfg" -o -name "*.md" \) | while read -r FILE; do find "${DIRECTORY}" -type f \( -name "*.h" -o -name "*.hpp" -o -name "*.ipp" -o -name "*.cpp" -o -name "*.cmake" -o -name "*.txt" -o -name "*.cfg" -o -name "*.md" \) | while read -r FILE; do
echo "Processing file: ${FILE}" echo "Processing file: ${FILE}"
${SED_COMMAND} -i -E 's/rippled(-example)?[ .]cfg/xrpld\1.cfg/g' "${FILE}" ${SED_COMMAND} -i -E 's/rippled(-example)?[ .]cfg/xrpld\1.cfg/g' "${FILE}"
${SED_COMMAND} -i 's/rippleConfig/xrpldConfig/g' "${FILE}"
done done
done done
${SED_COMMAND} -i 's/rippled/xrpld/g' cfg/xrpld-example.cfg ${SED_COMMAND} -i 's/rippled/xrpld/g' cfg/xrpld-example.cfg
${SED_COMMAND} -i 's/rippled/xrpld/g' src/test/core/Config_test.cpp ${SED_COMMAND} -i 's/rippled/xrpld/g' src/test/core/Config_test.cpp
${SED_COMMAND} -i 's/ripplevalidators/xrplvalidators/g' src/test/core/Config_test.cpp # cspell: disable-line ${SED_COMMAND} -i 's/ripplevalidators/xrplvalidators/g' src/test/core/Config_test.cpp # cspell: disable-line
${SED_COMMAND} -i 's/rippleConfig/xrpldConfig/g' src/test/core/Config_test.cpp
${SED_COMMAND} -i 's@ripple/@xrpld/@g' src/test/core/Config_test.cpp ${SED_COMMAND} -i 's@ripple/@xrpld/@g' src/test/core/Config_test.cpp
${SED_COMMAND} -i 's/Rippled/File/g' src/test/core/Config_test.cpp ${SED_COMMAND} -i 's/Rippled/File/g' src/test/core/Config_test.cpp
# Restore the old config file name in the code that maintains support for now. # Restore the old config file name in the code that maintains support for now.
${SED_COMMAND} -i 's/configLegacyName = "xrpld.cfg"/configLegacyName = "rippled.cfg"/g' src/xrpld/core/detail/Config.cpp ${SED_COMMAND} -i 's/configLegacyName = "xrpld.cfg"/configLegacyName = "rippled.cfg"/g' src/xrpld/core/detail/Config.cpp

View File

@@ -31,7 +31,7 @@ if [ ! -d "${DIRECTORY}" ]; then
echo "Error: Directory '${DIRECTORY}' does not exist." echo "Error: Directory '${DIRECTORY}' does not exist."
exit 1 exit 1
fi fi
pushd ${DIRECTORY} pushd "${DIRECTORY}"
# Prevent sed and echo from removing newlines and tabs in string literals by # Prevent sed and echo from removing newlines and tabs in string literals by
# temporarily replacing them with placeholders. This only affects one file. # temporarily replacing them with placeholders. This only affects one file.
@@ -76,11 +76,11 @@ fi
if ! grep -q 'Dev Null' src/test/rpc/ValidatorInfo_test.cpp; then if ! grep -q 'Dev Null' src/test/rpc/ValidatorInfo_test.cpp; then
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/rpc/ValidatorInfo_test.cpp)" > src/test/rpc/ValidatorInfo_test.cpp echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/rpc/ValidatorInfo_test.cpp)" > src/test/rpc/ValidatorInfo_test.cpp
fi fi
if ! grep -q 'Dev Null' src/xrpld/rpc/handlers/DoManifest.cpp; then if ! grep -q 'Dev Null' src/xrpld/rpc/handlers/server_info/Manifest.cpp; then
echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/DoManifest.cpp)" > src/xrpld/rpc/handlers/DoManifest.cpp echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/server_info/Manifest.cpp)" > src/xrpld/rpc/handlers/server_info/Manifest.cpp
fi fi
if ! grep -q 'Dev Null' src/xrpld/rpc/handlers/ValidatorInfo.cpp; then if ! grep -q 'Dev Null' src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp; then
echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/ValidatorInfo.cpp)" > src/xrpld/rpc/handlers/ValidatorInfo.cpp echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp)" > src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp
fi fi
if ! grep -q 'Bougalis' include/xrpl/basics/SlabAllocator.h; then if ! grep -q 'Bougalis' include/xrpl/basics/SlabAllocator.h; then
echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/SlabAllocator.h)" > include/xrpl/basics/SlabAllocator.h # cspell: ignore Nikolaos Bougalis nikb echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/SlabAllocator.h)" > include/xrpl/basics/SlabAllocator.h # cspell: ignore Nikolaos Bougalis nikb

96
.github/scripts/rename/docs.sh vendored Executable file
View File

@@ -0,0 +1,96 @@
#!/bin/bash
# Exit the script as soon as an error occurs.
set -e
# On MacOS, ensure that GNU sed is installed and available as `gsed`.
SED_COMMAND=sed
if [[ "${OSTYPE}" == 'darwin'* ]]; then
if ! command -v gsed &> /dev/null; then
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
exit 1
fi
SED_COMMAND=gsed
fi
# This script renames all remaining references to `ripple` and `rippled` to
# `xrpl` and `xrpld`, respectively, in code, comments, and documentation.
# Usage: .github/scripts/rename/docs.sh <repository directory>
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <repository directory>"
exit 1
fi
DIRECTORY=$1
echo "Processing directory: ${DIRECTORY}"
if [ ! -d "${DIRECTORY}" ]; then
echo "Error: Directory '${DIRECTORY}' does not exist."
exit 1
fi
pushd "${DIRECTORY}"
find . -type f \( -name "*.h" -o -name "*.hpp" -o -name "*.ipp" -o -name "*.cpp" -o -name "*.txt" -o -name "*.cfg" -o -name "*.md" -o -name "*.proto" \) -not -path "./.github/scripts/*" | while read -r FILE; do
echo "Processing file: ${FILE}"
${SED_COMMAND} -i 's/rippleLockEscrowMPT/lockEscrowMPT/g' "${FILE}"
${SED_COMMAND} -i 's/rippleUnlockEscrowMPT/unlockEscrowMPT/g' "${FILE}"
${SED_COMMAND} -i 's/rippleCredit/directSendNoFee/g' "${FILE}"
${SED_COMMAND} -i 's/rippleSend/directSendNoLimit/g' "${FILE}"
${SED_COMMAND} -i -E 's@([^/+-])rippled@\1xrpld@g' "${FILE}"
${SED_COMMAND} -i -E 's@([^/+-])Rippled@\1Xrpld@g' "${FILE}"
${SED_COMMAND} -i -E 's/^rippled/xrpld/g' "${FILE}"
${SED_COMMAND} -i -E 's/^Rippled/Xrpld/g' "${FILE}"
# cspell: disable
${SED_COMMAND} -i -E 's/(r|R)ipple (a|A)ddress/XRPL address/g' "${FILE}"
${SED_COMMAND} -i -E 's/(r|R)ipple (a|A)ccount/XRPL account/g' "${FILE}"
${SED_COMMAND} -i -E 's/(r|R)ipple (a|A)lgorithm/XRPL algorithm/g' "${FILE}"
${SED_COMMAND} -i -E 's/(r|R)ipple (c|C)lient/XRPL client/g' "${FILE}"
${SED_COMMAND} -i -E 's/(r|R)ipple (c|C)luster/XRPL cluster/g' "${FILE}"
${SED_COMMAND} -i -E 's/(r|R)ipple (c|C)onsensus/XRPL consensus/g' "${FILE}"
${SED_COMMAND} -i -E 's/(r|R)ipple (d|D)efault/XRPL default/g' "${FILE}"
${SED_COMMAND} -i -E 's/(r|R)ipple (e|E)poch/XRPL epoch/g' "${FILE}"
${SED_COMMAND} -i -E 's/(r|R)ipple (f|F)eature/XRPL feature/g' "${FILE}"
${SED_COMMAND} -i -E 's/(r|R)ipple (n|N)etwork/XRPL network/g' "${FILE}"
${SED_COMMAND} -i -E 's/(r|R)ipple (p|P)ayment/XRPL payment/g' "${FILE}"
${SED_COMMAND} -i -E 's/(r|R)ipple (p|P)rotocol/XRPL protocol/g' "${FILE}"
${SED_COMMAND} -i -E 's/(r|R)ipple (r|R)epository/XRPL repository/g' "${FILE}"
${SED_COMMAND} -i -E 's/(r|R)ipple RPC/XRPL RPC/g' "${FILE}"
${SED_COMMAND} -i -E 's/(r|R)ipple (s|S)erialization/XRPL serialization/g' "${FILE}"
${SED_COMMAND} -i -E 's/(r|R)ipple (s|S)erver/XRPL server/g' "${FILE}"
${SED_COMMAND} -i -E 's/(r|R)ipple (s|S)pecific/XRPL specific/g' "${FILE}"
${SED_COMMAND} -i -E 's/(r|R)ipple Source/XRPL Source/g' "${FILE}"
${SED_COMMAND} -i -E 's/(r|R)ipple (t|T)imestamp/XRPL timestamp/g' "${FILE}"
${SED_COMMAND} -i -E 's/(r|R)ipple uses the consensus/XRPL uses the consensus/g' "${FILE}"
${SED_COMMAND} -i -E 's/(r|R)ipple (v|V)alidator/XRPL validator/g' "${FILE}"
# cspell: enable
${SED_COMMAND} -i 's/RippleLib/XrplLib/g' "${FILE}"
${SED_COMMAND} -i 's/ripple-lib/XrplLib/g' "${FILE}"
${SED_COMMAND} -i 's@opt/ripple/@opt/xrpld/@g' "${FILE}"
${SED_COMMAND} -i 's@src/ripple/@src/xrpld/@g' "${FILE}"
${SED_COMMAND} -i 's@ripple/app/@xrpld/app/@g' "${FILE}"
${SED_COMMAND} -i 's@github.com/ripple/rippled@github.com/XRPLF/rippled@g' "${FILE}"
${SED_COMMAND} -i 's/\ba xrpl/an xrpl/g' "${FILE}"
${SED_COMMAND} -i 's/\ba XRPL/an XRPL/g' "${FILE}"
done
${SED_COMMAND} -i 's/ripple_libs/xrpl_libs/' BUILD.md
${SED_COMMAND} -i 's/Ripple integrators/XRPL developers/' README.md
${SED_COMMAND} -i 's/sanitizer-configuration-for-rippled/sanitizer-configuration-for-xrpld/' docs/build/sanitizers.md
${SED_COMMAND} -i 's/rippled/xrpld/g' .github/scripts/levelization/README.md
${SED_COMMAND} -i 's/rippled/xrpld/g' .github/scripts/strategy-matrix/generate.py
${SED_COMMAND} -i 's@/rippled@/xrpld@g' docs/build/install.md
${SED_COMMAND} -i 's@github.com/XRPLF/xrpld@github.com/XRPLF/rippled@g' docs/build/install.md
${SED_COMMAND} -i 's/rippled/xrpld/g' docs/Doxyfile
${SED_COMMAND} -i 's/ripple_basics/basics/' include/xrpl/basics/CountedObject.h
${SED_COMMAND} -i 's/<ripple/<xrpl/' include/xrpl/protocol/AccountID.h
${SED_COMMAND} -i 's/Ripple:/the XRPL:/g' include/xrpl/protocol/SecretKey.h
${SED_COMMAND} -i 's/Ripple:/the XRPL:/g' include/xrpl/protocol/Seed.h
${SED_COMMAND} -i 's/ripple/xrpl/g' src/test/README.md
${SED_COMMAND} -i 's/www.ripple.com/www.xrpl.org/g' src/test/protocol/Seed_test.cpp
# Restore specific changes.
${SED_COMMAND} -i 's@b5efcc/src/xrpld@b5efcc/src/ripple@' include/xrpl/protocol/README.md
${SED_COMMAND} -i 's/dbPrefix_ = "xrpldb"/dbPrefix_ = "rippledb"/' src/xrpld/app/misc/SHAMapStoreImp.h # cspell: disable-line
${SED_COMMAND} -i 's/configLegacyName = "xrpld.cfg"/configLegacyName = "rippled.cfg"/' src/xrpld/core/detail/Config.cpp
popd
echo "Renaming complete."

View File

@@ -31,16 +31,17 @@ if [ ! -d "${DIRECTORY}" ]; then
echo "Error: Directory '${DIRECTORY}' does not exist." echo "Error: Directory '${DIRECTORY}' does not exist."
exit 1 exit 1
fi fi
pushd ${DIRECTORY} pushd "${DIRECTORY}"
DIRECTORIES=("include" "src" "tests") DIRECTORIES=("include" "src" "tests")
for DIRECTORY in "${DIRECTORIES[@]}"; do for DIRECTORY in "${DIRECTORIES[@]}"; do
echo "Processing directory: ${DIRECTORY}" echo "Processing directory: ${DIRECTORY}"
find "${DIRECTORY}" -type f \( -name "*.h" -o -name "*.hpp" -o -name "*.ipp" -o -name "*.cpp" \) | while read -r FILE; do find "${DIRECTORY}" -type f \( -name "*.h" -o -name "*.hpp" -o -name "*.ipp" -o -name "*.cpp" -o -name "*.macro" \) | while read -r FILE; do
echo "Processing file: ${FILE}" echo "Processing file: ${FILE}"
${SED_COMMAND} -i 's/namespace ripple/namespace xrpl/g' "${FILE}" ${SED_COMMAND} -i 's/namespace ripple/namespace xrpl/g' "${FILE}"
${SED_COMMAND} -i 's/ripple::/xrpl::/g' "${FILE}" ${SED_COMMAND} -i 's/ripple::/xrpl::/g' "${FILE}"
${SED_COMMAND} -i 's/"ripple:/"xrpl::/g' "${FILE}"
${SED_COMMAND} -i -E 's/(BEAST_DEFINE_TESTSUITE.+)ripple(.+)/\1xrpl\2/g' "${FILE}" ${SED_COMMAND} -i -E 's/(BEAST_DEFINE_TESTSUITE.+)ripple(.+)/\1xrpl\2/g' "${FILE}"
done done
done done

View File

@@ -235,7 +235,7 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
# so that they are easier to identify in the GitHub Actions UI, as long # so that they are easier to identify in the GitHub Actions UI, as long
# names get truncated. # names get truncated.
# Add Address and Thread (both coupled with UB) sanitizers for specific bookworm distros. # Add Address and Thread (both coupled with UB) sanitizers for specific bookworm distros.
# GCC-Asan rippled-embedded tests are failing because of https://github.com/google/sanitizers/issues/856 # GCC-Asan xrpld-embedded tests are failing because of https://github.com/google/sanitizers/issues/856
if ( if (
os["distro_version"] == "bookworm" os["distro_version"] == "bookworm"
and f"{os['compiler_name']}-{os['compiler_version']}" == "clang-20" and f"{os['compiler_name']}-{os['compiler_version']}" == "clang-20"

View File

@@ -10,4 +10,4 @@ permissions:
jobs: jobs:
check_commits: check_commits:
uses: XRPLF/actions/.github/workflows/check-pr-commits.yml@481048b78b94ac3343d1292b4ef125a813879f2b uses: XRPLF/actions/.github/workflows/check-pr-commits.yml@e2c7f400d1e85ae65dad552fd425169fbacca4a3

View File

@@ -11,4 +11,4 @@ on:
jobs: jobs:
check_title: check_title:
if: ${{ github.event.pull_request.draft != true }} if: ${{ github.event.pull_request.draft != true }}
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@e2c7f400d1e85ae65dad552fd425169fbacca4a3 uses: XRPLF/actions/.github/workflows/check-pr-title.yml@a5d8dd35be543365e90a11358447130c8763871d

View File

@@ -14,7 +14,7 @@ on:
jobs: jobs:
# Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks. # Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks.
run-hooks: run-hooks:
uses: XRPLF/actions/.github/workflows/pre-commit.yml@e7896f15cc60d0da1a272c77ee5c4026b424f9c7 uses: XRPLF/actions/.github/workflows/pre-commit.yml@9307df762265e15c745ddcdb38a581c989f7f349
with: with:
runs_on: ubuntu-latest runs_on: ubuntu-latest
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-41ec7c1" }' container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-41ec7c1" }'

View File

@@ -47,7 +47,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/prepare-runner@2bbc2dc1abeec7bfaa886804ab86871ac201764e uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
with: with:
enable_ccache: false enable_ccache: false
@@ -81,13 +81,13 @@ jobs:
cmake --build . --target docs --parallel ${BUILD_NPROC} cmake --build . --target docs --parallel ${BUILD_NPROC}
- name: Create documentation artifact - name: Create documentation artifact
if: ${{ (github.repository_owner == 'XRPLF' || github.event.repository.visibility == 'public') && github.event_name == 'push' }} if: ${{ github.event.repository.visibility == 'public' && github.event_name == 'push' }}
uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0 uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
with: with:
path: ${{ env.BUILD_DIR }}/docs/html path: ${{ env.BUILD_DIR }}/docs/html
deploy: deploy:
if: ${{ (github.repository_owner == 'XRPLF' || github.event.repository.visibility == 'public') && github.event_name == 'push' }} if: ${{ github.repository == 'XRPLF/rippled' && github.event_name == 'push' }}
needs: build needs: build
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:

View File

@@ -107,7 +107,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/prepare-runner@2bbc2dc1abeec7bfaa886804ab86871ac201764e uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
with: with:
enable_ccache: ${{ inputs.ccache_enabled }} enable_ccache: ${{ inputs.ccache_enabled }}
@@ -199,7 +199,7 @@ jobs:
fi fi
- name: Upload the binary (Linux) - name: Upload the binary (Linux)
if: ${{ (github.repository_owner == 'XRPLF' || github.event.repository.visibility == 'public') && runner.os == 'Linux' }} if: ${{ github.event.repository.visibility == 'public' && runner.os == 'Linux' }}
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with: with:
name: xrpld-${{ inputs.config_name }} name: xrpld-${{ inputs.config_name }}

View File

@@ -33,6 +33,8 @@ jobs:
run: .github/scripts/rename/config.sh . run: .github/scripts/rename/config.sh .
- name: Check include guards - name: Check include guards
run: .github/scripts/rename/include.sh . run: .github/scripts/rename/include.sh .
- name: Check documentation
run: .github/scripts/rename/docs.sh .
- name: Check for differences - name: Check for differences
env: env:
MESSAGE: | MESSAGE: |

View File

@@ -35,7 +35,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/prepare-runner@2bbc2dc1abeec7bfaa886804ab86871ac201764e uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
with: with:
enable_ccache: false enable_ccache: false
@@ -83,7 +83,7 @@ jobs:
run-clang-tidy -j ${{ steps.nproc.outputs.nproc }} -p "${BUILD_DIR}" -quiet -allow-no-checks ${TARGETS} 2>&1 | tee clang-tidy-output.txt run-clang-tidy -j ${{ steps.nproc.outputs.nproc }} -p "${BUILD_DIR}" -quiet -allow-no-checks ${TARGETS} 2>&1 | tee clang-tidy-output.txt
- name: Upload clang-tidy output - name: Upload clang-tidy output
if: ${{ (github.repository_owner == 'XRPLF' || github.event.repository.visibility == 'public') && steps.run_clang_tidy.outcome != 'success' }} if: ${{ github.event.repository.visibility == 'public' && steps.run_clang_tidy.outcome != 'success' }}
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with: with:
name: clang-tidy-results name: clang-tidy-results

View File

@@ -70,7 +70,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/prepare-runner@2bbc2dc1abeec7bfaa886804ab86871ac201764e uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
with: with:
enable_ccache: false enable_ccache: false

View File

@@ -17,7 +17,6 @@ repos:
args: [--maxkb=400, --enforce-all] args: [--maxkb=400, --enforce-all]
- id: trailing-whitespace - id: trailing-whitespace
- id: end-of-file-fixer - id: end-of-file-fixer
- id: mixed-line-ending
- id: check-merge-conflict - id: check-merge-conflict
args: [--assume-in-merge] args: [--assume-in-merge]
@@ -38,6 +37,7 @@ repos:
rev: c2bc67fe8f8f549cc489e00ba8b45aa18ee713b1 # frozen: v3.8.1 rev: c2bc67fe8f8f549cc489e00ba8b45aa18ee713b1 # frozen: v3.8.1
hooks: hooks:
- id: prettier - id: prettier
args: [--end-of-line=auto]
- repo: https://github.com/psf/black-pre-commit-mirror - repo: https://github.com/psf/black-pre-commit-mirror
rev: ea488cebbfd88a5f50b8bd95d5c829d0bb76feb8 # frozen: 26.1.0 rev: ea488cebbfd88a5f50b8bd95d5c829d0bb76feb8 # frozen: 26.1.0

View File

@@ -4,23 +4,23 @@ This changelog is intended to list all updates to the [public API methods](https
For info about how [API versioning](https://xrpl.org/request-formatting.html#api-versioning) works, including examples, please view the [XLS-22d spec](https://github.com/XRPLF/XRPL-Standards/discussions/54). For details about the implementation of API versioning, view the [implementation PR](https://github.com/XRPLF/rippled/pull/3155). API versioning ensures existing integrations and users continue to receive existing behavior, while those that request a higher API version will experience new behavior. For info about how [API versioning](https://xrpl.org/request-formatting.html#api-versioning) works, including examples, please view the [XLS-22d spec](https://github.com/XRPLF/XRPL-Standards/discussions/54). For details about the implementation of API versioning, view the [implementation PR](https://github.com/XRPLF/rippled/pull/3155). API versioning ensures existing integrations and users continue to receive existing behavior, while those that request a higher API version will experience new behavior.
The API version controls the API behavior you see. This includes what properties you see in responses, what parameters you're permitted to send in requests, and so on. You specify the API version in each of your requests. When a breaking change is introduced to the `rippled` API, a new version is released. To avoid breaking your code, you should set (or increase) your version when you're ready to upgrade. The API version controls the API behavior you see. This includes what properties you see in responses, what parameters you're permitted to send in requests, and so on. You specify the API version in each of your requests. When a breaking change is introduced to the `xrpld` API, a new version is released. To avoid breaking your code, you should set (or increase) your version when you're ready to upgrade.
The [commandline](https://xrpl.org/docs/references/http-websocket-apis/api-conventions/request-formatting/#commandline-format) always uses the latest API version. The command line is intended for ad-hoc usage by humans, not programs or automated scripts. The command line is not meant for use in production code. The [commandline](https://xrpl.org/docs/references/http-websocket-apis/api-conventions/request-formatting/#commandline-format) always uses the latest API version. The command line is intended for ad-hoc usage by humans, not programs or automated scripts. The command line is not meant for use in production code.
For a log of breaking changes, see the **API Version [number]** headings. In general, breaking changes are associated with a particular API Version number. For non-breaking changes, scroll to the **XRP Ledger version [x.y.z]** headings. Non-breaking changes are associated with a particular XRP Ledger (`rippled`) release. For a log of breaking changes, see the **API Version [number]** headings. In general, breaking changes are associated with a particular API Version number. For non-breaking changes, scroll to the **XRP Ledger version [x.y.z]** headings. Non-breaking changes are associated with a particular XRP Ledger (`xrpld`) release.
## API Version 3 (Beta) ## API Version 3 (Beta)
API version 3 is currently a beta API. It requires enabling `[beta_rpc_api]` in the rippled configuration to use. See [API-VERSION-3.md](API-VERSION-3.md) for the full list of changes in API version 3. API version 3 is currently a beta API. It requires enabling `[beta_rpc_api]` in the xrpld configuration to use. See [API-VERSION-3.md](API-VERSION-3.md) for the full list of changes in API version 3.
## API Version 2 ## API Version 2
API version 2 is available in `rippled` version 2.0.0 and later. See [API-VERSION-2.md](API-VERSION-2.md) for the full list of changes in API version 2. API version 2 is available in `xrpld` version 2.0.0 and later. See [API-VERSION-2.md](API-VERSION-2.md) for the full list of changes in API version 2.
## API Version 1 ## API Version 1
This version is supported by all `rippled` versions. For WebSocket and HTTP JSON-RPC requests, it is currently the default API version used when no `api_version` is specified. This version is supported by all `xrpld` versions. For WebSocket and HTTP JSON-RPC requests, it is currently the default API version used when no `api_version` is specified.
## Unreleased ## Unreleased
@@ -38,6 +38,8 @@ This section contains changes targeting a future version.
### Bugfixes ### Bugfixes
- Peer Crawler: The `port` field in `overlay.active[]` now consistently returns an integer instead of a string for outbound peers. [#6318](https://github.com/XRPLF/rippled/pull/6318) - Peer Crawler: The `port` field in `overlay.active[]` now consistently returns an integer instead of a string for outbound peers. [#6318](https://github.com/XRPLF/rippled/pull/6318)
- `ping`: The `ip` field is no longer returned as an empty string for proxied connections without a forwarded-for header. It is now omitted, consistent with the behavior for identified connections. [#6730](https://github.com/XRPLF/rippled/pull/6730)
- gRPC `GetLedgerDiff`: Fixed error message that incorrectly said "base ledger not validated" when the desired ledger was not validated. [#6730](https://github.com/XRPLF/rippled/pull/6730)
## XRP Ledger server version 3.1.0 ## XRP Ledger server version 3.1.0

View File

@@ -1,6 +1,6 @@
# API Version 2 # API Version 2
API version 2 is available in `rippled` version 2.0.0 and later. To use this API, clients specify `"api_version" : 2` in each request. API version 2 is available in `xrpld` version 2.0.0 and later. To use this API, clients specify `"api_version" : 2` in each request.
For info about how [API versioning](https://xrpl.org/request-formatting.html#api-versioning) works, including examples, please view the [XLS-22d spec](https://github.com/XRPLF/XRPL-Standards/discussions/54). For details about the implementation of API versioning, view the [implementation PR](https://github.com/XRPLF/rippled/pull/3155). API versioning ensures existing integrations and users continue to receive existing behavior, while those that request a higher API version will experience new behavior. For info about how [API versioning](https://xrpl.org/request-formatting.html#api-versioning) works, including examples, please view the [XLS-22d spec](https://github.com/XRPLF/XRPL-Standards/discussions/54). For details about the implementation of API versioning, view the [implementation PR](https://github.com/XRPLF/rippled/pull/3155). API versioning ensures existing integrations and users continue to receive existing behavior, while those that request a higher API version will experience new behavior.

View File

@@ -1,6 +1,6 @@
# API Version 3 # API Version 3
API version 3 is currently a **beta API**. It requires enabling `[beta_rpc_api]` in the rippled configuration to use. To use this API, clients specify `"api_version" : 3` in each request. API version 3 is currently a **beta API**. It requires enabling `[beta_rpc_api]` in the xrpld configuration to use. To use this API, clients specify `"api_version" : 3` in each request.
For info about how [API versioning](https://xrpl.org/request-formatting.html#api-versioning) works, including examples, please view the [XLS-22d spec](https://github.com/XRPLF/XRPL-Standards/discussions/54). For details about the implementation of API versioning, view the [implementation PR](https://github.com/XRPLF/rippled/pull/3155). API versioning ensures existing integrations and users continue to receive existing behavior, while those that request a higher API version will experience new behavior. For info about how [API versioning](https://xrpl.org/request-formatting.html#api-versioning) works, including examples, please view the [XLS-22d spec](https://github.com/XRPLF/XRPL-Standards/discussions/54). For details about the implementation of API versioning, view the [implementation PR](https://github.com/XRPLF/rippled/pull/3155). API versioning ensures existing integrations and users continue to receive existing behavior, while those that request a higher API version will experience new behavior.

View File

@@ -603,8 +603,8 @@ If you want to experiment with a new package, follow these steps:
`default_options` property (with syntax `'$package:$option': $value`). `default_options` property (with syntax `'$package:$option': $value`).
3. Modify [`CMakeLists.txt`](./CMakeLists.txt): 3. Modify [`CMakeLists.txt`](./CMakeLists.txt):
- Add a call to `find_package($package REQUIRED)`. - Add a call to `find_package($package REQUIRED)`.
- Link a library from the package to the target `ripple_libs` - Link a library from the package to the target `xrpl_libs`
(search for the existing call to `target_link_libraries(ripple_libs INTERFACE ...)`). (search for the existing call to `target_link_libraries(xrpl_libs INTERFACE ...)`).
4. Start coding! Don't forget to include whatever headers you need from the package. 4. Start coding! Don't forget to include whatever headers you need from the package.
[1]: https://github.com/conan-io/conan-center-index/issues/13168 [1]: https://github.com/conan-io/conan-center-index/issues/13168

View File

@@ -533,7 +533,7 @@ All releases, including release candidates and betas, are handled
differently from typical PRs. Most importantly, never use differently from typical PRs. Most importantly, never use
the Github UI to merge a release. the Github UI to merge a release.
Rippled uses a linear workflow model that can be summarized as: Xrpld uses a linear workflow model that can be summarized as:
1. In between releases, developers work against the `develop` branch. 1. In between releases, developers work against the `develop` branch.
2. Periodically, a maintainer will build and tag a beta version from 2. Periodically, a maintainer will build and tag a beta version from

View File

@@ -8,11 +8,11 @@ The [XRP Ledger](https://xrpl.org/) is a decentralized cryptographic ledger powe
[XRP](https://xrpl.org/xrp.html) is a public, counterparty-free crypto-asset native to the XRP Ledger, and is designed as a gas token for network services and to bridge different currencies. XRP is traded on the open-market and is available for anyone to access. The XRP Ledger was created in 2012 with a finite supply of 100 billion units of XRP. [XRP](https://xrpl.org/xrp.html) is a public, counterparty-free crypto-asset native to the XRP Ledger, and is designed as a gas token for network services and to bridge different currencies. XRP is traded on the open-market and is available for anyone to access. The XRP Ledger was created in 2012 with a finite supply of 100 billion units of XRP.
## rippled ## xrpld
The server software that powers the XRP Ledger is called `rippled` and is available in this repository under the permissive [ISC open-source license](LICENSE.md). The `rippled` server software is written primarily in C++ and runs on a variety of platforms. The `rippled` server software can run in several modes depending on its [configuration](https://xrpl.org/rippled-server-modes.html). The server software that powers the XRP Ledger is called `xrpld` and is available in this repository under the permissive [ISC open-source license](LICENSE.md). The `xrpld` server software is written primarily in C++ and runs on a variety of platforms. The `xrpld` server software can run in several modes depending on its [configuration](https://xrpl.org/rippled-server-modes.html).
If you are interested in running an **API Server** (including a **Full History Server**), take a look at [Clio](https://github.com/XRPLF/clio). (rippled Reporting Mode has been replaced by Clio.) If you are interested in running an **API Server** (including a **Full History Server**), take a look at [Clio](https://github.com/XRPLF/clio). (xrpld Reporting Mode has been replaced by Clio.)
### Build from Source ### Build from Source
@@ -41,19 +41,19 @@ If you are interested in running an **API Server** (including a **Full History S
Here are some good places to start learning the source code: Here are some good places to start learning the source code:
- Read the markdown files in the source tree: `src/ripple/**/*.md`. - Read the markdown files in the source tree: `src/xrpld/**/*.md`.
- Read [the levelization document](.github/scripts/levelization) to get an idea of the internal dependency graph. - Read [the levelization document](.github/scripts/levelization) to get an idea of the internal dependency graph.
- In the big picture, the `main` function constructs an `ApplicationImp` object, which implements the `Application` virtual interface. Almost every component in the application takes an `Application&` parameter in its constructor, typically named `app` and stored as a member variable `app_`. This allows most components to depend on any other component. - In the big picture, the `main` function constructs an `ApplicationImp` object, which implements the `Application` virtual interface. Almost every component in the application takes an `Application&` parameter in its constructor, typically named `app` and stored as a member variable `app_`. This allows most components to depend on any other component.
### Repository Contents ### Repository Contents
| Folder | Contents | | Folder | Contents |
| :--------- | :----------------------------------------------- | | :--------- | :--------------------------------------------- |
| `./bin` | Scripts and data files for Ripple integrators. | | `./bin` | Scripts and data files for XRPL developers. |
| `./Builds` | Platform-specific guides for building `rippled`. | | `./Builds` | Platform-specific guides for building `xrpld`. |
| `./docs` | Source documentation files and doxygen config. | | `./docs` | Source documentation files and doxygen config. |
| `./cfg` | Example configuration files. | | `./cfg` | Example configuration files. |
| `./src` | Source code. | | `./src` | Source code. |
Some of the directories under `src` are external repositories included using Some of the directories under `src` are external repositories included using
git-subtree. See those directories' README files for more details. git-subtree. See those directories' README files for more details.

View File

@@ -6,7 +6,7 @@ For more details on operating an XRP Ledger server securely, please visit https:
## Supported Versions ## Supported Versions
Software constantly evolves. In order to focus resources, we only generally only accept vulnerability reports that affect recent and current versions of the software. We always accept reports for issues present in the **master**, **release** or **develop** branches, and with proposed, [open pull requests](https://github.com/ripple/rippled/pulls). Software constantly evolves. In order to focus resources, we generally only accept vulnerability reports that affect recent and current versions of the software. We always accept reports for issues present in the **master**, **release** or **develop** branches, and with proposed, [open pull requests](https://github.com/XRPLF/rippled/pulls).
## Identifying and Reporting Vulnerabilities ## Identifying and Reporting Vulnerabilities
@@ -59,11 +59,11 @@ While we commit to responding with 24 hours of your initial report with our tria
## Bug Bounty Program ## Bug Bounty Program
[Ripple](https://ripple.com) is generously sponsoring a bug bounty program for vulnerabilities in [`rippled`](https://github.com/XRPLF/rippled) (and other related projects, like [`xrpl.js`](https://github.com/XRPLF/xrpl.js), [`xrpl-py`](https://github.com/XRPLF/xrpl-py), [`xrpl4j`](https://github.com/XRPLF/xrpl4j)). [Ripple](https://ripple.com) is generously sponsoring a bug bounty program for vulnerabilities in [`xrpld`](https://github.com/XRPLF/rippled) (and other related projects, like [`xrpl.js`](https://github.com/XRPLF/xrpl.js), [`xrpl-py`](https://github.com/XRPLF/xrpl-py), [`xrpl4j`](https://github.com/XRPLF/xrpl4j)).
This program allows us to recognize and reward individuals or groups that identify and report bugs. In summary, in order to qualify for a bounty, the bug must be: This program allows us to recognize and reward individuals or groups that identify and report bugs. In summary, in order to qualify for a bounty, the bug must be:
1. **In scope**. Only bugs in software under the scope of the program qualify. Currently, that means `rippled`, `xrpl.js`, `xrpl-py`, `xrpl4j`. 1. **In scope**. Only bugs in software under the scope of the program qualify. Currently, that means `xrpld`, `xrpl.js`, `xrpl-py`, `xrpl4j`.
2. **Relevant**. A security issue, posing a danger to user funds, privacy, or the operation of the XRP Ledger. 2. **Relevant**. A security issue, posing a danger to user funds, privacy, or the operation of the XRP Ledger.
3. **Original and previously unknown**. Bugs that are already known and discussed in public do not qualify. Previously reported bugs, even if publicly unknown, are not eligible. 3. **Original and previously unknown**. Bugs that are already known and discussed in public do not qualify. Previously reported bugs, even if publicly unknown, are not eligible.
4. **Specific**. We welcome general security advice or recommendations, but we cannot pay bounties for that. 4. **Specific**. We welcome general security advice or recommendations, but we cannot pay bounties for that.

View File

@@ -28,7 +28,7 @@
# https://vl.ripple.com # https://vl.ripple.com
# https://unl.xrplf.org # https://unl.xrplf.org
# http://127.0.0.1:8000 # http://127.0.0.1:8000
# file:///etc/opt/ripple/vl.txt # file:///etc/opt/xrpld/vl.txt
# #
# [validator_list_keys] # [validator_list_keys]
# #
@@ -43,11 +43,11 @@
# ED307A760EE34F2D0CAA103377B1969117C38B8AA0AA1E2A24DAC1F32FC97087ED # ED307A760EE34F2D0CAA103377B1969117C38B8AA0AA1E2A24DAC1F32FC97087ED
# #
# The default validator list publishers that the rippled instance # The default validator list publishers that the xrpld instance
# trusts. # trusts.
# #
# WARNING: Changing these values can cause your rippled instance to see a # WARNING: Changing these values can cause your xrpld instance to see a
# validated ledger that contradicts other rippled instances' # validated ledger that contradicts other xrpld instances'
# validated ledgers (aka a ledger fork) if your validator list(s) # validated ledgers (aka a ledger fork) if your validator list(s)
# do not sufficiently overlap with the list(s) used by others. # do not sufficiently overlap with the list(s) used by others.
# See: https://arxiv.org/pdf/1802.07242.pdf # See: https://arxiv.org/pdf/1802.07242.pdf

View File

@@ -9,7 +9,7 @@
# #
# 2. Peer Protocol # 2. Peer Protocol
# #
# 3. Ripple Protocol # 3. XRPL protocol
# #
# 4. HTTPS Client # 4. HTTPS Client
# #
@@ -383,7 +383,7 @@
# #
# These settings control security and access attributes of the Peer to Peer # These settings control security and access attributes of the Peer to Peer
# server section of the xrpld process. Peer Protocol implements the # server section of the xrpld process. Peer Protocol implements the
# Ripple Payment protocol. It is over peer connections that transactions # XRPL payment protocol. It is over peer connections that transactions
# and validations are passed from to machine to machine, to determine the # and validations are passed from to machine to machine, to determine the
# contents of validated ledgers. # contents of validated ledgers.
# #
@@ -406,7 +406,7 @@
# #
# [ips] # [ips]
# #
# List of hostnames or ips where the Ripple protocol is served. A default # List of hostnames or ips where the XRPL protocol is served. A default
# starter list is included in the code and used if no other hostnames are # starter list is included in the code and used if no other hostnames are
# available. # available.
# #
@@ -435,7 +435,7 @@
# List of IP addresses or hostnames to which xrpld should always attempt to # List of IP addresses or hostnames to which xrpld should always attempt to
# maintain peer connections with. This is useful for manually forming private # maintain peer connections with. This is useful for manually forming private
# networks, for example to configure a validation server that connects to the # networks, for example to configure a validation server that connects to the
# Ripple network through a public-facing server, or for building a set # XRPL network through a public-facing server, or for building a set
# of cluster peers. # of cluster peers.
# #
# One address or domain names per line is allowed. A port must be specified # One address or domain names per line is allowed. A port must be specified
@@ -748,8 +748,8 @@
# the folder in which the xrpld.cfg file is located. # the folder in which the xrpld.cfg file is located.
# #
# Examples: # Examples:
# /home/ripple/validators.txt # /home/username/validators.txt
# C:/home/ripple/validators.txt # C:/home/username/validators.txt
# #
# Example content: # Example content:
# [validators] # [validators]
@@ -840,7 +840,7 @@
# #
# 0: Disable the ledger replay feature [default] # 0: Disable the ledger replay feature [default]
# 1: Enable the ledger replay feature. With this feature enabled, when # 1: Enable the ledger replay feature. With this feature enabled, when
# acquiring a ledger from the network, a xrpld node only downloads # acquiring a ledger from the network, an xrpld node only downloads
# the ledger header and the transactions instead of the whole ledger. # the ledger header and the transactions instead of the whole ledger.
# And the ledger is built by applying the transactions to the parent # And the ledger is built by applying the transactions to the parent
# ledger. # ledger.
@@ -853,7 +853,7 @@
# #
# The xrpld server instance uses HTTPS GET requests in a variety of # The xrpld server instance uses HTTPS GET requests in a variety of
# circumstances, including but not limited to contacting trusted domains to # circumstances, including but not limited to contacting trusted domains to
# fetch information such as mapping an email address to a Ripple Payment # fetch information such as mapping an email address to an XRPL payment
# Network address. # Network address.
# #
# [ssl_verify] # [ssl_verify]
@@ -1227,7 +1227,7 @@
# #
#---------- #----------
# #
# The vote settings configure settings for the entire Ripple network. # The vote settings configure settings for the entire XRPL network.
# While a single instance of xrpld cannot unilaterally enforce network-wide # While a single instance of xrpld cannot unilaterally enforce network-wide
# settings, these choices become part of the instance's vote during the # settings, these choices become part of the instance's vote during the
# consensus process for each voting ledger. # consensus process for each voting ledger.

View File

@@ -44,6 +44,10 @@ suggestWords:
words: words:
- abempty - abempty
- AMMID - AMMID
- AMMMPT
- AMMMPToken
- AMMMPTokens
- AMMXRP
- amt - amt
- amts - amts
- asnode - asnode
@@ -96,6 +100,7 @@ words:
- distro - distro
- doxyfile - doxyfile
- dxrpl - dxrpl
- enabled
- endmacro - endmacro
- exceptioned - exceptioned
- Falco - Falco
@@ -148,6 +153,8 @@ words:
- ltype - ltype
- mcmodel - mcmodel
- MEMORYSTATUSEX - MEMORYSTATUSEX
- MPTAMM
- MPTDEX
- Merkle - Merkle
- Metafuncton - Metafuncton
- misprediction - misprediction
@@ -157,6 +164,7 @@ words:
- mptid - mptid
- mptissuance - mptissuance
- mptissuanceid - mptissuanceid
- mptissue
- mptoken - mptoken
- mptokenid - mptokenid
- mptokenissuance - mptokenissuance

View File

@@ -558,7 +558,7 @@ network delay. A test case specifies:
1. a UNL with different number of validators for different test cases, 1. a UNL with different number of validators for different test cases,
1. a network with zero or more non-validator nodes, 1. a network with zero or more non-validator nodes,
1. a sequence of validator reliability change events (by killing/restarting 1. a sequence of validator reliability change events (by killing/restarting
nodes, or by running modified rippled that does not send all validation nodes, or by running modified xrpld that does not send all validation
messages), messages),
1. the correct outcomes. 1. the correct outcomes.
@@ -566,7 +566,7 @@ For all the test cases, the correct outcomes are verified by examining logs. We
will grep the log to see if the correct negative UNLs are generated, and whether will grep the log to see if the correct negative UNLs are generated, and whether
or not the network is making progress when it should be. The ripdtop tool will or not the network is making progress when it should be. The ripdtop tool will
be helpful for monitoring validators' states and ledger progress. Some of the be helpful for monitoring validators' states and ledger progress. Some of the
timing parameters of rippled will be changed to have faster ledger time. Most if timing parameters of xrpld will be changed to have faster ledger time. Most if
not all test cases do not need client transactions. not all test cases do not need client transactions.
For example, the test cases for the prototype: For example, the test cases for the prototype:
@@ -583,7 +583,7 @@ For example, the test cases for the prototype:
We considered testing with the current unit test framework, specifically the We considered testing with the current unit test framework, specifically the
[Consensus Simulation [Consensus Simulation
Framework](https://github.com/ripple/rippled/blob/develop/src/test/csf/README.md) Framework](https://github.com/XRPLF/rippled/blob/develop/src/test/csf/README.md)
(CSF). However, the CSF currently can only test the generic consensus algorithm (CSF). However, the CSF currently can only test the generic consensus algorithm
as in the paper: [Analysis of the XRP Ledger Consensus as in the paper: [Analysis of the XRP Ledger Consensus
Protocol](https://arxiv.org/abs/1802.07242). Protocol](https://arxiv.org/abs/1802.07242).

View File

@@ -4,7 +4,7 @@ skinparam sequenceArrowThickness 2
skinparam roundcorner 20 skinparam roundcorner 20
skinparam maxmessagesize 160 skinparam maxmessagesize 160
actor "Rippled Start" as RS actor "Xrpld Start" as RS
participant "Timer" as T participant "Timer" as T
participant "NetworkOPs" as NOP participant "NetworkOPs" as NOP
participant "ValidatorList" as VL #lightgreen participant "ValidatorList" as VL #lightgreen

View File

@@ -1,5 +1,5 @@
# `rippled` Docker Image # `xrpld` Docker Image
- Some info relating to Docker containers can be found here: [../Builds/containers](../Builds/containers) - Some info relating to Docker containers can be found here: [../Builds/containers](../Builds/containers)
- Images for building and testing rippled can be found here: [thejohnfreeman/rippled-docker](https://github.com/thejohnfreeman/rippled-docker/) - Images for building and testing xrpld can be found here: [thejohnfreeman/rippled-docker](https://github.com/thejohnfreeman/rippled-docker/)
- These images do not have rippled. They have all the tools necessary to build rippled. - These images do not have xrpld. They have all the tools necessary to build xrpld.

View File

@@ -2,7 +2,7 @@
# Project related configuration options # Project related configuration options
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8 DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "rippled" PROJECT_NAME = "xrpld"
PROJECT_NUMBER = PROJECT_NUMBER =
PROJECT_BRIEF = PROJECT_BRIEF =
PROJECT_LOGO = PROJECT_LOGO =

View File

@@ -1,4 +1,4 @@
## Heap profiling of rippled with jemalloc ## Heap profiling of xrpld with jemalloc
The jemalloc library provides a good API for doing heap analysis, The jemalloc library provides a good API for doing heap analysis,
including a mechanism to dump a description of the heap from within the including a mechanism to dump a description of the heap from within the
@@ -7,26 +7,26 @@ activity in general, as well as how to acquire the software, are available on
the jemalloc site: the jemalloc site:
[https://github.com/jemalloc/jemalloc/wiki/Use-Case:-Heap-Profiling](https://github.com/jemalloc/jemalloc/wiki/Use-Case:-Heap-Profiling) [https://github.com/jemalloc/jemalloc/wiki/Use-Case:-Heap-Profiling](https://github.com/jemalloc/jemalloc/wiki/Use-Case:-Heap-Profiling)
jemalloc is acquired separately from rippled, and is not affiliated jemalloc is acquired separately from xrpld, and is not affiliated
with Ripple Labs. If you compile and install jemalloc from the with Ripple Labs. If you compile and install jemalloc from the
source release with default options, it will install the library and header source release with default options, it will install the library and header
under `/usr/local/lib` and `/usr/local/include`, respectively. Heap under `/usr/local/lib` and `/usr/local/include`, respectively. Heap
profiling has been tested with rippled on a Linux platform. It should profiling has been tested with xrpld on a Linux platform. It should
work on platforms on which both rippled and jemalloc are available. work on platforms on which both xrpld and jemalloc are available.
To link rippled with jemalloc, the argument To link xrpld with jemalloc, the argument
`profile-jemalloc=<jemalloc_dir>` is provided after the optional target. `profile-jemalloc=<jemalloc_dir>` is provided after the optional target.
The `<jemalloc_dir>` argument should be the same as that of the The `<jemalloc_dir>` argument should be the same as that of the
`--prefix` parameter passed to the jemalloc configure script when building. `--prefix` parameter passed to the jemalloc configure script when building.
## Examples: ## Examples:
Build rippled with jemalloc library under /usr/local/lib and Build xrpld with jemalloc library under /usr/local/lib and
header under /usr/local/include: header under /usr/local/include:
$ scons profile-jemalloc=/usr/local $ scons profile-jemalloc=/usr/local
Build rippled using clang with the jemalloc library under /opt/local/lib Build xrpld using clang with the jemalloc library under /opt/local/lib
and header under /opt/local/include: and header under /opt/local/include:
$ scons clang profile-jemalloc=/opt/local $ scons clang profile-jemalloc=/opt/local

View File

@@ -1,61 +0,0 @@
# Building documentation
## Dependencies
Install these dependencies:
- [Doxygen](http://www.doxygen.nl): All major platforms have [official binary
distributions](http://www.doxygen.nl/download.html#srcbin), or you can
build from [source](http://www.doxygen.nl/download.html#srcbin).
- MacOS: We recommend installing via Homebrew: `brew install doxygen`.
The executable will be installed in `/usr/local/bin` which is already
in the default `PATH`.
If you use the official binary distribution, then you'll need to make
Doxygen available to your command line. You can do this by adding
a symbolic link from `/usr/local/bin` to the `doxygen` executable. For
example,
```
$ ln -s /Applications/Doxygen.app/Contents/Resources/doxygen /usr/local/bin/doxygen
```
- [PlantUML](http://plantuml.com):
1. Install a functioning Java runtime, if you don't already have one.
2. Download [`plantuml.jar`](http://sourceforge.net/projects/plantuml/files/plantuml.jar/download).
- [Graphviz](https://www.graphviz.org):
- Linux: Install from your package manager.
- Windows: Use an [official installer](https://graphviz.gitlab.io/_pages/Download/Download_windows.html).
- MacOS: Install via Homebrew: `brew install graphviz`.
## Docker
Instead of installing the above dependencies locally, you can use the official
build environment Docker image, which has all of them installed already.
1. Install [Docker](https://docs.docker.com/engine/installation/)
2. Pull the image:
```
sudo docker pull rippleci/rippled-ci-builder:2944b78d22db
```
3. Run the image from the project folder:
```
sudo docker run -v $PWD:/opt/rippled --rm rippleci/rippled-ci-builder:2944b78d22db
```
## Build
There is a `docs` target in the CMake configuration.
```
mkdir build
cd build
cmake -Donly_docs=ON ..
cmake --build . --target docs --parallel
```
The output will be in `build/docs/html`.

View File

@@ -20,7 +20,7 @@ CMakeToolchain
``` ```
# If you want to depend on a version of libxrpl that is not in ConanCenter, # If you want to depend on a version of libxrpl that is not in ConanCenter,
# then you can export the recipe from the rippled project. # then you can export the recipe from the xrpld project.
conan export <path> conan export <path>
``` ```
@@ -49,9 +49,9 @@ cmake --build . --parallel
## CMake subdirectory ## CMake subdirectory
The second method adds the [rippled][] project as a CMake The second method adds the [xrpld][] project as a CMake
[subdirectory][add_subdirectory]. [subdirectory][add_subdirectory].
This method works well when you keep the rippled project as a Git This method works well when you keep the xrpld project as a Git
[submodule][]. [submodule][].
It's good for when you want to make changes to libxrpl as part of your own It's good for when you want to make changes to libxrpl as part of your own
project. project.
@@ -90,6 +90,6 @@ cmake --build . --parallel
[add_subdirectory]: https://cmake.org/cmake/help/latest/command/add_subdirectory.html [add_subdirectory]: https://cmake.org/cmake/help/latest/command/add_subdirectory.html
[submodule]: https://git-scm.com/book/en/v2/Git-Tools-Submodules [submodule]: https://git-scm.com/book/en/v2/Git-Tools-Submodules
[rippled]: https://github.com/ripple/rippled [xrpld]: https://github.com/XRPLF/rippled
[Conan]: https://docs.conan.io/ [Conan]: https://docs.conan.io/
[CMake]: https://cmake.org/cmake/help/latest/ [CMake]: https://cmake.org/cmake/help/latest/

View File

@@ -55,7 +55,7 @@ clang --version
### Install Xcode Specific Version (Optional) ### Install Xcode Specific Version (Optional)
If you develop other applications using XCode you might be consistently updating to the newest version of Apple Clang. If you develop other applications using XCode you might be consistently updating to the newest version of Apple Clang.
This will likely cause issues building rippled. You may want to install a specific version of Xcode: This will likely cause issues building xrpld. You may want to install a specific version of Xcode:
1. **Download Xcode** 1. **Download Xcode**
- Visit [Apple Developer Downloads](https://developer.apple.com/download/more/) - Visit [Apple Developer Downloads](https://developer.apple.com/download/more/)

58
docs/build/install.md vendored
View File

@@ -1,4 +1,4 @@
This document contains instructions for installing rippled. This document contains instructions for installing xrpld.
The APT package manager is common on Debian-based Linux distributions like The APT package manager is common on Debian-based Linux distributions like
Ubuntu, Ubuntu,
while the YUM package manager is common on Red Hat-based Linux distributions while the YUM package manager is common on Red Hat-based Linux distributions
@@ -8,7 +8,7 @@ and the only supported option for installing custom builds.
## From source ## From source
From a source build, you can install rippled and libxrpl using CMake's From a source build, you can install xrpld and libxrpl using CMake's
`--install` mode: `--install` mode:
``` ```
@@ -16,7 +16,7 @@ cmake --install . --prefix /opt/local
``` ```
The default [prefix][1] is typically `/usr/local` on Linux and macOS and The default [prefix][1] is typically `/usr/local` on Linux and macOS and
`C:/Program Files/rippled` on Windows. `C:/Program Files/xrpld` on Windows.
[1]: https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html [1]: https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html
@@ -50,9 +50,9 @@ The default [prefix][1] is typically `/usr/local` on Linux and macOS and
In particular, make sure that the fingerprint matches. (In the above example, the fingerprint is on the third line, starting with `C001`.) In particular, make sure that the fingerprint matches. (In the above example, the fingerprint is on the third line, starting with `C001`.)
5. Add the appropriate Ripple repository for your operating system version: 5. Add the appropriate XRPL repository for your operating system version:
echo "deb [signed-by=/usr/local/share/keyrings/ripple-key.gpg] https://repos.ripple.com/repos/rippled-deb focal stable" | \ echo "deb [signed-by=/usr/local/share/keyrings/ripple-key.gpg] https://repos.ripple.com/repos/xrpld-deb focal stable" | \
sudo tee -a /etc/apt/sources.list.d/ripple.list sudo tee -a /etc/apt/sources.list.d/ripple.list
The above example is appropriate for **Ubuntu 20.04 Focal Fossa**. For other operating systems, replace the word `focal` with one of the following: The above example is appropriate for **Ubuntu 20.04 Focal Fossa**. For other operating systems, replace the word `focal` with one of the following:
@@ -61,33 +61,33 @@ The default [prefix][1] is typically `/usr/local` on Linux and macOS and
- `bullseye` for **Debian 11 Bullseye** - `bullseye` for **Debian 11 Bullseye**
- `buster` for **Debian 10 Buster** - `buster` for **Debian 10 Buster**
If you want access to development or pre-release versions of `rippled`, use one of the following instead of `stable`: If you want access to development or pre-release versions of `xrpld`, use one of the following instead of `stable`:
- `unstable` - Pre-release builds ([`release` branch](https://github.com/ripple/rippled/tree/release)) - `unstable` - Pre-release builds ([`release` branch](https://github.com/XRPLF/rippled/tree/release))
- `nightly` - Experimental/development builds ([`develop` branch](https://github.com/ripple/rippled/tree/develop)) - `nightly` - Experimental/development builds ([`develop` branch](https://github.com/XRPLF/rippled/tree/develop))
**Warning:** Unstable and nightly builds may be broken at any time. Do not use these builds for production servers. **Warning:** Unstable and nightly builds may be broken at any time. Do not use these builds for production servers.
6. Fetch the Ripple repository. 6. Fetch the XRPL repository.
sudo apt -y update sudo apt -y update
7. Install the `rippled` software package: 7. Install the `xrpld` software package:
sudo apt -y install rippled sudo apt -y install xrpld
8. Check the status of the `rippled` service: 8. Check the status of the `xrpld` service:
systemctl status rippled.service systemctl status xrpld.service
The `rippled` service should start automatically. If not, you can start it manually: The `xrpld` service should start automatically. If not, you can start it manually:
sudo systemctl start rippled.service sudo systemctl start xrpld.service
9. Optional: allow `rippled` to bind to privileged ports. 9. Optional: allow `xrpld` to bind to privileged ports.
This allows you to serve incoming API requests on port 80 or 443. (If you want to do so, you must also update the config file's port settings.) This allows you to serve incoming API requests on port 80 or 443. (If you want to do so, you must also update the config file's port settings.)
sudo setcap 'cap_net_bind_service=+ep' /opt/ripple/bin/rippled sudo setcap 'cap_net_bind_service=+ep' /opt/xrpld/bin/xrpld
## With the YUM package manager ## With the YUM package manager
@@ -106,8 +106,8 @@ The default [prefix][1] is typically `/usr/local` on Linux and macOS and
enabled=1 enabled=1
gpgcheck=0 gpgcheck=0
repo_gpgcheck=1 repo_gpgcheck=1
baseurl=https://repos.ripple.com/repos/rippled-rpm/stable/ baseurl=https://repos.ripple.com/repos/xrpld-rpm/stable/
gpgkey=https://repos.ripple.com/repos/rippled-rpm/stable/repodata/repomd.xml.key gpgkey=https://repos.ripple.com/repos/xrpld-rpm/stable/repodata/repomd.xml.key
REPOFILE REPOFILE
_Unstable_ _Unstable_
@@ -118,8 +118,8 @@ The default [prefix][1] is typically `/usr/local` on Linux and macOS and
enabled=1 enabled=1
gpgcheck=0 gpgcheck=0
repo_gpgcheck=1 repo_gpgcheck=1
baseurl=https://repos.ripple.com/repos/rippled-rpm/unstable/ baseurl=https://repos.ripple.com/repos/xrpld-rpm/unstable/
gpgkey=https://repos.ripple.com/repos/rippled-rpm/unstable/repodata/repomd.xml.key gpgkey=https://repos.ripple.com/repos/xrpld-rpm/unstable/repodata/repomd.xml.key
REPOFILE REPOFILE
_Nightly_ _Nightly_
@@ -130,22 +130,22 @@ The default [prefix][1] is typically `/usr/local` on Linux and macOS and
enabled=1 enabled=1
gpgcheck=0 gpgcheck=0
repo_gpgcheck=1 repo_gpgcheck=1
baseurl=https://repos.ripple.com/repos/rippled-rpm/nightly/ baseurl=https://repos.ripple.com/repos/xrpld-rpm/nightly/
gpgkey=https://repos.ripple.com/repos/rippled-rpm/nightly/repodata/repomd.xml.key gpgkey=https://repos.ripple.com/repos/xrpld-rpm/nightly/repodata/repomd.xml.key
REPOFILE REPOFILE
2. Fetch the latest repo updates: 2. Fetch the latest repo updates:
sudo yum -y update sudo yum -y update
3. Install the new `rippled` package: 3. Install the new `xrpld` package:
sudo yum install -y rippled sudo yum install -y xrpld
4. Configure the `rippled` service to start on boot: 4. Configure the `xrpld` service to start on boot:
sudo systemctl enable rippled.service sudo systemctl enable xrpld.service
5. Start the `rippled` service: 5. Start the `xrpld` service:
sudo systemctl start rippled.service sudo systemctl start xrpld.service

View File

@@ -1,9 +1,9 @@
# Sanitizer Configuration for Rippled # Sanitizer Configuration for Xrpld
This document explains how to properly configure and run sanitizers (AddressSanitizer, undefinedbehaviorSanitizer, ThreadSanitizer) with the xrpld project. This document explains how to properly configure and run sanitizers (AddressSanitizer, undefinedbehaviorSanitizer, ThreadSanitizer) with the xrpld project.
Corresponding suppression files are located in the `sanitizers/suppressions` directory. Corresponding suppression files are located in the `sanitizers/suppressions` directory.
- [Sanitizer Configuration for Rippled](#sanitizer-configuration-for-rippled) - [Sanitizer Configuration for Xrpld](#sanitizer-configuration-for-xrpld)
- [Building with Sanitizers](#building-with-sanitizers) - [Building with Sanitizers](#building-with-sanitizers)
- [Summary](#summary) - [Summary](#summary)
- [Build steps:](#build-steps) - [Build steps:](#build-steps)
@@ -100,7 +100,7 @@ export LSAN_OPTIONS="include=sanitizers/suppressions/runtime-lsan-options.txt:su
- Boost intrusive containers (used in `aged_unordered_container`) trigger false positives - Boost intrusive containers (used in `aged_unordered_container`) trigger false positives
- Boost context switching (used in `Workers.cpp`) confuses ASAN's stack tracking - Boost context switching (used in `Workers.cpp`) confuses ASAN's stack tracking
- Since we usually don't build Boost (because we don't want to instrument Boost and detect issues in Boost code) with ASAN but use Boost containers in ASAN instrumented rippled code, it generates false positives. - Since we usually don't build Boost (because we don't want to instrument Boost and detect issues in Boost code) with ASAN but use Boost containers in ASAN instrumented xrpld code, it generates false positives.
- Building dependencies with ASAN instrumentation reduces false positives. But we don't want to instrument dependencies like Boost with ASAN because it is slow (to compile as well as run tests) and not necessary. - Building dependencies with ASAN instrumentation reduces false positives. But we don't want to instrument dependencies like Boost with ASAN because it is slow (to compile as well as run tests) and not necessary.
- See: https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow - See: https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow
- More such flags are detailed [here](https://github.com/google/sanitizers/wiki/AddressSanitizerFlags) - More such flags are detailed [here](https://github.com/google/sanitizers/wiki/AddressSanitizerFlags)

View File

@@ -5,9 +5,9 @@
Consensus is the task of reaching agreement within a distributed system in the Consensus is the task of reaching agreement within a distributed system in the
presence of faulty or even malicious participants. This document outlines the presence of faulty or even malicious participants. This document outlines the
[XRP Ledger Consensus Algorithm](https://arxiv.org/abs/1802.07242) [XRP Ledger Consensus Algorithm](https://arxiv.org/abs/1802.07242)
as implemented in [rippled](https://github.com/ripple/rippled), but as implemented in [xrpld](https://github.com/XRPLF/rippled), but
focuses on its utility as a generic consensus algorithm independent of the focuses on its utility as a generic consensus algorithm independent of the
detailed mechanics of the Ripple Consensus Ledger. Most notably, the algorithm detailed mechanics of the XRPL consensus Ledger. Most notably, the algorithm
does not require fully synchronous communication between all nodes in the does not require fully synchronous communication between all nodes in the
network, or even a fixed network topology, but instead achieves consensus via network, or even a fixed network topology, but instead achieves consensus via
collectively trusted subnetworks. collectively trusted subnetworks.
@@ -15,7 +15,7 @@ collectively trusted subnetworks.
## Distributed Agreement ## Distributed Agreement
A challenge for distributed systems is reaching agreement on changes in shared A challenge for distributed systems is reaching agreement on changes in shared
state. For the Ripple network, the shared state is the current ledger--account state. For the XRPL network, the shared state is the current ledger--account
information, account balances, order books and other financial data. We will information, account balances, order books and other financial data. We will
refer to shared distributed state as a /ledger/ throughout the remainder of this refer to shared distributed state as a /ledger/ throughout the remainder of this
document. document.
@@ -23,7 +23,7 @@ document.
![Ledger Chain](images/consensus/ledger_chain.png "Ledger Chain") ![Ledger Chain](images/consensus/ledger_chain.png "Ledger Chain")
As shown above, new ledgers are made by applying a set of transactions to the As shown above, new ledgers are made by applying a set of transactions to the
prior ledger. For the Ripple network, transactions include payments, prior ledger. For the XRPL network, transactions include payments,
modification of account settings, updates to offers and more. modification of account settings, updates to offers and more.
In a centralized system, generating the next ledger is trivial since there is a In a centralized system, generating the next ledger is trivial since there is a
@@ -33,10 +33,10 @@ the set of transactions to include, the order to apply those transactions, and
even the resulting ledger after applying the transactions. This is even more even the resulting ledger after applying the transactions. This is even more
difficult when some participants are faulty or malicious. difficult when some participants are faulty or malicious.
The Ripple network is a decentralized and **trust-full** network. Anyone is free The XRPL network is a decentralized and **trust-full** network. Anyone is free
to join and participants are free to choose a subset of peers that are to join and participants are free to choose a subset of peers that are
collectively trusted to not collude in an attempt to defraud the participant. collectively trusted to not collude in an attempt to defraud the participant.
Leveraging this network of trust, the Ripple algorithm has two main components. Leveraging this network of trust, the XRPL algorithm has two main components.
- _Consensus_ in which network participants agree on the transactions to apply - _Consensus_ in which network participants agree on the transactions to apply
to a prior ledger, based on the positions of their chosen peers. to a prior ledger, based on the positions of their chosen peers.
@@ -54,9 +54,9 @@ and was abandoned.
The remainder of this section describes the Consensus and Validation algorithms The remainder of this section describes the Consensus and Validation algorithms
in more detail and is meant as a companion guide to understanding the generic in more detail and is meant as a companion guide to understanding the generic
implementation in `rippled`. The document **does not** discuss correctness, implementation in `xrpld`. The document **does not** discuss correctness,
fault-tolerance or liveness properties of the algorithms or the full details of fault-tolerance or liveness properties of the algorithms or the full details of
how they integrate within `rippled` to support the Ripple Consensus Ledger. how they integrate within `xrpld` to support the XRPL consensus Ledger.
## Consensus Overview ## Consensus Overview

2
external/README.md vendored
View File

@@ -1,6 +1,6 @@
# External Conan recipes # External Conan recipes
The subdirectories in this directory contain external libraries used by rippled. The subdirectories in this directory contain external libraries used by xrpld.
| Folder | Upstream | Description | | Folder | Upstream | Description |
| :--------------- | :------------------------------------------------------------- | :------------------------------------------------------------------------------------------- | | :--------------- | :------------------------------------------------------------- | :------------------------------------------------------------------------------------------- |

View File

@@ -1,11 +1,11 @@
cmake_minimum_required(VERSION 3.18) cmake_minimum_required(VERSION 3.18)
# Note, version set explicitly by rippled project # Note, version set explicitly by xrpld project
project(antithesis-sdk-cpp VERSION 0.4.4 LANGUAGES CXX) project(antithesis-sdk-cpp VERSION 0.4.4 LANGUAGES CXX)
add_library(antithesis-sdk-cpp INTERFACE antithesis_sdk.h) add_library(antithesis-sdk-cpp INTERFACE antithesis_sdk.h)
# Note, both sections below created by rippled project # Note, both sections below created by xrpld project
target_include_directories(antithesis-sdk-cpp INTERFACE target_include_directories(antithesis-sdk-cpp INTERFACE
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>

View File

@@ -99,7 +99,7 @@ private:
Derived classes have their instances counted automatically. This is used Derived classes have their instances counted automatically. This is used
for reporting purposes. for reporting purposes.
@ingroup ripple_basics @ingroup basics
*/ */
template <class Object> template <class Object>
class CountedObject class CountedObject

View File

@@ -59,7 +59,7 @@ concept CAdoptTag = std::is_same_v<T, SharedIntrusiveAdoptIncrementStrongTag> ||
still retaining the reference counts. For example, for SHAMapInnerNodes the still retaining the reference counts. For example, for SHAMapInnerNodes the
children may be reset in that function. Note that std::shared_pointer WILL children may be reset in that function. Note that std::shared_pointer WILL
run the destructor when the strong count reaches zero, but may not free the run the destructor when the strong count reaches zero, but may not free the
memory used by the object until the weak count reaches zero. In rippled, we memory used by the object until the weak count reaches zero. In xrpld, we
typically allocate shared pointers with the `make_shared` function. When typically allocate shared pointers with the `make_shared` function. When
that is used, the memory is not reclaimed until the weak count reaches zero. that is used, the memory is not reclaimed until the weak count reaches zero.
*/ */

View File

@@ -33,7 +33,7 @@ enum class ReleaseWeakRefAction { noop, destroy };
/** Implement the strong count, weak count, and bit flags for an intrusive /** Implement the strong count, weak count, and bit flags for an intrusive
pointer. pointer.
A class can satisfy the requirements of a xrpl::IntrusivePointer by A class can satisfy the requirements of an xrpl::IntrusivePointer by
inheriting from this class. inheriting from this class.
*/ */
struct IntrusiveRefCounts struct IntrusiveRefCounts

View File

@@ -2,9 +2,9 @@
Utility functions and classes. Utility functions and classes.
ripple/basic should contain no dependencies on other modules. The module xrpl/basics should contain no dependencies on other modules.
# Choosing a rippled container. # Choosing an xrpld container.
- `std::vector` - `std::vector`
- For ordered containers with most insertions or erases at the end. - For ordered containers with most insertions or erases at the end.

View File

@@ -26,7 +26,7 @@ public:
explicit UptimeClock() = default; explicit UptimeClock() = default;
static time_point static time_point
now(); // seconds since rippled program start now(); // seconds since xrpld program start
private: private:
static std::atomic<rep> now_; static std::atomic<rep> now_;

View File

@@ -17,13 +17,13 @@ static_assert(
// NOLINTNEXTLINE(misc-redundant-expression) // NOLINTNEXTLINE(misc-redundant-expression)
std::is_integral<beast::xor_shift_engine::result_type>::value && std::is_integral<beast::xor_shift_engine::result_type>::value &&
std::is_unsigned<beast::xor_shift_engine::result_type>::value, std::is_unsigned<beast::xor_shift_engine::result_type>::value,
"The Ripple default PRNG engine must return an unsigned integral type."); "The XRPL default PRNG engine must return an unsigned integral type.");
static_assert( static_assert(
// NOLINTNEXTLINE(misc-redundant-expression) // NOLINTNEXTLINE(misc-redundant-expression)
std::numeric_limits<beast::xor_shift_engine::result_type>::max() >= std::numeric_limits<beast::xor_shift_engine::result_type>::max() >=
std::numeric_limits<std::uint64_t>::max(), std::numeric_limits<std::uint64_t>::max(),
"The Ripple default PRNG engine return must be at least 64 bits wide."); "The XRPL default PRNG engine return must be at least 64 bits wide.");
#endif #endif
namespace detail { namespace detail {

View File

@@ -213,11 +213,60 @@ public:
// Called when a credit is made to an account // Called when a credit is made to an account
// This is required to support PaymentSandbox // This is required to support PaymentSandbox
virtual void virtual void
creditHook( creditHookIOU(
AccountID const& from, AccountID const& from,
AccountID const& to, AccountID const& to,
STAmount const& amount, STAmount const& amount,
STAmount const& preCreditBalance) STAmount const& preCreditBalance)
{
XRPL_ASSERT(amount.holds<Issue>(), "creditHookIOU: amount is for Issue");
}
virtual void
creditHookMPT(
AccountID const& from,
AccountID const& to,
STAmount const& amount,
std::uint64_t preCreditBalanceHolder,
std::int64_t preCreditBalanceIssuer)
{
XRPL_ASSERT(amount.holds<MPTIssue>(), "creditHookMPT: amount is for MPTIssue");
}
/** Facilitate tracking of MPT sold by an issuer owning MPT sell offer.
* Unlike IOU, MPT doesn't have bi-directional relationship with an issuer,
* where a trustline limits an amount that can be issued to a holder.
* Consequently, the credit step (last MPTEndpointStep or
* BookStep buying MPT) might temporarily overflow OutstandingAmount.
* Limiting of a step's output amount in this case is delegated to
* the next step (in rev order). The next step always redeems when a holder
* account sells MPT (first MPTEndpointStep or BookStep selling MPT).
* In this case the holder account is only limited by the step's output
* and it's available funds since it's transferring the funds from one
* account to another account and doesn't change OutstandingAmount.
* This doesn't apply to an offer owned by an issuer.
* In this case the issuer sells or self debits and is increasing
* OutstandingAmount. Ability to issue is limited by the issuer
* originally available funds less already self sold MPT amounts (MPT sell
* offer).
* Consider an example:
* - GW creates MPT(USD) with 1,000USD MaximumAmount.
* - GW pays 950USD to A1.
* - A1 creates an offer 100XRP(buy)/100USD(sell).
* - GW creates an offer 100XRP(buy)/100USD(sell).
* - A2 pays 200USD to A3 with sendMax of 200XRP.
* Since the payment engine executes payments in reverse,
* OutstandingAmount overflows in MPTEndpointStep: 950 + 200 = 1,150USD.
* BookStep first consumes A1 offer. This reduces OutstandingAmount
* by 100USD: 1,150 - 100 = 1,050USD. GW offer can only be partially
* consumed because the initial available amount is 50USD = 1,000 - 950.
* BookStep limits it's output to 150USD. This in turn limits A3's send
* amount to 150XRP: A1 buys 100XRP and sells 100USD to A3. This doesn't
* change OutstandingAmount. GW buys 50XRP and sells 50USD to A3. This
* changes OutstandingAmount to 1,000USD.
*/
virtual void
issuerSelfDebitHookMPT(MPTIssue const& issue, std::uint64_t amount, std::int64_t origBalance)
{ {
} }

View File

@@ -34,7 +34,7 @@ auto constexpr decreaseLedgerTimeResolutionEvery = 1;
/** Calculates the close time resolution for the specified ledger. /** Calculates the close time resolution for the specified ledger.
The Ripple protocol uses binning to represent time intervals using only one The XRPL protocol uses binning to represent time intervals using only one
timestamp. This allows servers to derive a common time for the next ledger, timestamp. This allows servers to derive a common time for the next ledger,
without the need for perfectly synchronized clocks. without the need for perfectly synchronized clocks.
The time resolution (i.e. the size of the intervals) is adjusted dynamically The time resolution (i.e. the size of the intervals) is adjusted dynamically
@@ -62,7 +62,7 @@ getNextLedgerTimeResolution(
bool previousAgree, bool previousAgree,
Seq ledgerSeq) Seq ledgerSeq)
{ {
XRPL_ASSERT(ledgerSeq != Seq{0}, "ripple:getNextLedgerTimeResolution : valid ledger sequence"); XRPL_ASSERT(ledgerSeq != Seq{0}, "xrpl::getNextLedgerTimeResolution : valid ledger sequence");
using namespace std::chrono; using namespace std::chrono;
// Find the current resolution: // Find the current resolution:
@@ -72,7 +72,7 @@ getNextLedgerTimeResolution(
previousResolution); previousResolution);
XRPL_ASSERT( XRPL_ASSERT(
iter != std::end(ledgerPossibleTimeResolutions), iter != std::end(ledgerPossibleTimeResolutions),
"ripple:getNextLedgerTimeResolution : found time resolution"); "xrpl::getNextLedgerTimeResolution : found time resolution");
// This should never happen, but just as a precaution // This should never happen, but just as a precaution
if (iter == std::end(ledgerPossibleTimeResolutions)) if (iter == std::end(ledgerPossibleTimeResolutions))

View File

@@ -3,8 +3,8 @@
#include <xrpl/ledger/AcceptedLedgerTx.h> #include <xrpl/ledger/AcceptedLedgerTx.h>
#include <xrpl/ledger/BookListeners.h> #include <xrpl/ledger/BookListeners.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/protocol/Asset.h>
#include <xrpl/protocol/Book.h> #include <xrpl/protocol/Book.h>
#include <xrpl/protocol/Issue.h>
#include <xrpl/protocol/MultiApiJson.h> #include <xrpl/protocol/MultiApiJson.h>
#include <xrpl/protocol/UintTypes.h> #include <xrpl/protocol/UintTypes.h>
@@ -53,30 +53,30 @@ public:
issue. This is useful for pathfinding to find all possible next hops issue. This is useful for pathfinding to find all possible next hops
from a given currency. from a given currency.
@param issue The issue to search for @param asset The asset to search for
@param domain Optional domain restriction for the order book @param domain Optional domain restriction for the order book
@return Vector of books that want this issue @return Vector of books that want this issue
*/ */
virtual std::vector<Book> virtual std::vector<Book>
getBooksByTakerPays(Issue const& issue, std::optional<Domain> const& domain = std::nullopt) = 0; getBooksByTakerPays(Asset const& asset, std::optional<Domain> const& domain = std::nullopt) = 0;
/** Get the count of order books that want a specific issue. /** Get the count of order books that want a specific issue.
@param issue The issue to search for @param asset The asset to search for
@param domain Optional domain restriction for the order book @param domain Optional domain restriction for the order book
@return Number of books that want this issue @return Number of books that want this issue
*/ */
virtual int virtual int
getBookSize(Issue const& issue, std::optional<Domain> const& domain = std::nullopt) = 0; getBookSize(Asset const& asset, std::optional<Domain> const& domain = std::nullopt) = 0;
/** Check if an order book to XRP exists for the given issue. /** Check if an order book to XRP exists for the given issue.
@param issue The issue to check @param asset The asset to check
@param domain Optional domain restriction for the order book @param domain Optional domain restriction for the order book
@return true if a book from this issue to XRP exists @return true if a book from this issue to XRP exists
*/ */
virtual bool virtual bool
isBookToXRP(Issue const& issue, std::optional<Domain> const& domain = std::nullopt) = 0; isBookToXRP(Asset const& asset, std::optional<Domain> const& domain = std::nullopt) = 0;
/** /**
* Process a transaction for order book tracking. * Process a transaction for order book tracking.

View File

@@ -15,10 +15,55 @@ namespace detail {
// into the PaymentSandbox class itself // into the PaymentSandbox class itself
class DeferredCredits class DeferredCredits
{ {
public: private:
struct Adjustment using KeyIOU = std::tuple<AccountID, AccountID, Currency>;
struct ValueIOU
{ {
Adjustment(STAmount const& d, STAmount const& c, STAmount const& b) explicit ValueIOU() = default;
STAmount lowAcctCredits;
STAmount highAcctCredits;
STAmount lowAcctOrigBalance;
};
struct HolderValueMPT
{
HolderValueMPT() = default;
// Debit to issuer
std::uint64_t debit = 0;
std::uint64_t origBalance = 0;
};
struct IssuerValueMPT
{
IssuerValueMPT() = default;
std::map<AccountID, HolderValueMPT> holders;
// Credit to holder
std::uint64_t credit = 0;
// OutstandingAmount might overflow when MPTs are credited to a holder.
// Consider A1 paying 100MPT to A2 and A1 already having maximum MPTs.
// Since the payment engine executes a payment in revers, A2 is
// credited first and OutstandingAmount is going to be equal
// to MaximumAmount + 100MPT. In the next step A1 redeems 100MPT
// to the issuer and OutstandingAmount balances out.
std::int64_t origBalance = 0;
// Self debit on offer selling MPT. Since the payment engine executes
// a payment in reverse, a crediting/buying step may overflow
// OutstandingAmount. A sell MPT offer owned by a holder can redeem any
// amount up to the offer's amount and holder's available funds,
// balancing out OutstandingAmount. But if the offer's owner is issuer
// then it issues more MPT. In this case the available amount to issue
// is the initial issuer's available amount less all offer sell amounts
// by the issuer. This is self-debit, where the offer's owner,
// issuer in this case, debits to self.
std::uint64_t selfDebit = 0;
};
using AdjustmentMPT = IssuerValueMPT;
public:
struct AdjustmentIOU
{
AdjustmentIOU(STAmount const& d, STAmount const& c, STAmount const& b)
: debits(d), credits(c), origBalance(b) : debits(d), credits(c), origBalance(b)
{ {
} }
@@ -29,16 +74,30 @@ public:
// Get the adjustments for the balance between main and other. // Get the adjustments for the balance between main and other.
// Returns the debits, credits and the original balance // Returns the debits, credits and the original balance
std::optional<Adjustment> std::optional<AdjustmentIOU>
adjustments(AccountID const& main, AccountID const& other, Currency const& currency) const; adjustmentsIOU(AccountID const& main, AccountID const& other, Currency const& currency) const;
std::optional<AdjustmentMPT>
adjustmentsMPT(MPTID const& mptID) const;
void void
credit( creditIOU(
AccountID const& sender, AccountID const& sender,
AccountID const& receiver, AccountID const& receiver,
STAmount const& amount, STAmount const& amount,
STAmount const& preCreditSenderBalance); STAmount const& preCreditSenderBalance);
void
creditMPT(
AccountID const& sender,
AccountID const& receiver,
STAmount const& amount,
std::uint64_t preCreditBalanceHolder,
std::int64_t preCreditBalanceIssuer);
void
issuerSelfDebitMPT(MPTIssue const& issue, std::uint64_t amount, std::int64_t origBalance);
void void
ownerCount(AccountID const& id, std::uint32_t cur, std::uint32_t next); ownerCount(AccountID const& id, std::uint32_t cur, std::uint32_t next);
@@ -52,21 +111,11 @@ public:
apply(DeferredCredits& to); apply(DeferredCredits& to);
private: private:
// lowAccount, highAccount static KeyIOU
using Key = std::tuple<AccountID, AccountID, Currency>; makeKeyIOU(AccountID const& a1, AccountID const& a2, Currency const& currency);
struct Value
{
explicit Value() = default;
STAmount lowAcctCredits; std::map<KeyIOU, ValueIOU> creditsIOU_;
STAmount highAcctCredits; std::map<MPTID, IssuerValueMPT> creditsMPT_;
STAmount lowAcctOrigBalance;
};
static Key
makeKey(AccountID const& a1, AccountID const& a2, Currency const& c);
std::map<Key, Value> credits_;
std::map<AccountID, std::uint32_t> ownerCounts_; std::map<AccountID, std::uint32_t> ownerCounts_;
}; };
@@ -131,16 +180,35 @@ public:
/** @} */ /** @} */
STAmount STAmount
balanceHook(AccountID const& account, AccountID const& issuer, STAmount const& amount) balanceHookIOU(AccountID const& account, AccountID const& issuer, STAmount const& amount)
const override; const override;
STAmount
balanceHookMPT(AccountID const& account, MPTIssue const& issue, std::int64_t amount)
const override;
STAmount
balanceHookSelfIssueMPT(MPTIssue const& issue, std::int64_t amount) const override;
void void
creditHook( creditHookIOU(
AccountID const& from, AccountID const& from,
AccountID const& to, AccountID const& to,
STAmount const& amount, STAmount const& amount,
STAmount const& preCreditBalance) override; STAmount const& preCreditBalance) override;
void
creditHookMPT(
AccountID const& from,
AccountID const& to,
STAmount const& amount,
std::uint64_t preCreditBalanceHolder,
std::int64_t preCreditBalanceIssuer) override;
void
issuerSelfDebitHookMPT(MPTIssue const& issue, std::uint64_t amount, std::int64_t origBalance)
override;
void void
adjustOwnerCountHook(AccountID const& account, std::uint32_t cur, std::uint32_t next) override; adjustOwnerCountHook(AccountID const& account, std::uint32_t cur, std::uint32_t next) override;

View File

@@ -148,15 +148,35 @@ public:
// Accounts in a payment are not allowed to use assets acquired during that // Accounts in a payment are not allowed to use assets acquired during that
// payment. The PaymentSandbox tracks the debits, credits, and owner count // payment. The PaymentSandbox tracks the debits, credits, and owner count
// changes that accounts make during a payment. `balanceHook` adjusts // changes that accounts make during a payment. `balanceHookIOU` adjusts
// balances so newly acquired assets are not counted toward the balance. // balances so newly acquired assets are not counted toward the balance.
// This is required to support PaymentSandbox. // This is required to support PaymentSandbox.
virtual STAmount virtual STAmount
balanceHook(AccountID const& account, AccountID const& issuer, STAmount const& amount) const balanceHookIOU(AccountID const& account, AccountID const& issuer, STAmount const& amount) const
{ {
XRPL_ASSERT(amount.holds<Issue>(), "balanceHookIOU: amount is for Issue");
return amount; return amount;
} }
// balanceHookMPT adjusts balances so newly acquired assets are not counted
// toward the balance.
virtual STAmount
balanceHookMPT(AccountID const& account, MPTIssue const& issue, std::int64_t amount) const
{
return STAmount{issue, amount};
}
// An offer owned by an issuer and selling MPT is limited by the issuer's
// funds available to issue, which are originally available funds less
// already self sold MPT amounts (MPT sell offer). This hook is used
// by issuerFundsToSelfIssue() function.
virtual STAmount
balanceHookSelfIssueMPT(MPTIssue const& issue, std::int64_t amount) const
{
return STAmount{issue, amount};
}
// Accounts in a payment are not allowed to use assets acquired during that // Accounts in a payment are not allowed to use assets acquired during that
// payment. The PaymentSandbox tracks the debits, credits, and owner count // payment. The PaymentSandbox tracks the debits, credits, and owner count
// changes that accounts make during a payment. `ownerCountHook` adjusts the // changes that accounts make during a payment. `ownerCountHook` adjusts the

View File

@@ -30,10 +30,10 @@ enum class SkipEntry : bool { No = false, Yes };
/** Determines whether the given expiration time has passed. /** Determines whether the given expiration time has passed.
In the XRP Ledger, expiration times are defined as the number of whole In the XRP Ledger, expiration times are defined as the number of whole
seconds after the "Ripple Epoch" which, for historical reasons, is set seconds after the "XRPL epoch" which, for historical reasons, is set
to January 1, 2000 (00:00 UTC). to January 1, 2000 (00:00 UTC).
This is like the way the Unix epoch works, except the Ripple Epoch is This is like the way the Unix epoch works, except the XRPL epoch is
precisely 946,684,800 seconds after the Unix Epoch. precisely 946,684,800 seconds after the Unix Epoch.
See https://xrpl.org/basic-data-types.html#specifying-time See https://xrpl.org/basic-data-types.html#specifying-time
@@ -63,8 +63,8 @@ isVaultPseudoAccountFrozen(
isLPTokenFrozen( isLPTokenFrozen(
ReadView const& view, ReadView const& view,
AccountID const& account, AccountID const& account,
Issue const& asset, Asset const& asset,
Issue const& asset2); Asset const& asset2);
// Return the list of enabled amendments // Return the list of enabled amendments
[[nodiscard]] std::set<uint256> [[nodiscard]] std::set<uint256>

View File

@@ -1,8 +1,13 @@
#pragma once #pragma once
#include <xrpl/basics/Expected.h>
#include <xrpl/basics/Log.h> #include <xrpl/basics/Log.h>
#include <xrpl/basics/Number.h> #include <xrpl/basics/Number.h>
#include <xrpl/beast/utility/Journal.h> #include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AMMCore.h> #include <xrpl/protocol/AMMCore.h>
#include <xrpl/protocol/AmountConversions.h> #include <xrpl/protocol/AmountConversions.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
@@ -11,6 +16,7 @@
#include <xrpl/protocol/Quality.h> #include <xrpl/protocol/Quality.h>
#include <xrpl/protocol/Rules.h> #include <xrpl/protocol/Rules.h>
#include <xrpl/protocol/STAmount.h> #include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STLedgerEntry.h>
namespace xrpl { namespace xrpl {
@@ -36,7 +42,7 @@ enum class IsDeposit : bool { No = false, Yes = true };
* @return LP Tokens as IOU * @return LP Tokens as IOU
*/ */
STAmount STAmount
ammLPTokens(STAmount const& asset1, STAmount const& asset2, Issue const& lptIssue); ammLPTokens(STAmount const& asset1, STAmount const& asset2, Asset const& lptIssue);
/** Calculate LP Tokens given asset's deposit amount. /** Calculate LP Tokens given asset's deposit amount.
* @param asset1Balance current AMM asset1 balance * @param asset1Balance current AMM asset1 balance
@@ -124,7 +130,8 @@ withinRelativeDistance(Quality const& calcQuality, Quality const& reqQuality, Nu
template <typename Amt> template <typename Amt>
requires( requires(
std::is_same_v<Amt, STAmount> || std::is_same_v<Amt, IOUAmount> || std::is_same_v<Amt, STAmount> || std::is_same_v<Amt, IOUAmount> ||
std::is_same_v<Amt, XRPAmount> || std::is_same_v<Amt, Number>) std::is_same_v<Amt, XRPAmount> || std::is_same_v<Amt, MPTAmount> ||
std::is_same_v<Amt, Number>)
bool bool
withinRelativeDistance(Amt const& calc, Amt const& req, Number const& dist) withinRelativeDistance(Amt const& calc, Amt const& req, Number const& dist)
{ {
@@ -195,7 +202,7 @@ getAMMOfferStartWithTakerGets(
// Round downward to minimize the offer and to maximize the quality. // Round downward to minimize the offer and to maximize the quality.
// This has the most impact when takerGets is XRP. // This has the most impact when takerGets is XRP.
auto const takerGets = auto const takerGets =
toAmount<TOut>(getIssue(pool.out), nTakerGetsProposed, Number::downward); toAmount<TOut>(getAsset(pool.out), nTakerGetsProposed, Number::downward);
return TAmounts<TIn, TOut>{swapAssetOut(pool, takerGets, tfee), takerGets}; return TAmounts<TIn, TOut>{swapAssetOut(pool, takerGets, tfee), takerGets};
}; };
@@ -262,7 +269,7 @@ getAMMOfferStartWithTakerPays(
// Round downward to minimize the offer and to maximize the quality. // Round downward to minimize the offer and to maximize the quality.
// This has the most impact when takerPays is XRP. // This has the most impact when takerPays is XRP.
auto const takerPays = auto const takerPays =
toAmount<TIn>(getIssue(pool.in), nTakerPaysProposed, Number::downward); toAmount<TIn>(getAsset(pool.in), nTakerPaysProposed, Number::downward);
return TAmounts<TIn, TOut>{takerPays, swapAssetIn(pool, takerPays, tfee)}; return TAmounts<TIn, TOut>{takerPays, swapAssetIn(pool, takerPays, tfee)};
}; };
@@ -331,7 +338,7 @@ changeSpotPriceQuality(
<< " " << to_string(pool.out) << " " << quality << " " << tfee; << " " << to_string(pool.out) << " " << quality << " " << tfee;
return std::nullopt; return std::nullopt;
} }
auto const takerPays = toAmount<TIn>(getIssue(pool.in), nTakerPays, Number::upward); auto const takerPays = toAmount<TIn>(getAsset(pool.in), nTakerPays, Number::upward);
// should not fail // should not fail
if (auto amounts = TAmounts<TIn, TOut>{takerPays, swapAssetIn(pool, takerPays, tfee)}; if (auto amounts = TAmounts<TIn, TOut>{takerPays, swapAssetIn(pool, takerPays, tfee)};
Quality{amounts} < quality && Quality{amounts} < quality &&
@@ -360,7 +367,7 @@ changeSpotPriceQuality(
// Generate the offer starting with XRP side. Return seated offer amounts // Generate the offer starting with XRP side. Return seated offer amounts
// if the offer can be generated, otherwise nullopt. // if the offer can be generated, otherwise nullopt.
auto amounts = [&]() { auto amounts = [&]() {
if (isXRP(getIssue(pool.out))) if (isXRP(getAsset(pool.out)))
return getAMMOfferStartWithTakerGets(pool, quality, tfee); return getAMMOfferStartWithTakerGets(pool, quality, tfee);
return getAMMOfferStartWithTakerPays(pool, quality, tfee); return getAMMOfferStartWithTakerPays(pool, quality, tfee);
}(); }();
@@ -445,7 +452,7 @@ swapAssetIn(TAmounts<TIn, TOut> const& pool, TIn const& assetIn, std::uint16_t t
auto const denom = pool.in + assetIn * (1 - fee); auto const denom = pool.in + assetIn * (1 - fee);
if (denom.signum() <= 0) if (denom.signum() <= 0)
return toAmount<TOut>(getIssue(pool.out), 0); return toAmount<TOut>(getAsset(pool.out), 0);
Number::setround(Number::upward); Number::setround(Number::upward);
auto const ratio = numerator / denom; auto const ratio = numerator / denom;
@@ -454,14 +461,14 @@ swapAssetIn(TAmounts<TIn, TOut> const& pool, TIn const& assetIn, std::uint16_t t
auto const swapOut = pool.out - ratio; auto const swapOut = pool.out - ratio;
if (swapOut.signum() < 0) if (swapOut.signum() < 0)
return toAmount<TOut>(getIssue(pool.out), 0); return toAmount<TOut>(getAsset(pool.out), 0);
return toAmount<TOut>(getIssue(pool.out), swapOut, Number::downward); return toAmount<TOut>(getAsset(pool.out), swapOut, Number::downward);
} }
else else
{ {
return toAmount<TOut>( return toAmount<TOut>(
getIssue(pool.out), getAsset(pool.out),
pool.out - (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)), pool.out - (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)),
Number::downward); Number::downward);
} }
@@ -508,7 +515,7 @@ swapAssetOut(TAmounts<TIn, TOut> const& pool, TOut const& assetOut, std::uint16_
auto const denom = pool.out - assetOut; auto const denom = pool.out - assetOut;
if (denom.signum() <= 0) if (denom.signum() <= 0)
{ {
return toMaxAmount<TIn>(getIssue(pool.in)); return toMaxAmount<TIn>(getAsset(pool.in));
} }
Number::setround(Number::upward); Number::setround(Number::upward);
@@ -522,14 +529,14 @@ swapAssetOut(TAmounts<TIn, TOut> const& pool, TOut const& assetOut, std::uint16_
Number::setround(Number::upward); Number::setround(Number::upward);
auto const swapIn = numerator2 / feeMult; auto const swapIn = numerator2 / feeMult;
if (swapIn.signum() < 0) if (swapIn.signum() < 0)
return toAmount<TIn>(getIssue(pool.in), 0); return toAmount<TIn>(getAsset(pool.in), 0);
return toAmount<TIn>(getIssue(pool.in), swapIn, Number::upward); return toAmount<TIn>(getAsset(pool.in), swapIn, Number::upward);
} }
else else
{ {
return toAmount<TIn>( return toAmount<TIn>(
getIssue(pool.in), getAsset(pool.in),
((pool.in * pool.out) / (pool.out - assetOut) - pool.in) / feeMult(tfee), ((pool.in * pool.out) / (pool.out - assetOut) - pool.in) / feeMult(tfee),
Number::upward); Number::upward);
} }
@@ -616,9 +623,9 @@ getRoundedAsset(Rules const& rules, STAmount const& balance, A const& frac, IsDe
if (!rules.enabled(fixAMMv1_3)) if (!rules.enabled(fixAMMv1_3))
{ {
if constexpr (std::is_same_v<A, STAmount>) if constexpr (std::is_same_v<A, STAmount>)
return multiply(balance, frac, balance.issue()); return multiply(balance, frac, balance.asset());
else else
return toSTAmount(balance.issue(), balance * frac); return toSTAmount(balance.asset(), balance * frac);
} }
auto const rm = detail::getAssetRounding(isDeposit); auto const rm = detail::getAssetRounding(isDeposit);
return multiply(balance, frac, rm); return multiply(balance, frac, rm);
@@ -712,4 +719,94 @@ adjustFracByTokens(
STAmount const& tokens, STAmount const& tokens,
Number const& frac); Number const& frac);
/** Get AMM pool balances.
*/
std::pair<STAmount, STAmount>
ammPoolHolds(
ReadView const& view,
AccountID const& ammAccountID,
Asset const& asset1,
Asset const& asset2,
FreezeHandling freezeHandling,
AuthHandling authHandling,
beast::Journal const j);
/** Get AMM pool and LP token balances. If both optIssue are
* provided then they are used as the AMM token pair issues.
* Otherwise the missing issues are fetched from ammSle.
*/
Expected<std::tuple<STAmount, STAmount, STAmount>, TER>
ammHolds(
ReadView const& view,
SLE const& ammSle,
std::optional<Asset> const& optAsset1,
std::optional<Asset> const& optAsset2,
FreezeHandling freezeHandling,
AuthHandling authHandling,
beast::Journal const j);
/** Get the balance of LP tokens.
*/
STAmount
ammLPHolds(
ReadView const& view,
Asset const& asset1,
Asset const& asset2,
AccountID const& ammAccount,
AccountID const& lpAccount,
beast::Journal const j);
STAmount
ammLPHolds(
ReadView const& view,
SLE const& ammSle,
AccountID const& lpAccount,
beast::Journal const j);
/** Get AMM trading fee for the given account. The fee is discounted
* if the account is the auction slot owner or one of the slot's authorized
* accounts.
*/
std::uint16_t
getTradingFee(ReadView const& view, SLE const& ammSle, AccountID const& account);
/** Returns total amount held by AMM for the given token.
*/
STAmount
ammAccountHolds(ReadView const& view, AccountID const& ammAccountID, Asset const& asset);
/** Delete trustlines to AMM. If all trustlines are deleted then
* AMM object and account are deleted. Otherwise tecINCOMPLETE is returned.
*/
TER
deleteAMMAccount(Sandbox& view, Asset const& asset, Asset const& asset2, beast::Journal j);
/** Initialize Auction and Voting slots and set the trading/discounted fee.
*/
void
initializeFeeAuctionVote(
ApplyView& view,
std::shared_ptr<SLE>& ammSle,
AccountID const& account,
Asset const& lptAsset,
std::uint16_t tfee);
/** Return true if the Liquidity Provider is the only AMM provider, false
* otherwise. Return tecINTERNAL if encountered an unexpected condition,
* for instance Liquidity Provider has more than one LPToken trustline.
*/
Expected<bool, TER>
isOnlyLiquidityProvider(ReadView const& view, Issue const& ammIssue, AccountID const& lpAccount);
/** Due to rounding, the LPTokenBalance of the last LP might
* not match the LP's trustline balance. If it's within the tolerance,
* update LPTokenBalance to match the LP's trustline balance.
*/
Expected<bool, TER>
verifyAndAdjustLPTokenBalance(
Sandbox& sb,
STAmount const& lpTokens,
std::shared_ptr<SLE>& ammSle,
AccountID const& account);
} // namespace xrpl } // namespace xrpl

View File

@@ -10,7 +10,6 @@
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/MPTAmount.h> #include <xrpl/protocol/MPTAmount.h>
#include <xrpl/protocol/Rate.h> #include <xrpl/protocol/Rate.h>
#include <xrpl/tx/transactors/token/MPTokenAuthorize.h>
namespace xrpl { namespace xrpl {
@@ -42,7 +41,8 @@ escrowUnlockApplyHelper<Issue>(
bool createAsset, bool createAsset,
beast::Journal journal) beast::Journal journal)
{ {
Keylet const trustLineKey = keylet::line(receiver, amount.issue()); Issue const& issue = amount.get<Issue>();
Keylet const trustLineKey = keylet::line(receiver, issue);
bool const recvLow = issuer > receiver; bool const recvLow = issuer > receiver;
bool const senderIssuer = issuer == sender; bool const senderIssuer = issuer == sender;
bool const receiverIssuer = issuer == receiver; bool const receiverIssuer = issuer == receiver;
@@ -65,9 +65,9 @@ escrowUnlockApplyHelper<Issue>(
return tecNO_LINE_INSUF_RESERVE; return tecNO_LINE_INSUF_RESERVE;
} }
Currency const currency = amount.getCurrency(); Currency const currency = issue.currency;
STAmount initialBalance(amount.issue()); STAmount initialBalance(issue);
initialBalance.setIssuer(noAccount()); initialBalance.get<Issue>().account = noAccount();
if (TER const ter = trustCreate( if (TER const ter = trustCreate(
view, // payment sandbox view, // payment sandbox
@@ -114,7 +114,8 @@ escrowUnlockApplyHelper<Issue>(
if ((!senderIssuer && !receiverIssuer) && lockedRate != parityRate) if ((!senderIssuer && !receiverIssuer) && lockedRate != parityRate)
{ {
// compute transfer fee, if any // compute transfer fee, if any
auto const xferFee = amount.value() - divideRound(amount, lockedRate, amount.issue(), true); auto const xferFee =
amount.value() - divideRound(amount, lockedRate, amount.get<Issue>(), true);
// compute balance to transfer // compute balance to transfer
finalAmt = amount.value() - xferFee; finalAmt = amount.value() - xferFee;
} }
@@ -149,7 +150,7 @@ escrowUnlockApplyHelper<Issue>(
// if destination is not the issuer then transfer funds // if destination is not the issuer then transfer funds
if (!receiverIssuer) if (!receiverIssuer)
{ {
auto const ter = rippleCredit(view, issuer, receiver, finalAmt, true, journal); auto const ter = directSendNoFee(view, issuer, receiver, finalAmt, true, journal);
if (!isTesSuccess(ter)) if (!isTesSuccess(ter))
return ter; // LCOV_EXCL_LINE return ter; // LCOV_EXCL_LINE
} }
@@ -183,8 +184,7 @@ escrowUnlockApplyHelper<MPTIssue>(
return tecINSUFFICIENT_RESERVE; return tecINSUFFICIENT_RESERVE;
} }
if (auto const ter = MPTokenAuthorize::createMPToken(view, mptID, receiver, 0); if (auto const ter = createMPToken(view, mptID, receiver, 0); !isTesSuccess(ter))
!isTesSuccess(ter))
{ {
return ter; // LCOV_EXCL_LINE return ter; // LCOV_EXCL_LINE
} }
@@ -218,7 +218,7 @@ escrowUnlockApplyHelper<MPTIssue>(
// compute balance to transfer // compute balance to transfer
finalAmt = amount.value() - xferFee; finalAmt = amount.value() - xferFee;
} }
return rippleUnlockEscrowMPT( return unlockEscrowMPT(
view, view,
sender, sender,
receiver, receiver,

View File

@@ -80,6 +80,7 @@ authorizeMPToken(
* requireAuth check is recursive for MPT shares in a vault, descending to * requireAuth check is recursive for MPT shares in a vault, descending to
* assets in the vault, up to maxAssetCheckDepth recursion depth. This is * assets in the vault, up to maxAssetCheckDepth recursion depth. This is
* purely defensive, as we currently do not allow such vaults to be created. * purely defensive, as we currently do not allow such vaults to be created.
* WeakAuth intentionally allows missing MPTokens under MPToken V2.
*/ */
[[nodiscard]] TER [[nodiscard]] TER
requireAuth( requireAuth(
@@ -114,6 +115,12 @@ canTransfer(
AccountID const& from, AccountID const& from,
AccountID const& to); AccountID const& to);
/** Check if Asset can be traded on DEX. return tecNO_PERMISSION
* if it doesn't and tesSUCCESS otherwise.
*/
[[nodiscard]] TER
canTrade(ReadView const& view, Asset const& asset);
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// //
// Empty holding operations (MPT-specific) // Empty holding operations (MPT-specific)
@@ -142,14 +149,14 @@ removeEmptyHolding(
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
TER TER
rippleLockEscrowMPT( lockEscrowMPT(
ApplyView& view, ApplyView& view,
AccountID const& uGrantorID, AccountID const& uGrantorID,
STAmount const& saAmount, STAmount const& saAmount,
beast::Journal j); beast::Journal j);
TER TER
rippleUnlockEscrowMPT( unlockEscrowMPT(
ApplyView& view, ApplyView& view,
AccountID const& uGrantorID, AccountID const& uGrantorID,
AccountID const& uGranteeID, AccountID const& uGranteeID,
@@ -157,4 +164,80 @@ rippleUnlockEscrowMPT(
STAmount const& grossAmount, STAmount const& grossAmount,
beast::Journal j); beast::Journal j);
TER
createMPToken(
ApplyView& view,
MPTID const& mptIssuanceID,
AccountID const& account,
std::uint32_t const flags);
TER
checkCreateMPT(
xrpl::ApplyView& view,
xrpl::MPTIssue const& mptIssue,
xrpl::AccountID const& holder,
beast::Journal j);
//------------------------------------------------------------------------------
//
// MPT Overflow related
//
//------------------------------------------------------------------------------
// MaximumAmount doesn't exceed 2**63-1
std::int64_t
maxMPTAmount(SLE const& sleIssuance);
// OutstandingAmount may overflow and available amount might be negative.
// But available amount is always <= |MaximumAmount - OutstandingAmount|.
std::int64_t
availableMPTAmount(SLE const& sleIssuance);
std::int64_t
availableMPTAmount(ReadView const& view, MPTID const& mptID);
/** Checks for two types of OutstandingAmount overflow during a send operation.
* 1. **Direct directSendNoFee (Overflow: No):** A true overflow check when
* `OutstandingAmount > MaximumAmount`. This threshold is used for direct
* 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.
*/
bool
isMPTOverflow(
std::int64_t sendAmount,
std::uint64_t outstandingAmount,
std::int64_t maximumAmount,
AllowMPTOverflow allowOverflow);
/**
* Determine funds available for an issuer to sell in an issuer owned offer.
* Issuing step, which could be either MPTEndPointStep last step or BookStep's
* TakerPays may overflow OutstandingAmount. Redeeming step, in BookStep's
* TakerGets redeems the offer's owner funds, essentially balancing out
* the overflow, unless the offer's owner is the issuer.
*/
[[nodiscard]] STAmount
issuerFundsToSelfIssue(ReadView const& view, MPTIssue const& issue);
/** Facilitate tracking of MPT sold by an issuer owning MPT sell offer.
* See ApplyView::issuerSelfDebitHookMPT().
*/
void
issuerSelfDebitHookMPT(ApplyView& view, MPTIssue const& issue, std::uint64_t amount);
//------------------------------------------------------------------------------
//
// MPT DEX
//
//------------------------------------------------------------------------------
/* Return true if a transaction is allowed for the specified MPT/account. The
* function checks MPTokenIssuance and MPToken objects flags to determine if the
* transaction is allowed.
*/
TER
checkMPTTxAllowed(ReadView const& v, TxType tx, Asset const& asset, AccountID const& accountID);
} // namespace xrpl } // namespace xrpl

View File

@@ -1,12 +1,12 @@
#pragma once #pragma once
#include <xrpl/basics/Log.h>
#include <xrpl/basics/base_uint.h> #include <xrpl/basics/base_uint.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/TER.h> #include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxFlags.h> #include <xrpl/protocol/TxFlags.h>
#include <xrpl/protocol/nft.h> #include <xrpl/protocol/nft.h>
#include <xrpl/tx/Transactor.h>
namespace xrpl { namespace xrpl {

View File

@@ -252,4 +252,14 @@ deleteAMMTrustLine(
std::optional<AccountID> const& ammAccountID, std::optional<AccountID> const& ammAccountID,
beast::Journal j); beast::Journal j);
/** Delete AMMs MPToken. The passed `sle` must be obtained from a prior
* call to view.peek().
*/
[[nodiscard]] TER
deleteAMMMPToken(
ApplyView& view,
std::shared_ptr<SLE> sleMPT,
AccountID const& ammAccountID,
beast::Journal j);
} // namespace xrpl } // namespace xrpl

View File

@@ -31,6 +31,9 @@ enum SpendableHandling { shSIMPLE_BALANCE, shFULL_BALANCE };
enum class WaiveTransferFee : bool { No = false, Yes }; enum class WaiveTransferFee : bool { No = false, Yes };
/** Controls whether accountSend is allowed to overflow OutstandingAmount **/
enum class AllowMPTOverflow : bool { No = false, Yes };
/* Check if MPToken (for MPT) or trust line (for IOU) exists: /* Check if MPToken (for MPT) or trust line (for IOU) exists:
* - StrongAuth - before checking if authorization is required * - StrongAuth - before checking if authorization is required
* - WeakAuth * - WeakAuth
@@ -176,6 +179,16 @@ accountFunds(
FreezeHandling freezeHandling, FreezeHandling freezeHandling,
beast::Journal j); beast::Journal j);
// Overload with AuthHandling to support IOU and MPT.
[[nodiscard]] STAmount
accountFunds(
ReadView const& view,
AccountID const& id,
STAmount const& saDefault,
FreezeHandling freezeHandling,
AuthHandling authHandling,
beast::Journal j);
/** Returns the transfer fee as Rate based on the type of token /** Returns the transfer fee as Rate based on the type of token
* @param view The ledger view * @param view The ledger view
* @param amount The amount to transfer * @param amount The amount to transfer
@@ -235,11 +248,11 @@ canTransfer(ReadView const& view, Asset const& asset, AccountID const& from, Acc
// --> bCheckIssuer : normally require issuer to be involved. // --> bCheckIssuer : normally require issuer to be involved.
// [[nodiscard]] // nodiscard commented out so DirectStep.cpp compiles. // [[nodiscard]] // nodiscard commented out so DirectStep.cpp compiles.
/** Calls static rippleCreditIOU if saAmount represents Issue. /** Calls static directSendNoFeeIOU if saAmount represents Issue.
* Calls static rippleCreditMPT if saAmount represents MPTIssue. * Calls static directSendNoFeeMPT if saAmount represents MPTIssue.
*/ */
TER TER
rippleCredit( directSendNoFee(
ApplyView& view, ApplyView& view,
AccountID const& uSenderID, AccountID const& uSenderID,
AccountID const& uReceiverID, AccountID const& uReceiverID,
@@ -257,7 +270,8 @@ accountSend(
AccountID const& to, AccountID const& to,
STAmount const& saAmount, STAmount const& saAmount,
beast::Journal j, beast::Journal j,
WaiveTransferFee waiveFee = WaiveTransferFee::No); WaiveTransferFee waiveFee = WaiveTransferFee::No,
AllowMPTOverflow allowOverflow = AllowMPTOverflow::No);
using MultiplePaymentDestinations = std::vector<std::pair<AccountID, Number>>; using MultiplePaymentDestinations = std::vector<std::pair<AccountID, Number>>;
/** Like accountSend, except one account is sending multiple payments (with the /** Like accountSend, except one account is sending multiple payments (with the

View File

@@ -51,7 +51,7 @@ A blob containing the payload. Stored in the following format.
--- ---
The `NodeStore` provides an interface that stores, in a persistent database, a The `NodeStore` provides an interface that stores, in a persistent database, a
collection of NodeObjects that rippled uses as its primary representation of collection of NodeObjects that xrpld uses as its primary representation of
ledger entries. All ledger entries are stored as NodeObjects and as such, need ledger entries. All ledger entries are stored as NodeObjects and as such, need
to be persisted between launches. If a NodeObject is accessed and is not in to be persisted between launches. If a NodeObject is accessed and is not in
memory, it will be retrieved from the database. memory, it will be retrieved from the database.
@@ -110,7 +110,7 @@ The `NodeStore.Timing` test is used to execute a set of read/write workloads to
compare current available nodestore backends. It can be executed with: compare current available nodestore backends. It can be executed with:
``` ```
$rippled --unittest=NodeStoreTiming $xrpld --unittest=NodeStoreTiming
``` ```
It is also possible to use alternate DB config params by passing config strings It is also possible to use alternate DB config params by passing config strings
@@ -143,10 +143,10 @@ Through various executions and profiling some conclusions are presented below.
just after ledger close, then that would provide similar, but more predictable just after ledger close, then that would provide similar, but more predictable
guarantees. It would also remove an unneeded thread and unnecessary memory guarantees. It would also remove an unneeded thread and unnecessary memory
usage. An alternative point of view is that because there will always be many usage. An alternative point of view is that because there will always be many
other rippled instances running there is no need for such guarantees. The nodes other xrpld instances running there is no need for such guarantees. The nodes
will always be available from another peer. will always be available from another peer.
- Lookup in a block was previously using binary search. With rippled's use case - Lookup in a block was previously using binary search. With xrpld's use case
it is highly unlikely that two adjacent key/values will ever be requested one it is highly unlikely that two adjacent key/values will ever be requested one
after the other. Therefore hash indexing of blocks makes much more sense. after the other. Therefore hash indexing of blocks makes much more sense.
Rocksdb has a number of options for hash indexing both memtables and blocks and Rocksdb has a number of options for hash indexing both memtables and blocks and

View File

@@ -1,8 +1,8 @@
# Protocol buffer definitions for gRPC # Protocol buffer definitions for gRPC
This folder contains the protocol buffer definitions used by the rippled gRPC API. This folder contains the protocol buffer definitions used by the xrpld gRPC API.
The gRPC API attempts to mimic the JSON/Websocket API as much as possible. The gRPC API attempts to mimic the JSON/Websocket API as much as possible.
As of April 2020, the gRPC API supports a subset of the full rippled API: As of April 2020, the gRPC API supports a subset of the full xrpld API:
tx, account_tx, account_info, fee and submit. tx, account_tx, account_info, fee and submit.
### Making Changes ### Making Changes
@@ -63,7 +63,7 @@ templated `CallData` class in GRPCServerImpl::setupListeners(). The template
parameters should be the request type and the response type. parameters should be the request type and the response type.
Finally, define the handler itself in the appropriate file under the Finally, define the handler itself in the appropriate file under the
src/ripple/rpc/handlers folder. If the method already has a JSON/Websocket src/xrpld/rpc/handlers folder. If the method already has a JSON/Websocket
equivalent, write the gRPC handler in the same file, and abstract common logic equivalent, write the gRPC handler in the same file, and abstract common logic
into helper functions (see Tx.cpp or AccountTx.cpp for an example). into helper functions (see Tx.cpp or AccountTx.cpp for an example).

View File

@@ -36,7 +36,7 @@ enum MessageType {
/* Provides the current ephemeral key for a validator. */ /* Provides the current ephemeral key for a validator. */
message TMManifest { message TMManifest {
// A Manifest object in the Ripple serialization format. // A Manifest object in the XRPL serialization format.
required bytes stobject = 1; required bytes stobject = 1;
} }

View File

@@ -2,7 +2,7 @@
#include <xrpl/basics/Number.h> #include <xrpl/basics/Number.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Issue.h> #include <xrpl/protocol/Asset.h>
#include <xrpl/protocol/TER.h> #include <xrpl/protocol/TER.h>
#include <xrpl/protocol/UintTypes.h> #include <xrpl/protocol/UintTypes.h>
@@ -31,12 +31,12 @@ class Rules;
/** Calculate Liquidity Provider Token (LPT) Currency. /** Calculate Liquidity Provider Token (LPT) Currency.
*/ */
Currency Currency
ammLPTCurrency(Currency const& cur1, Currency const& cur2); ammLPTCurrency(Asset const& asset1, Asset const& asset2);
/** Calculate LPT Issue from AMM asset pair. /** Calculate LPT Issue from AMM asset pair.
*/ */
Issue Issue
ammLPTIssue(Currency const& cur1, Currency const& cur2, AccountID const& ammAccountID); ammLPTIssue(Asset const& asset1, Asset const& asset2, AccountID const& ammAccountID);
/** Validate the amount. /** Validate the amount.
* If validZero is false and amount is beast::zero then invalid amount. * If validZero is false and amount is beast::zero then invalid amount.
@@ -46,19 +46,19 @@ ammLPTIssue(Currency const& cur1, Currency const& cur2, AccountID const& ammAcco
NotTEC NotTEC
invalidAMMAmount( invalidAMMAmount(
STAmount const& amount, STAmount const& amount,
std::optional<std::pair<Issue, Issue>> const& pair = std::nullopt, std::optional<std::pair<Asset, Asset>> const& pair = std::nullopt,
bool validZero = false); bool validZero = false);
NotTEC NotTEC
invalidAMMAsset( invalidAMMAsset(
Issue const& issue, Asset const& asset,
std::optional<std::pair<Issue, Issue>> const& pair = std::nullopt); std::optional<std::pair<Asset, Asset>> const& pair = std::nullopt);
NotTEC NotTEC
invalidAMMAssetPair( invalidAMMAssetPair(
Issue const& issue1, Asset const& asset1,
Issue const& issue2, Asset const& asset2,
std::optional<std::pair<Issue, Issue>> const& pair = std::nullopt); std::optional<std::pair<Asset, Asset>> const& pair = std::nullopt);
/** Get time slot of the auction slot. /** Get time slot of the auction slot.
*/ */

View File

@@ -2,7 +2,7 @@
#include <xrpl/protocol/tokens.h> #include <xrpl/protocol/tokens.h>
// VFALCO Uncomment when the header issues are resolved // VFALCO Uncomment when the header issues are resolved
// #include <ripple/protocol/PublicKey.h> // #include <xrpl/protocol/PublicKey.h>
#include <xrpl/basics/UnorderedContainers.h> #include <xrpl/basics/UnorderedContainers.h>
#include <xrpl/basics/base_uint.h> #include <xrpl/basics/base_uint.h>
#include <xrpl/json/json_value.h> #include <xrpl/json/json_value.h>

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <xrpl/protocol/IOUAmount.h> #include <xrpl/protocol/IOUAmount.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/STAmount.h> #include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/XRPAmount.h> #include <xrpl/protocol/XRPAmount.h>
@@ -9,11 +10,12 @@
namespace xrpl { namespace xrpl {
inline STAmount inline STAmount
toSTAmount(IOUAmount const& iou, Issue const& iss) toSTAmount(IOUAmount const& iou, Asset const& asset)
{ {
XRPL_ASSERT(asset.holds<Issue>(), "xrpl::toSTAmount : is Issue");
bool const isNeg = iou.signum() < 0; bool const isNeg = iou.signum() < 0;
std::uint64_t const umant = isNeg ? -iou.mantissa() : iou.mantissa(); std::uint64_t const umant = isNeg ? -iou.mantissa() : iou.mantissa();
return STAmount(iss, umant, iou.exponent(), isNeg, STAmount::unchecked()); return STAmount(asset, umant, iou.exponent(), isNeg, STAmount::unchecked());
} }
inline STAmount inline STAmount
@@ -31,12 +33,25 @@ toSTAmount(XRPAmount const& xrp)
} }
inline STAmount inline STAmount
toSTAmount(XRPAmount const& xrp, Issue const& iss) toSTAmount(XRPAmount const& xrp, Asset const& asset)
{ {
XRPL_ASSERT(isXRP(iss.account) && isXRP(iss.currency), "xrpl::toSTAmount : is XRP"); XRPL_ASSERT(isXRP(asset), "xrpl::toSTAmount : is XRP");
return toSTAmount(xrp); return toSTAmount(xrp);
} }
inline STAmount
toSTAmount(MPTAmount const& mpt)
{
return STAmount(mpt, noMPT());
}
inline STAmount
toSTAmount(MPTAmount const& mpt, Asset const& asset)
{
XRPL_ASSERT(asset.holds<MPTIssue>(), "xrpl::toSTAmount : is MPT");
return STAmount(mpt, asset.get<MPTIssue>());
}
template <class T> template <class T>
T T
toAmount(STAmount const& amt) = delete; toAmount(STAmount const& amt) = delete;
@@ -76,6 +91,21 @@ toAmount<XRPAmount>(STAmount const& amt)
return XRPAmount(sMant); return XRPAmount(sMant);
} }
template <>
inline MPTAmount
toAmount<MPTAmount>(STAmount const& amt)
{
XRPL_ASSERT(
amt.holds<MPTIssue>() && amt.mantissa() <= maxMPTokenAmount && amt.exponent() == 0,
"xrpl::toAmount<MPTAmount> : maximum mantissa");
if (amt.mantissa() > maxMPTokenAmount || amt.exponent() != 0)
Throw<std::runtime_error>("toAmount<MPTAmount>: invalid mantissa or exponent");
bool const isNeg = amt.negative();
std::int64_t const sMant = isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa();
return MPTAmount(sMant);
}
template <class T> template <class T>
T T
toAmount(IOUAmount const& amt) = delete; toAmount(IOUAmount const& amt) = delete;
@@ -98,23 +128,36 @@ toAmount<XRPAmount>(XRPAmount const& amt)
return amt; return amt;
} }
template <class T>
T
toAmount(MPTAmount const& amt) = delete;
template <>
inline MPTAmount
toAmount<MPTAmount>(MPTAmount const& amt)
{
return amt;
}
template <typename T> template <typename T>
T T
toAmount(Issue const& issue, Number const& n, Number::rounding_mode mode = Number::getround()) toAmount(Asset const& asset, Number const& n, Number::rounding_mode mode = Number::getround())
{ {
saveNumberRoundMode const rm(Number::getround()); saveNumberRoundMode const rm(Number::getround());
if (isXRP(issue)) if (isXRP(asset))
Number::setround(mode); Number::setround(mode);
if constexpr (std::is_same_v<IOUAmount, T>) if constexpr (std::is_same_v<IOUAmount, T>)
return IOUAmount(n); return IOUAmount(n);
else if constexpr (std::is_same_v<XRPAmount, T>) else if constexpr (std::is_same_v<XRPAmount, T>)
return XRPAmount(static_cast<std::int64_t>(n)); return XRPAmount(static_cast<std::int64_t>(n));
else if constexpr (std::is_same_v<MPTAmount, T>)
return MPTAmount(static_cast<std::int64_t>(n));
else if constexpr (std::is_same_v<STAmount, T>) else if constexpr (std::is_same_v<STAmount, T>)
{ {
if (isXRP(issue)) if (isXRP(asset))
return STAmount(issue, static_cast<std::int64_t>(n)); return STAmount(asset, static_cast<std::int64_t>(n));
return STAmount(issue, n); return STAmount(asset, n);
} }
else else
{ {
@@ -125,17 +168,23 @@ toAmount(Issue const& issue, Number const& n, Number::rounding_mode mode = Numbe
template <typename T> template <typename T>
T T
toMaxAmount(Issue const& issue) toMaxAmount(Asset const& asset)
{ {
if constexpr (std::is_same_v<IOUAmount, T>) if constexpr (std::is_same_v<IOUAmount, T>)
return IOUAmount(STAmount::cMaxValue, STAmount::cMaxOffset); return IOUAmount(STAmount::cMaxValue, STAmount::cMaxOffset);
else if constexpr (std::is_same_v<XRPAmount, T>) else if constexpr (std::is_same_v<XRPAmount, T>)
return XRPAmount(static_cast<std::int64_t>(STAmount::cMaxNativeN)); return XRPAmount(static_cast<std::int64_t>(STAmount::cMaxNativeN));
else if constexpr (std::is_same_v<MPTAmount, T>)
return MPTAmount(maxMPTokenAmount);
else if constexpr (std::is_same_v<STAmount, T>) else if constexpr (std::is_same_v<STAmount, T>)
{ {
if (isXRP(issue)) return asset.visit(
return STAmount(issue, static_cast<std::int64_t>(STAmount::cMaxNativeN)); [](Issue const& issue) {
return STAmount(issue, STAmount::cMaxValue, STAmount::cMaxOffset); if (isXRP(issue))
return STAmount(issue, static_cast<std::int64_t>(STAmount::cMaxNativeN));
return STAmount(issue, STAmount::cMaxValue, STAmount::cMaxOffset);
},
[](MPTIssue const& issue) { return STAmount(issue, maxMPTokenAmount); });
} }
else else
{ {
@@ -145,21 +194,23 @@ toMaxAmount(Issue const& issue)
} }
inline STAmount inline STAmount
toSTAmount(Issue const& issue, Number const& n, Number::rounding_mode mode = Number::getround()) toSTAmount(Asset const& asset, Number const& n, Number::rounding_mode mode = Number::getround())
{ {
return toAmount<STAmount>(issue, n, mode); return toAmount<STAmount>(asset, n, mode);
} }
template <typename T> template <typename T>
Issue Asset
getIssue(T const& amt) getAsset(T const& amt)
{ {
if constexpr (std::is_same_v<IOUAmount, T>) if constexpr (std::is_same_v<IOUAmount, T>)
return noIssue(); return noIssue();
else if constexpr (std::is_same_v<XRPAmount, T>) else if constexpr (std::is_same_v<XRPAmount, T>)
return xrpIssue(); return xrpIssue();
else if constexpr (std::is_same_v<MPTAmount, T>)
return noMPT();
else if constexpr (std::is_same_v<STAmount, T>) else if constexpr (std::is_same_v<STAmount, T>)
return amt.issue(); return amt.asset();
else else
{ {
constexpr bool alwaysFalse = !std::is_same_v<T, T>; constexpr bool alwaysFalse = !std::is_same_v<T, T>;
@@ -175,6 +226,8 @@ get(STAmount const& a)
return a.iou(); return a.iou();
else if constexpr (std::is_same_v<XRPAmount, T>) else if constexpr (std::is_same_v<XRPAmount, T>)
return a.xrp(); return a.xrp();
else if constexpr (std::is_same_v<MPTAmount, T>)
return a.mpt();
else if constexpr (std::is_same_v<STAmount, T>) else if constexpr (std::is_same_v<STAmount, T>)
return a; return a;
else else

View File

@@ -2,20 +2,37 @@
#include <xrpl/basics/Number.h> #include <xrpl/basics/Number.h>
#include <xrpl/basics/base_uint.h> #include <xrpl/basics/base_uint.h>
#include <xrpl/protocol/Concepts.h>
#include <xrpl/protocol/Issue.h> #include <xrpl/protocol/Issue.h>
#include <xrpl/protocol/MPTIssue.h> #include <xrpl/protocol/MPTIssue.h>
#include <xrpl/protocol/Rules.h>
namespace xrpl { namespace xrpl {
class Asset;
class STAmount; class STAmount;
template <typename TIss> template <typename T>
concept ValidIssueType = std::is_same_v<TIss, Issue> || std::is_same_v<TIss, MPTIssue>; requires(
std::is_same_v<T, XRPAmount> || std::is_same_v<T, IOUAmount> ||
std::is_same_v<T, MPTAmount>)
struct AmountType
{
using amount_type = T;
};
template <typename A> /* Used to check for an asset with either badCurrency()
concept AssetType = std::is_convertible_v<A, Asset> || std::is_convertible_v<A, Issue> || * or MPT with 0 account.
std::is_convertible_v<A, MPTIssue> || std::is_convertible_v<A, MPTID>; */
struct BadAsset
{
};
inline BadAsset const&
badAsset()
{
static BadAsset const a;
return a;
}
/* Asset is an abstraction of three different issue types: XRP, IOU, MPT. /* Asset is an abstraction of three different issue types: XRP, IOU, MPT.
* For historical reasons, two issue types XRP and IOU are wrapped in Issue * For historical reasons, two issue types XRP and IOU are wrapped in Issue
@@ -26,6 +43,9 @@ class Asset
{ {
public: public:
using value_type = std::variant<Issue, MPTIssue>; using value_type = std::variant<Issue, MPTIssue>;
using token_type = std::variant<Currency, MPTID>;
using AmtType =
std::variant<AmountType<XRPAmount>, AmountType<IOUAmount>, AmountType<MPTAmount>>;
private: private:
value_type issue_; value_type issue_;
@@ -69,36 +89,42 @@ public:
constexpr value_type const& constexpr value_type const&
value() const; value() const;
constexpr token_type
token() const;
void void
setJson(Json::Value& jv) const; setJson(Json::Value& jv) const;
STAmount STAmount
operator()(Number const&) const; operator()(Number const&) const;
bool constexpr AmtType
getAmountType() const;
// Custom, generic visit implementation
template <typename... Visitors>
constexpr auto
visit(Visitors&&... visitors) const -> decltype(auto)
{
// Simple delegation to the reusable utility, passing the internal
// variant data.
return detail::visit(issue_, std::forward<Visitors>(visitors)...);
}
constexpr bool
native() const native() const
{ {
return std::visit( return visit(
[&]<ValidIssueType TIss>(TIss const& issue) { [&](Issue const& issue) { return issue.native(); },
if constexpr (std::is_same_v<TIss, Issue>) [&](MPTIssue const&) { return false; });
return issue.native();
if constexpr (std::is_same_v<TIss, MPTIssue>)
return false;
},
issue_);
} }
bool bool
integral() const integral() const
{ {
return std::visit( return visit(
[&]<ValidIssueType TIss>(TIss const& issue) { [&](Issue const& issue) { return issue.native(); },
if constexpr (std::is_same_v<TIss, Issue>) [&](MPTIssue const&) { return true; });
return issue.native();
if constexpr (std::is_same_v<TIss, MPTIssue>)
return true;
},
issue_);
} }
friend constexpr bool friend constexpr bool
@@ -110,6 +136,10 @@ public:
friend constexpr bool friend constexpr bool
operator==(Currency const& lhs, Asset const& rhs); operator==(Currency const& lhs, Asset const& rhs);
// rhs is either badCurrency() or MPT issuer is 0
friend constexpr bool
operator==(BadAsset const& lhs, Asset const& rhs);
/** Return true if both assets refer to the same currency (regardless of /** Return true if both assets refer to the same currency (regardless of
* issuer) or MPT issuance. Otherwise return false. * issuer) or MPT issuance. Otherwise return false.
*/ */
@@ -117,6 +147,12 @@ public:
equalTokens(Asset const& lhs, Asset const& rhs); equalTokens(Asset const& lhs, Asset const& rhs);
}; };
template <ValidIssueType TIss>
constexpr bool is_issue_v = std::is_same_v<TIss, Issue>;
template <ValidIssueType TIss>
constexpr bool is_mptissue_v = std::is_same_v<TIss, MPTIssue>;
inline Json::Value inline Json::Value
to_json(Asset const& asset) to_json(Asset const& asset)
{ {
@@ -156,6 +192,29 @@ Asset::value() const
return issue_; return issue_;
} }
constexpr Asset::token_type
Asset::token() const
{
return visit(
[&](Issue const& issue) -> Asset::token_type { return issue.currency; },
[&](MPTIssue const& issue) -> Asset::token_type { return issue.getMptID(); });
}
constexpr Asset::AmtType
Asset::getAmountType() const
{
return visit(
[&](Issue const& issue) -> Asset::AmtType {
constexpr AmountType<XRPAmount> xrp;
constexpr AmountType<IOUAmount> iou;
return native() ? AmtType(xrp) : AmtType(iou);
},
[&](MPTIssue const& issue) -> Asset::AmtType {
constexpr AmountType<MPTAmount> mpt;
return AmtType(mpt);
});
}
constexpr bool constexpr bool
operator==(Asset const& lhs, Asset const& rhs) operator==(Asset const& lhs, Asset const& rhs)
{ {
@@ -177,7 +236,7 @@ operator<=>(Asset const& lhs, Asset const& rhs)
[]<ValidIssueType TLhs, ValidIssueType TRhs>(TLhs const& lhs_, TRhs const& rhs_) { []<ValidIssueType TLhs, ValidIssueType TRhs>(TLhs const& lhs_, TRhs const& rhs_) {
if constexpr (std::is_same_v<TLhs, TRhs>) if constexpr (std::is_same_v<TLhs, TRhs>)
return std::weak_ordering(lhs_ <=> rhs_); return std::weak_ordering(lhs_ <=> rhs_);
else if constexpr (std::is_same_v<TLhs, Issue> && std::is_same_v<TRhs, MPTIssue>) else if constexpr (is_issue_v<TLhs> && is_mptissue_v<TRhs>)
return std::weak_ordering::greater; return std::weak_ordering::greater;
else else
return std::weak_ordering::less; return std::weak_ordering::less;
@@ -189,7 +248,17 @@ operator<=>(Asset const& lhs, Asset const& rhs)
constexpr bool constexpr bool
operator==(Currency const& lhs, Asset const& rhs) operator==(Currency const& lhs, Asset const& rhs)
{ {
return rhs.holds<Issue>() && rhs.get<Issue>().currency == lhs; return rhs.visit(
[&](Issue const& issue) { return issue.currency == lhs; },
[](MPTIssue const& issue) { return false; });
}
constexpr bool
operator==(BadAsset const&, Asset const& rhs)
{
return rhs.visit(
[](Issue const& issue) -> bool { return badCurrency() == issue.currency; },
[](MPTIssue const& issue) -> bool { return issue.getIssuer() == xrpAccount(); });
} }
constexpr bool constexpr bool
@@ -223,4 +292,36 @@ validJSONAsset(Json::Value const& jv);
Asset Asset
assetFromJson(Json::Value const& jv); assetFromJson(Json::Value const& jv);
Json::Value
to_json(Asset const& asset);
inline bool
isConsistent(Asset const& asset)
{
return asset.visit(
[](Issue const& issue) { return isConsistent(issue); },
[](MPTIssue const&) { return true; });
}
inline bool
validAsset(Asset const& asset)
{
return asset.visit(
[](Issue const& issue) { return isConsistent(issue) && issue.currency != badCurrency(); },
[](MPTIssue const& issue) { return issue.getIssuer() != xrpAccount(); });
}
template <class Hasher>
void
hash_append(Hasher& h, Asset const& r)
{
using beast::hash_append;
r.visit(
[&](Issue const& issue) { hash_append(h, issue); },
[&](MPTIssue const& issue) { hash_append(h, issue); });
}
std::ostream&
operator<<(std::ostream& os, Asset const& x);
} // namespace xrpl } // namespace xrpl

View File

@@ -2,7 +2,7 @@
#include <xrpl/basics/CountedObject.h> #include <xrpl/basics/CountedObject.h>
#include <xrpl/basics/base_uint.h> #include <xrpl/basics/base_uint.h>
#include <xrpl/protocol/Issue.h> #include <xrpl/protocol/Asset.h>
#include <boost/utility/base_from_member.hpp> #include <boost/utility/base_from_member.hpp>
@@ -15,15 +15,15 @@ namespace xrpl {
class Book final : public CountedObject<Book> class Book final : public CountedObject<Book>
{ {
public: public:
Issue in; Asset in;
Issue out; Asset out;
std::optional<uint256> domain; std::optional<uint256> domain;
Book() Book()
{ {
} }
Book(Issue const& in_, Issue const& out_, std::optional<uint256> const& domain_) Book(Asset const& in_, Asset const& out_, std::optional<uint256> const& domain_)
: in(in_), out(out_), domain(domain_) : in(in_), out(out_), domain(domain_)
{ {
} }
@@ -112,16 +112,67 @@ public:
} }
}; };
template <>
struct hash<xrpl::MPTIssue> : private boost::base_from_member<std::hash<xrpl::MPTID>, 0>
{
private:
using id_hash_type = boost::base_from_member<std::hash<xrpl::MPTID>, 0>;
public:
explicit hash() = default;
using value_type = std::size_t;
using argument_type = xrpl::MPTIssue;
value_type
operator()(argument_type const& value) const
{
value_type const result(id_hash_type::member(value.getMptID()));
return result;
}
};
template <>
struct hash<xrpl::Asset>
{
private:
using value_type = std::size_t;
using argument_type = xrpl::Asset;
using issue_hasher = std::hash<xrpl::Issue>;
using mptissue_hasher = std::hash<xrpl::MPTIssue>;
issue_hasher m_issue_hasher;
mptissue_hasher m_mptissue_hasher;
public:
explicit hash() = default;
value_type
operator()(argument_type const& asset) const
{
return asset.visit(
[&](xrpl::Issue const& issue) {
value_type const result(m_issue_hasher(issue));
return result;
},
[&](xrpl::MPTIssue const& issue) {
value_type const result(m_mptissue_hasher(issue));
return result;
});
}
};
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template <> template <>
struct hash<xrpl::Book> struct hash<xrpl::Book>
{ {
private: private:
using issue_hasher = std::hash<xrpl::Issue>; using asset_hasher = std::hash<xrpl::Asset>;
using uint256_hasher = xrpl::uint256::hasher; using uint256_hasher = xrpl::uint256::hasher;
issue_hasher m_issue_hasher; asset_hasher m_asset_hasher;
uint256_hasher m_uint256_hasher; uint256_hasher m_uint256_hasher;
public: public:
@@ -133,8 +184,8 @@ public:
value_type value_type
operator()(argument_type const& value) const operator()(argument_type const& value) const
{ {
value_type result(m_issue_hasher(value.in)); value_type result(m_asset_hasher(value.in));
boost::hash_combine(result, m_issue_hasher(value.out)); boost::hash_combine(result, m_asset_hasher(value.out));
if (value.domain) if (value.domain)
boost::hash_combine(result, m_uint256_hasher(*value.domain)); boost::hash_combine(result, m_uint256_hasher(*value.domain));
@@ -159,6 +210,22 @@ struct hash<xrpl::Issue> : std::hash<xrpl::Issue>
// using Base::Base; // inherit ctors // using Base::Base; // inherit ctors
}; };
template <>
struct hash<xrpl::MPTIssue> : std::hash<xrpl::MPTIssue>
{
explicit hash() = default;
using Base = std::hash<xrpl::MPTIssue>;
};
template <>
struct hash<xrpl::Asset> : std::hash<xrpl::Asset>
{
explicit hash() = default;
using Base = std::hash<xrpl::Asset>;
};
template <> template <>
struct hash<xrpl::Book> : std::hash<xrpl::Book> struct hash<xrpl::Book> : std::hash<xrpl::Book>
{ {

View File

@@ -33,7 +33,7 @@ getFullVersionString();
X: 16 bits identifying the particular implementation X: 16 bits identifying the particular implementation
Y: 48 bits of data specific to the implementation Y: 48 bits of data specific to the implementation
The rippled-specific format (implementation ID is: 0x18 0x3B) is: The xrpld-specific format (implementation ID is: 0x18 0x3B) is:
00011000-00111011-MMMMMMMM-mmmmmmmm-pppppppp-TTNNNNNN-00000000-00000000 00011000-00111011-MMMMMMMM-mmmmmmmm-pppppppp-TTNNNNNN-00000000-00000000
@@ -55,23 +55,23 @@ encodeSoftwareVersion(std::string_view versionStr);
std::uint64_t std::uint64_t
getEncodedVersion(); getEncodedVersion();
/** Check if the encoded software version is a rippled software version. /** Check if the encoded software version is an xrpld software version.
@param version another node's encoded software version @param version another node's encoded software version
@return true if the version is a rippled software version, false otherwise @return true if the version is an xrpld software version, false otherwise
*/ */
bool bool
isRippledVersion(std::uint64_t version); isXrpldVersion(std::uint64_t version);
/** Check if the version is newer than the local node's rippled software /** Check if the version is newer than the local node's xrpld software
version. version.
@param version another node's encoded software version @param version another node's encoded software version
@return true if the version is newer than the local node's rippled software @return true if the version is newer than the local node's xrpld software
version, false otherwise. version, false otherwise.
@note This function only understands version numbers that are generated by @note This function only understands version numbers that are generated by
rippled. Please see the encodeSoftwareVersion() function for detail. xrpld. Please see the encodeSoftwareVersion() function for detail.
*/ */
bool bool
isNewerVersion(std::uint64_t version); isNewerVersion(std::uint64_t version);

View File

@@ -0,0 +1,86 @@
#pragma once
#include <xrpl/protocol/UintTypes.h>
#include <type_traits>
namespace xrpl {
class STAmount;
class Asset;
class Issue;
class MPTIssue;
class IOUAmount;
class XRPAmount;
class MPTAmount;
template <typename A>
concept StepAmount =
std::is_same_v<A, XRPAmount> || std::is_same_v<A, IOUAmount> || std::is_same_v<A, MPTAmount>;
template <typename TIss>
concept ValidIssueType = std::is_same_v<TIss, Issue> || std::is_same_v<TIss, MPTIssue>;
template <typename A>
concept AssetType = std::is_convertible_v<A, Asset> || std::is_convertible_v<A, Issue> ||
std::is_convertible_v<A, MPTIssue> || std::is_convertible_v<A, MPTID>;
template <typename T>
concept ValidPathAsset = (std::is_same_v<T, Currency> || std::is_same_v<T, MPTID>);
template <class TTakerPays, class TTakerGets>
concept ValidTaker =
((std::is_same_v<TTakerPays, IOUAmount> || std::is_same_v<TTakerPays, XRPAmount> ||
std::is_same_v<TTakerPays, MPTAmount>) &&
(std::is_same_v<TTakerGets, IOUAmount> || std::is_same_v<TTakerGets, XRPAmount> ||
std::is_same_v<TTakerGets, MPTAmount>) &&
(!std::is_same_v<TTakerPays, XRPAmount> || !std::is_same_v<TTakerGets, XRPAmount>));
namespace detail {
// This template combines multiple callable objects (lambdas) into a single
// object that std::visit can use for overload resolution.
template <typename... Ts>
struct CombineVisitors : Ts...
{
// Bring all operator() overloads from base classes into this scope.
// It's the mechanism that makes the CombineVisitors struct function
// as a single callable object with multiple overloads.
using Ts::operator()...;
// Perfect forwarding constructor to correctly initialize the base class
// lambdas
constexpr CombineVisitors(Ts&&... ts) : Ts(std::forward<Ts>(ts))...
{
}
};
// This function forces function template argument deduction, which is more
// robust than class template argument deduction (CTAD) via the deduction guide.
template <typename... Ts>
constexpr CombineVisitors<std::decay_t<Ts>...>
make_combine_visitors(Ts&&... ts)
{
// std::decay_t<Ts> is used to remove references/constness from the lambda
// types before they are passed as template arguments to the CombineVisitors
// struct.
return CombineVisitors<std::decay_t<Ts>...>{std::forward<Ts>(ts)...};
}
// This function takes ANY variant and ANY number of visitors, and performs the
// visit. It is the reusable core logic.
template <typename Variant, typename... Visitors>
constexpr auto
visit(Variant&& v, Visitors&&... visitors) -> decltype(auto)
{
// Use the function template helper instead of raw CTAD.
auto visitor_set = make_combine_visitors(std::forward<Visitors>(visitors)...);
// Delegate to std::visit, perfectly forwarding the variant and the visitor
// set.
return std::visit(visitor_set, std::forward<Variant>(v));
}
} // namespace detail
} // namespace xrpl

View File

@@ -153,7 +153,7 @@ enum warning_code_i {
warnRPC_AMENDMENT_BLOCKED = 1002, warnRPC_AMENDMENT_BLOCKED = 1002,
warnRPC_EXPIRED_VALIDATOR_LIST = 1003, warnRPC_EXPIRED_VALIDATOR_LIST = 1003,
// unused = 1004 // unused = 1004
warnRPC_FIELDS_DEPRECATED = 2004, // rippled needs to maintain warnRPC_FIELDS_DEPRECATED = 2004, // xrpld needs to maintain
// compatibility with Clio on this code. // compatibility with Clio on this code.
}; };

View File

@@ -37,10 +37,10 @@
* 5) If a supported feature (`Supported::yes`) was _ever_ in a released * 5) If a supported feature (`Supported::yes`) was _ever_ in a released
* version, it can never be changed back to `Supported::no`, because * version, it can never be changed back to `Supported::no`, because
* it _may_ still become enabled at any time. This would cause newer * it _may_ still become enabled at any time. This would cause newer
* versions of `rippled` to become amendment blocked. * versions of `xrpld` to become amendment blocked.
* Instead, to prevent newer versions from voting on the feature, use * Instead, to prevent newer versions from voting on the feature, use
* `VoteBehavior::Obsolete`. Obsolete features can not be voted for * `VoteBehavior::Obsolete`. Obsolete features can not be voted for
* by any versions of `rippled` built with that setting, but will still * by any versions of `xrpld` built with that setting, but will still
* work correctly if they get enabled. If a feature remains obsolete * work correctly if they get enabled. If a feature remains obsolete
* for long enough that _all_ clients that could vote for it are * for long enough that _all_ clients that could vote for it are
* amendment blocked, the feature can be removed from the code * amendment blocked, the feature can be removed from the code

View File

@@ -187,7 +187,8 @@ enum LedgerEntryType : std::uint16_t {
\ \
LEDGER_OBJECT(MPToken, \ LEDGER_OBJECT(MPToken, \
LSF_FLAG2(lsfMPTLocked, 0x00000001) \ LSF_FLAG2(lsfMPTLocked, 0x00000001) \
LSF_FLAG(lsfMPTAuthorized, 0x00000002)) \ LSF_FLAG(lsfMPTAuthorized, 0x00000002) \
LSF_FLAG(lsfMPTAMM, 0x00000004)) \
\ \
LEDGER_OBJECT(Credential, \ LEDGER_OBJECT(Credential, \
LSF_FLAG(lsfAccepted, 0x00010000)) \ LSF_FLAG(lsfAccepted, 0x00010000)) \

View File

@@ -22,11 +22,12 @@ public:
using value_type = std::int64_t; using value_type = std::int64_t;
protected: protected:
value_type value_; value_type value_{};
public: public:
MPTAmount() = default; MPTAmount() = default;
constexpr MPTAmount(MPTAmount const& other) = default; constexpr MPTAmount(MPTAmount const& other) = default;
constexpr MPTAmount(beast::Zero);
constexpr MPTAmount& constexpr MPTAmount&
operator=(MPTAmount const& other) = default; operator=(MPTAmount const& other) = default;
@@ -85,6 +86,11 @@ constexpr MPTAmount::MPTAmount(value_type value) : value_(value)
{ {
} }
constexpr MPTAmount::MPTAmount(beast::Zero)
{
*this = beast::zero;
}
constexpr MPTAmount& constexpr MPTAmount&
MPTAmount::operator=(beast::Zero) MPTAmount::operator=(beast::Zero)
{ {
@@ -116,6 +122,14 @@ MPTAmount::value() const
return value_; return value_;
} }
// Output MPTAmount as just the value.
template <class Char, class Traits>
std::basic_ostream<Char, Traits>&
operator<<(std::basic_ostream<Char, Traits>& os, MPTAmount const& q)
{
return os << q.value();
}
inline std::string inline std::string
to_string(MPTAmount const& amount) to_string(MPTAmount const& amount)
{ {

View File

@@ -17,7 +17,14 @@ private:
public: public:
MPTIssue() = default; MPTIssue() = default;
explicit MPTIssue(MPTID const& issuanceID); MPTIssue(MPTID const& issuanceID);
MPTIssue(std::uint32_t sequence, AccountID const& account);
operator MPTID const&() const
{
return mptID_;
}
AccountID const& AccountID const&
getIssuer() const; getIssuer() const;
@@ -73,6 +80,47 @@ isXRP(MPTID const&)
return false; return false;
} }
inline AccountID
getMPTIssuer(MPTID const& mptid)
{
static_assert(sizeof(MPTID) == (sizeof(std::uint32_t) + sizeof(AccountID)));
// Extract the 20 bytes for the AccountID
std::array<std::uint8_t, sizeof(AccountID)> bytes{};
std::copy_n(mptid.data() + sizeof(std::uint32_t), sizeof(AccountID), bytes.begin());
// bit_cast is a "magic" compiler intrinsic that is
// usually optimized away to nothing in the final assembly.
return std::bit_cast<AccountID>(bytes);
}
// Disallow temporary
inline AccountID const&
getMPTIssuer(MPTID const&&) = delete;
inline AccountID const&
getMPTIssuer(MPTID&&) = delete;
inline MPTID
noMPT()
{
static MPTIssue const mpt{0, noAccount()};
return mpt.getMptID();
}
inline MPTID
badMPT()
{
static MPTIssue const mpt{0, xrpAccount()};
return mpt.getMptID();
}
template <class Hasher>
void
hash_append(Hasher& h, MPTIssue const& r)
{
using beast::hash_append;
hash_append(h, r.getMptID());
}
Json::Value Json::Value
to_json(MPTIssue const& mptIssue); to_json(MPTIssue const& mptIssue);
@@ -82,4 +130,17 @@ to_string(MPTIssue const& mptIssue);
MPTIssue MPTIssue
mptIssueFromJson(Json::Value const& jv); mptIssueFromJson(Json::Value const& jv);
std::ostream&
operator<<(std::ostream& os, MPTIssue const& x);
} // namespace xrpl } // namespace xrpl
namespace std {
template <>
struct hash<xrpl::MPTID> : xrpl::MPTID::hasher
{
explicit hash() = default;
};
} // namespace std

View File

@@ -0,0 +1,130 @@
#pragma once
#include <xrpl/protocol/Asset.h>
#include <xrpl/protocol/Concepts.h>
namespace xrpl {
/* Represent STPathElement's asset, which can be Currency or MPTID.
*/
class PathAsset
{
private:
std::variant<Currency, MPTID> easset_;
public:
PathAsset() = default;
// Enables comparing Asset and PathAsset
PathAsset(Asset const& asset);
PathAsset(Currency const& currency) : easset_(currency)
{
}
PathAsset(MPTID const& mpt) : easset_(mpt)
{
}
template <ValidPathAsset T>
constexpr bool
holds() const;
constexpr bool
isXRP() const;
template <ValidPathAsset T>
T const&
get() const;
constexpr std::variant<Currency, MPTID> const&
value() const;
// Custom, generic visit implementation
template <typename... Visitors>
constexpr auto
visit(Visitors&&... visitors) const -> decltype(auto)
{
// Simple delegation to the reusable utility, passing the internal
// variant data.
return detail::visit(easset_, std::forward<Visitors>(visitors)...);
}
friend constexpr bool
operator==(PathAsset const& lhs, PathAsset const& rhs);
};
template <ValidPathAsset PA>
constexpr bool is_currency_v = std::is_same_v<PA, Currency>;
template <ValidPathAsset PA>
constexpr bool is_mptid_v = std::is_same_v<PA, MPTID>;
inline PathAsset::PathAsset(Asset const& asset)
{
asset.visit(
[&](Issue const& issue) { easset_ = issue.currency; },
[&](MPTIssue const& issue) { easset_ = issue.getMptID(); });
}
template <ValidPathAsset T>
constexpr bool
PathAsset::holds() const
{
return std::holds_alternative<T>(easset_);
}
template <ValidPathAsset T>
T const&
PathAsset::get() const
{
if (!holds<T>())
Throw<std::runtime_error>("PathAsset doesn't hold requested asset.");
return std::get<T>(easset_);
}
constexpr std::variant<Currency, MPTID> const&
PathAsset::value() const
{
return easset_;
}
constexpr bool
PathAsset::isXRP() const
{
return visit(
[&](Currency const& currency) { return xrpl::isXRP(currency); },
[](MPTID const&) { return false; });
}
constexpr bool
operator==(PathAsset const& lhs, PathAsset const& rhs)
{
return std::visit(
[]<ValidPathAsset TLhs, ValidPathAsset TRhs>(TLhs const& lhs_, TRhs const& rhs_) {
if constexpr (std::is_same_v<TLhs, TRhs>)
return lhs_ == rhs_;
else
return false;
},
lhs.value(),
rhs.value());
}
template <typename Hasher>
void
hash_append(Hasher& h, PathAsset const& pathAsset)
{
std::visit([&]<ValidPathAsset T>(T const& e) { hash_append(h, e); }, pathAsset.value());
}
inline bool
isXRP(PathAsset const& asset)
{
return asset.isXRP();
}
std::string
to_string(PathAsset const& asset);
std::ostream&
operator<<(std::ostream& os, PathAsset const& x);
} // namespace xrpl

View File

@@ -21,7 +21,7 @@ namespace xrpl {
Public keys are used in the public-key cryptography Public keys are used in the public-key cryptography
system used to verify signatures attached to messages. system used to verify signatures attached to messages.
The format of the public key is Ripple specific, The format of the public key is XRPL specific,
information needed to determine the cryptosystem information needed to determine the cryptosystem
parameters used is stored inside the key. parameters used is stored inside the key.

View File

@@ -78,7 +78,7 @@ operator!=(TAmounts<In, Out> const& lhs, TAmounts<In, Out> const& rhs) noexcept
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Ripple specific constant used for parsing qualities and other things // XRPL specific constant used for parsing qualities and other things
#define QUALITY_ONE 1'000'000'000 #define QUALITY_ONE 1'000'000'000
/** Represents the logical ratio of output currency to input currency. /** Represents the logical ratio of output currency to input currency.

View File

@@ -22,7 +22,7 @@ optional fields easier to read:
- The operation `x[~sfFoo]` means "return the value of 'Foo' - The operation `x[~sfFoo]` means "return the value of 'Foo'
if it exists, or nothing if it doesn't." This usage of the if it exists, or nothing if it doesn't." This usage of the
tilde/bitwise NOT operator is not standard outside of the tilde/bitwise NOT operator is not standard outside of the
`rippled` codebase. `xrpld` codebase.
- As a consequence of this, `x[~sfFoo] = y[~sfFoo]` - As a consequence of this, `x[~sfFoo] = y[~sfFoo]`
assigns the value of Foo from y to x, including omitting assigns the value of Foo from y to x, including omitting
Foo from x if it doesn't exist in y. Foo from x if it doesn't exist in y.
@@ -33,7 +33,7 @@ or may not hold a value. For things not guaranteed to exist,
you use `x[~sfFoo]` because you want such a container. It you use `x[~sfFoo]` because you want such a container. It
avoids having to look something up twice, once just to see if avoids having to look something up twice, once just to see if
it exists and a second time to get/set its value. it exists and a second time to get/set its value.
([Real example](https://github.com/ripple/rippled/blob/35f4698aed5dce02f771b34cfbb690495cb5efcc/src/ripple/app/tx/impl/PayChan.cpp#L229-L236)) ([Real example](https://github.com/XRPLF/rippled/blob/35f4698aed5dce02f771b34cfbb690495cb5efcc/src/ripple/app/tx/impl/PayChan.cpp#L229-L236))
The source of this "type magic" is in The source of this "type magic" is in
[SField.h](./SField.h#L296-L302). [SField.h](./SField.h#L296-L302).

View File

@@ -13,7 +13,7 @@ class STAccount final : public STBase, public CountedObject<STAccount>
private: private:
// The original implementation of STAccount kept the value in an STBlob. // The original implementation of STAccount kept the value in an STBlob.
// But an STAccount is always 160 bits, so we can store it with less // But an STAccount is always 160 bits, so we can store it with less
// overhead in a xrpl::uint160. However, so the serialized format of the // overhead in an xrpl::uint160. However, so the serialized format of the
// STAccount stays unchanged, we serialize and deserialize like an STBlob. // STAccount stays unchanged, we serialize and deserialize like an STBlob.
AccountID value_; AccountID value_;
bool default_; bool default_;

View File

@@ -164,12 +164,9 @@ public:
constexpr TIss const& constexpr TIss const&
get() const; get() const;
Issue const& template <ValidIssueType TIss>
issue() const; TIss&
get();
// These three are deprecated
Currency const&
getCurrency() const;
AccountID const& AccountID const&
getIssuer() const; getIssuer() const;
@@ -225,9 +222,6 @@ public:
void void
clear(Asset const& asset); clear(Asset const& asset);
void
setIssuer(AccountID const& uIssuer);
/** Set the Issue for this amount. */ /** Set the Issue for this amount. */
void void
setIssue(Asset const& asset); setIssue(Asset const& asset);
@@ -466,16 +460,11 @@ STAmount::get() const
return mAsset.get<TIss>(); return mAsset.get<TIss>();
} }
inline Issue const& template <ValidIssueType TIss>
STAmount::issue() const TIss&
STAmount::get()
{ {
return get<Issue>(); return mAsset.get<TIss>();
}
inline Currency const&
STAmount::getCurrency() const
{
return mAsset.get<Issue>().currency;
} }
inline AccountID const& inline AccountID const&
@@ -505,11 +494,13 @@ operator bool() const noexcept
inline STAmount:: inline STAmount::
operator Number() const operator Number() const
{ {
if (native()) return asset().visit(
return xrp(); [&](Issue const& issue) -> Number {
if (mAsset.holds<MPTIssue>()) if (issue.native())
return mpt(); return xrp();
return iou(); return iou();
},
[&](MPTIssue const&) -> Number { return mpt(); });
} }
inline STAmount& inline STAmount&
@@ -568,12 +559,6 @@ STAmount::clear(Asset const& asset)
clear(); clear();
} }
inline void
STAmount::setIssuer(AccountID const& uIssuer)
{
mAsset.get<Issue>().account = uIssuer;
}
inline STAmount const& inline STAmount const&
STAmount::value() const noexcept STAmount::value() const noexcept
{ {

View File

@@ -349,6 +349,8 @@ public:
void void
setFieldH128(SField const& field, uint128 const&); setFieldH128(SField const& field, uint128 const&);
void void
setFieldH192(SField const& field, uint192 const&);
void
setFieldH256(SField const& field, uint256 const&); setFieldH256(SField const& field, uint256 const&);
void void
setFieldI32(SField const& field, std::int32_t); setFieldI32(SField const& field, std::int32_t);

View File

@@ -3,6 +3,8 @@
#include <xrpl/basics/CountedObject.h> #include <xrpl/basics/CountedObject.h>
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/json/json_value.h> #include <xrpl/json/json_value.h>
#include <xrpl/protocol/Asset.h>
#include <xrpl/protocol/PathAsset.h>
#include <xrpl/protocol/SField.h> #include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STBase.h> #include <xrpl/protocol/STBase.h>
#include <xrpl/protocol/UintTypes.h> #include <xrpl/protocol/UintTypes.h>
@@ -16,7 +18,7 @@ class STPathElement final : public CountedObject<STPathElement>
{ {
unsigned int mType; unsigned int mType;
AccountID mAccountID; AccountID mAccountID;
Currency mCurrencyID; PathAsset mAssetID;
AccountID mIssuerID; AccountID mIssuerID;
bool is_offer_; bool is_offer_;
@@ -28,8 +30,10 @@ public:
typeAccount = 0x01, // Rippling through an account (vs taking an offer). typeAccount = 0x01, // Rippling through an account (vs taking an offer).
typeCurrency = 0x10, // Currency follows. typeCurrency = 0x10, // Currency follows.
typeIssuer = 0x20, // Issuer follows. typeIssuer = 0x20, // Issuer follows.
typeMPT = 0x40, // MPT follows.
typeBoundary = 0xFF, // Boundary between alternate paths. typeBoundary = 0xFF, // Boundary between alternate paths.
typeAll = typeAccount | typeCurrency | typeIssuer, typeAsset = typeCurrency | typeMPT,
typeAll = typeAccount | typeCurrency | typeIssuer | typeMPT,
// Combination of all types. // Combination of all types.
}; };
@@ -40,19 +44,19 @@ public:
STPathElement( STPathElement(
std::optional<AccountID> const& account, std::optional<AccountID> const& account,
std::optional<Currency> const& currency, std::optional<PathAsset> const& asset,
std::optional<AccountID> const& issuer); std::optional<AccountID> const& issuer);
STPathElement( STPathElement(
AccountID const& account, AccountID const& account,
Currency const& currency, PathAsset const& asset,
AccountID const& issuer, AccountID const& issuer,
bool forceCurrency = false); bool forceAsset = false);
STPathElement( STPathElement(
unsigned int uType, unsigned int uType,
AccountID const& account, AccountID const& account,
Currency const& currency, PathAsset const& asset,
AccountID const& issuer); AccountID const& issuer);
auto auto
@@ -70,6 +74,12 @@ public:
bool bool
hasCurrency() const; hasCurrency() const;
bool
hasMPT() const;
bool
hasAsset() const;
bool bool
isNone() const; isNone() const;
@@ -78,12 +88,21 @@ public:
AccountID const& AccountID const&
getAccountID() const; getAccountID() const;
PathAsset const&
getPathAsset() const;
Currency const& Currency const&
getCurrency() const; getCurrency() const;
MPTID const&
getMPTID() const;
AccountID const& AccountID const&
getIssuerID() const; getIssuerID() const;
bool
isType(Type const& pe) const;
bool bool
operator==(STPathElement const& t) const; operator==(STPathElement const& t) const;
@@ -118,7 +137,7 @@ public:
emplace_back(Args&&... args); emplace_back(Args&&... args);
bool bool
hasSeen(AccountID const& account, Currency const& currency, AccountID const& issuer) const; hasSeen(AccountID const& account, PathAsset const& asset, AccountID const& issuer) const;
Json::Value getJson(JsonOptions) const; Json::Value getJson(JsonOptions) const;
@@ -221,7 +240,7 @@ inline STPathElement::STPathElement() : mType(typeNone), is_offer_(true)
inline STPathElement::STPathElement( inline STPathElement::STPathElement(
std::optional<AccountID> const& account, std::optional<AccountID> const& account,
std::optional<Currency> const& currency, std::optional<PathAsset> const& asset,
std::optional<AccountID> const& issuer) std::optional<AccountID> const& issuer)
: mType(typeNone) : mType(typeNone)
{ {
@@ -238,10 +257,10 @@ inline STPathElement::STPathElement(
mAccountID != noAccount(), "xrpl::STPathElement::STPathElement : account is set"); mAccountID != noAccount(), "xrpl::STPathElement::STPathElement : account is set");
} }
if (currency) if (asset)
{ {
mCurrencyID = *currency; mAssetID = *asset;
mType |= typeCurrency; mType |= mAssetID.holds<Currency>() ? typeCurrency : typeMPT;
} }
if (issuer) if (issuer)
@@ -256,20 +275,20 @@ inline STPathElement::STPathElement(
inline STPathElement::STPathElement( inline STPathElement::STPathElement(
AccountID const& account, AccountID const& account,
Currency const& currency, PathAsset const& asset,
AccountID const& issuer, AccountID const& issuer,
bool forceCurrency) bool forceAsset)
: mType(typeNone) : mType(typeNone)
, mAccountID(account) , mAccountID(account)
, mCurrencyID(currency) , mAssetID(asset)
, mIssuerID(issuer) , mIssuerID(issuer)
, is_offer_(isXRP(mAccountID)) , is_offer_(isXRP(mAccountID))
{ {
if (!is_offer_) if (!is_offer_)
mType |= typeAccount; mType |= typeAccount;
if (forceCurrency || !isXRP(currency)) if (forceAsset || !isXRP(mAssetID))
mType |= typeCurrency; mType |= asset.holds<Currency>() ? typeCurrency : typeMPT;
if (!isXRP(issuer)) if (!isXRP(issuer))
mType |= typeIssuer; mType |= typeIssuer;
@@ -280,14 +299,19 @@ inline STPathElement::STPathElement(
inline STPathElement::STPathElement( inline STPathElement::STPathElement(
unsigned int uType, unsigned int uType,
AccountID const& account, AccountID const& account,
Currency const& currency, PathAsset const& asset,
AccountID const& issuer) AccountID const& issuer)
: mType(uType) : mType(uType)
, mAccountID(account) , mAccountID(account)
, mCurrencyID(currency) , mAssetID(asset)
, mIssuerID(issuer) , mIssuerID(issuer)
, is_offer_(isXRP(mAccountID)) , is_offer_(isXRP(mAccountID))
{ {
// uType could be assetType; i.e. either Currency or MPTID.
// Get the actual type.
mAssetID.visit(
[&](Currency const&) { mType = mType & (~Type::typeMPT); },
[&](MPTID const&) { mType = mType & (~Type::typeCurrency); });
hash_value_ = get_hash(*this); hash_value_ = get_hash(*this);
} }
@@ -309,16 +333,34 @@ STPathElement::isAccount() const
return !isOffer(); return !isOffer();
} }
inline bool
STPathElement::isType(Type const& pe) const
{
return (mType & pe) != 0u;
}
inline bool inline bool
STPathElement::hasIssuer() const STPathElement::hasIssuer() const
{ {
return getNodeType() & STPathElement::typeIssuer; return isType(STPathElement::typeIssuer);
} }
inline bool inline bool
STPathElement::hasCurrency() const STPathElement::hasCurrency() const
{ {
return getNodeType() & STPathElement::typeCurrency; return isType(STPathElement::typeCurrency);
}
inline bool
STPathElement::hasMPT() const
{
return isType(STPathElement::typeMPT);
}
inline bool
STPathElement::hasAsset() const
{
return isType(STPathElement::typeAsset);
} }
inline bool inline bool
@@ -335,10 +377,22 @@ STPathElement::getAccountID() const
return mAccountID; return mAccountID;
} }
inline PathAsset const&
STPathElement::getPathAsset() const
{
return mAssetID;
}
inline Currency const& inline Currency const&
STPathElement::getCurrency() const STPathElement::getCurrency() const
{ {
return mCurrencyID; return mAssetID.get<Currency>();
}
inline MPTID const&
STPathElement::getMPTID() const
{
return mAssetID.get<MPTID>();
} }
inline AccountID const& inline AccountID const&
@@ -351,7 +405,7 @@ inline bool
STPathElement::operator==(STPathElement const& t) const STPathElement::operator==(STPathElement const& t) const
{ {
return (mType & typeAccount) == (t.mType & typeAccount) && hash_value_ == t.hash_value_ && return (mType & typeAccount) == (t.mType & typeAccount) && hash_value_ == t.hash_value_ &&
mAccountID == t.mAccountID && mCurrencyID == t.mCurrencyID && mIssuerID == t.mIssuerID; mAccountID == t.mAccountID && mAssetID == t.mAssetID && mIssuerID == t.mIssuerID;
} }
inline bool inline bool

View File

@@ -118,7 +118,7 @@ derivePublicKey(KeyType type, SecretKey const& sk);
/** Generate a key pair deterministically. /** Generate a key pair deterministically.
This algorithm is specific to Ripple: This algorithm is specific to the XRPL:
For secp256k1 key pairs, the seed is converted For secp256k1 key pairs, the seed is converted
to a Generator and used to compute the key pair to a Generator and used to compute the key pair

View File

@@ -80,7 +80,7 @@ randomSeed();
/** Generate a seed deterministically. /** Generate a seed deterministically.
The algorithm is specific to Ripple: The algorithm is specific to the XRPL:
The seed is calculated as the first 128 bits The seed is calculated as the first 128 bits
of the SHA512-Half of the string text excluding of the SHA512-Half of the string text excluding

View File

@@ -121,6 +121,7 @@ enum TEMcodes : TERUnderlyingType {
temARRAY_TOO_LARGE, temARRAY_TOO_LARGE,
temBAD_TRANSFER_FEE, temBAD_TRANSFER_FEE,
temINVALID_INNER_BATCH, temINVALID_INNER_BATCH,
temBAD_MPT,
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -208,6 +209,7 @@ enum TERcodes : TERUnderlyingType {
terADDRESS_COLLISION, // Failed to allocate AccountID when trying to terADDRESS_COLLISION, // Failed to allocate AccountID when trying to
// create a pseudo-account // create a pseudo-account
terNO_DELEGATE_PERMISSION, // Delegate does not have permission terNO_DELEGATE_PERMISSION, // Delegate does not have permission
terLOCKED, // MPT is locked
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -342,10 +344,6 @@ enum TECcodes : TERUnderlyingType {
tecLIMIT_EXCEEDED = 195, tecLIMIT_EXCEEDED = 195,
tecPSEUDO_ACCOUNT = 196, tecPSEUDO_ACCOUNT = 196,
tecPRECISION_LOSS = 197, tecPRECISION_LOSS = 197,
// DEPRECATED: This error code tecNO_DELEGATE_PERMISSION is reserved for
// backward compatibility with historical data on non-prod networks, can be
// reclaimed after those networks reset.
tecNO_DELEGATE_PERMISSION = 198,
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@@ -21,7 +21,7 @@ namespace unit {
struct dropTag; struct dropTag;
/** "fee levels" are used by the transaction queue to compare the relative /** "fee levels" are used by the transaction queue to compare the relative
cost of transactions that require different levels of effort to process. cost of transactions that require different levels of effort to process.
See also: src/ripple/app/misc/FeeEscalation.md#fee-level */ See also: src/xrpld/app/misc/FeeEscalation.md#fee-level */
struct feelevelTag; struct feelevelTag;
/** unitless values are plain scalars wrapped in a ValueUnit. They are /** unitless values are plain scalars wrapped in a ValueUnit. They are
used for calculations in this header. */ used for calculations in this header. */

View File

@@ -15,6 +15,7 @@
// Add new amendments to the top of this list. // Add new amendments to the top of this list.
// Keep it sorted in reverse chronological order. // Keep it sorted in reverse chronological order.
XRPL_FEATURE(MPTokensV2, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (Security3_1_3, Supported::no, VoteBehavior::DefaultNo) XRPL_FIX (Security3_1_3, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (PermissionedDomainInvariant, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (PermissionedDomainInvariant, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (ExpiredNFTokenOfferRemoval, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (ExpiredNFTokenOfferRemoval, Supported::yes, VoteBehavior::DefaultNo)

View File

@@ -161,8 +161,10 @@ LEDGER_ENTRY(ltDIR_NODE, 0x0064, DirectoryNode, directory, ({
{sfOwner, soeOPTIONAL}, // for owner directories {sfOwner, soeOPTIONAL}, // for owner directories
{sfTakerPaysCurrency, soeOPTIONAL}, // order book directories {sfTakerPaysCurrency, soeOPTIONAL}, // order book directories
{sfTakerPaysIssuer, soeOPTIONAL}, // order book directories {sfTakerPaysIssuer, soeOPTIONAL}, // order book directories
{sfTakerPaysMPT, soeOPTIONAL}, // order book directories
{sfTakerGetsCurrency, soeOPTIONAL}, // order book directories {sfTakerGetsCurrency, soeOPTIONAL}, // order book directories
{sfTakerGetsIssuer, soeOPTIONAL}, // order book directories {sfTakerGetsIssuer, soeOPTIONAL}, // order book directories
{sfTakerGetsMPT, soeOPTIONAL}, // order book directories
{sfExchangeRate, soeOPTIONAL}, // order book directories {sfExchangeRate, soeOPTIONAL}, // order book directories
{sfIndexes, soeREQUIRED}, {sfIndexes, soeREQUIRED},
{sfRootIndex, soeREQUIRED}, {sfRootIndex, soeREQUIRED},
@@ -578,7 +580,7 @@ LEDGER_ENTRY(ltLOAN, 0x0089, Loan, loan, ({
// The unrounded true total value of the loan. // The unrounded true total value of the loan.
// //
// - TrueTotalPrincipalOutstanding can be computed using the algorithm // - TrueTotalPrincipalOutstanding can be computed using the algorithm
// in the ripple::detail::loanPrincipalFromPeriodicPayment function. // in the xrpl::detail::loanPrincipalFromPeriodicPayment function.
// //
// - TrueTotalInterestOutstanding = TrueTotalLoanValue - // - TrueTotalInterestOutstanding = TrueTotalLoanValue -
// TrueTotalPrincipalOutstanding // TrueTotalPrincipalOutstanding

View File

@@ -159,6 +159,8 @@ TYPED_SFIELD(sfTakerGetsIssuer, UINT160, 4)
// 192-bit (common) // 192-bit (common)
TYPED_SFIELD(sfMPTokenIssuanceID, UINT192, 1) TYPED_SFIELD(sfMPTokenIssuanceID, UINT192, 1)
TYPED_SFIELD(sfShareMPTID, UINT192, 2) TYPED_SFIELD(sfShareMPTID, UINT192, 2)
TYPED_SFIELD(sfTakerPaysMPT, UINT192, 3)
TYPED_SFIELD(sfTakerGetsMPT, UINT192, 4)
// 256-bit (common) // 256-bit (common)
TYPED_SFIELD(sfLedgerHash, UINT256, 1) TYPED_SFIELD(sfLedgerHash, UINT256, 1)

View File

@@ -27,7 +27,7 @@
TRANSACTION(ttPAYMENT, 0, Payment, TRANSACTION(ttPAYMENT, 0, Payment,
Delegation::delegable, Delegation::delegable,
uint256{}, uint256{},
createAcct, createAcct | mayCreateMPT,
({ ({
{sfDestination, soeREQUIRED}, {sfDestination, soeREQUIRED},
{sfAmount, soeREQUIRED, soeMPTSupported}, {sfAmount, soeREQUIRED, soeMPTSupported},
@@ -129,10 +129,10 @@ TRANSACTION(ttREGULAR_KEY_SET, 5, SetRegularKey,
TRANSACTION(ttOFFER_CREATE, 7, OfferCreate, TRANSACTION(ttOFFER_CREATE, 7, OfferCreate,
Delegation::delegable, Delegation::delegable,
uint256{}, uint256{},
noPriv, mayCreateMPT,
({ ({
{sfTakerPays, soeREQUIRED}, {sfTakerPays, soeREQUIRED, soeMPTSupported},
{sfTakerGets, soeREQUIRED}, {sfTakerGets, soeREQUIRED, soeMPTSupported},
{sfExpiration, soeOPTIONAL}, {sfExpiration, soeOPTIONAL},
{sfOfferSequence, soeOPTIONAL}, {sfOfferSequence, soeOPTIONAL},
{sfDomainID, soeOPTIONAL}, {sfDomainID, soeOPTIONAL},
@@ -239,7 +239,7 @@ TRANSACTION(ttCHECK_CREATE, 16, CheckCreate,
noPriv, noPriv,
({ ({
{sfDestination, soeREQUIRED}, {sfDestination, soeREQUIRED},
{sfSendMax, soeREQUIRED}, {sfSendMax, soeREQUIRED, soeMPTSupported},
{sfExpiration, soeOPTIONAL}, {sfExpiration, soeOPTIONAL},
{sfDestinationTag, soeOPTIONAL}, {sfDestinationTag, soeOPTIONAL},
{sfInvoiceID, soeOPTIONAL}, {sfInvoiceID, soeOPTIONAL},
@@ -252,11 +252,11 @@ TRANSACTION(ttCHECK_CREATE, 16, CheckCreate,
TRANSACTION(ttCHECK_CASH, 17, CheckCash, TRANSACTION(ttCHECK_CASH, 17, CheckCash,
Delegation::delegable, Delegation::delegable,
uint256{}, uint256{},
noPriv, mayCreateMPT,
({ ({
{sfCheckID, soeREQUIRED}, {sfCheckID, soeREQUIRED},
{sfAmount, soeOPTIONAL}, {sfAmount, soeOPTIONAL, soeMPTSupported},
{sfDeliverMin, soeOPTIONAL}, {sfDeliverMin, soeOPTIONAL, soeMPTSupported},
})) }))
/** This transaction type cancels an existing check. */ /** This transaction type cancels an existing check. */
@@ -409,12 +409,12 @@ TRANSACTION(ttCLAWBACK, 30, Clawback,
TRANSACTION(ttAMM_CLAWBACK, 31, AMMClawback, TRANSACTION(ttAMM_CLAWBACK, 31, AMMClawback,
Delegation::delegable, Delegation::delegable,
featureAMMClawback, featureAMMClawback,
mayDeleteAcct | overrideFreeze, mayDeleteAcct | overrideFreeze | mayAuthorizeMPT,
({ ({
{sfHolder, soeREQUIRED}, {sfHolder, soeREQUIRED},
{sfAsset, soeREQUIRED}, {sfAsset, soeREQUIRED, soeMPTSupported},
{sfAsset2, soeREQUIRED}, {sfAsset2, soeREQUIRED, soeMPTSupported},
{sfAmount, soeOPTIONAL}, {sfAmount, soeOPTIONAL, soeMPTSupported},
})) }))
/** This transaction type creates an AMM instance */ /** This transaction type creates an AMM instance */
@@ -424,10 +424,10 @@ TRANSACTION(ttAMM_CLAWBACK, 31, AMMClawback,
TRANSACTION(ttAMM_CREATE, 35, AMMCreate, TRANSACTION(ttAMM_CREATE, 35, AMMCreate,
Delegation::delegable, Delegation::delegable,
featureAMM, featureAMM,
createPseudoAcct, createPseudoAcct | mayCreateMPT,
({ ({
{sfAmount, soeREQUIRED}, {sfAmount, soeREQUIRED, soeMPTSupported},
{sfAmount2, soeREQUIRED}, {sfAmount2, soeREQUIRED, soeMPTSupported},
{sfTradingFee, soeREQUIRED}, {sfTradingFee, soeREQUIRED},
})) }))
@@ -440,10 +440,10 @@ TRANSACTION(ttAMM_DEPOSIT, 36, AMMDeposit,
featureAMM, featureAMM,
noPriv, noPriv,
({ ({
{sfAsset, soeREQUIRED}, {sfAsset, soeREQUIRED, soeMPTSupported},
{sfAsset2, soeREQUIRED}, {sfAsset2, soeREQUIRED, soeMPTSupported},
{sfAmount, soeOPTIONAL}, {sfAmount, soeOPTIONAL, soeMPTSupported},
{sfAmount2, soeOPTIONAL}, {sfAmount2, soeOPTIONAL, soeMPTSupported},
{sfEPrice, soeOPTIONAL}, {sfEPrice, soeOPTIONAL},
{sfLPTokenOut, soeOPTIONAL}, {sfLPTokenOut, soeOPTIONAL},
{sfTradingFee, soeOPTIONAL}, {sfTradingFee, soeOPTIONAL},
@@ -456,12 +456,12 @@ TRANSACTION(ttAMM_DEPOSIT, 36, AMMDeposit,
TRANSACTION(ttAMM_WITHDRAW, 37, AMMWithdraw, TRANSACTION(ttAMM_WITHDRAW, 37, AMMWithdraw,
Delegation::delegable, Delegation::delegable,
featureAMM, featureAMM,
mayDeleteAcct, mayDeleteAcct | mayAuthorizeMPT,
({ ({
{sfAsset, soeREQUIRED}, {sfAsset, soeREQUIRED, soeMPTSupported},
{sfAsset2, soeREQUIRED}, {sfAsset2, soeREQUIRED, soeMPTSupported},
{sfAmount, soeOPTIONAL}, {sfAmount, soeOPTIONAL, soeMPTSupported},
{sfAmount2, soeOPTIONAL}, {sfAmount2, soeOPTIONAL, soeMPTSupported},
{sfEPrice, soeOPTIONAL}, {sfEPrice, soeOPTIONAL},
{sfLPTokenIn, soeOPTIONAL}, {sfLPTokenIn, soeOPTIONAL},
})) }))
@@ -475,8 +475,8 @@ TRANSACTION(ttAMM_VOTE, 38, AMMVote,
featureAMM, featureAMM,
noPriv, noPriv,
({ ({
{sfAsset, soeREQUIRED}, {sfAsset, soeREQUIRED, soeMPTSupported},
{sfAsset2, soeREQUIRED}, {sfAsset2, soeREQUIRED, soeMPTSupported},
{sfTradingFee, soeREQUIRED}, {sfTradingFee, soeREQUIRED},
})) }))
@@ -489,8 +489,8 @@ TRANSACTION(ttAMM_BID, 39, AMMBid,
featureAMM, featureAMM,
noPriv, noPriv,
({ ({
{sfAsset, soeREQUIRED}, {sfAsset, soeREQUIRED, soeMPTSupported},
{sfAsset2, soeREQUIRED}, {sfAsset2, soeREQUIRED, soeMPTSupported},
{sfBidMin, soeOPTIONAL}, {sfBidMin, soeOPTIONAL},
{sfBidMax, soeOPTIONAL}, {sfBidMax, soeOPTIONAL},
{sfAuthAccounts, soeOPTIONAL}, {sfAuthAccounts, soeOPTIONAL},
@@ -503,10 +503,10 @@ TRANSACTION(ttAMM_BID, 39, AMMBid,
TRANSACTION(ttAMM_DELETE, 40, AMMDelete, TRANSACTION(ttAMM_DELETE, 40, AMMDelete,
Delegation::delegable, Delegation::delegable,
featureAMM, featureAMM,
mustDeleteAcct, mustDeleteAcct | mayDeleteMPT,
({ ({
{sfAsset, soeREQUIRED}, {sfAsset, soeREQUIRED, soeMPTSupported},
{sfAsset2, soeREQUIRED}, {sfAsset2, soeREQUIRED, soeMPTSupported},
})) }))
/** This transactions creates a crosschain sequence number */ /** This transactions creates a crosschain sequence number */

View File

@@ -100,7 +100,7 @@ using sha512_hasher = openssl_sha512_hasher;
/** Returns the RIPEMD-160 digest of the SHA256 hash of the message. /** Returns the RIPEMD-160 digest of the SHA256 hash of the message.
This operation is used to compute the 160-bit identifier This operation is used to compute the 160-bit identifier
representing a Ripple account, from a message. Typically the representing an XRPL account, from a message. Typically the
message is the public key of the account - which is not message is the public key of the account - which is not
stored in the account root. stored in the account root.

View File

@@ -401,6 +401,8 @@ JSS(min_ledger); // in: LedgerCleaner
JSS(minimum_fee); // out: TxQ JSS(minimum_fee); // out: TxQ
JSS(minimum_level); // out: TxQ JSS(minimum_level); // out: TxQ
JSS(missingCommand); // error JSS(missingCommand); // error
JSS(mpt_issuance_id_a); // out: BookChanges
JSS(mpt_issuance_id_b); // out: BookChanges
JSS(name); // out: AmendmentTableImpl, PeerImp JSS(name); // out: AmendmentTableImpl, PeerImp
JSS(needed_state_hashes); // out: InboundLedger JSS(needed_state_hashes); // out: InboundLedger
JSS(needed_transaction_hashes); // out: InboundLedger JSS(needed_transaction_hashes); // out: InboundLedger
@@ -511,7 +513,7 @@ JSS(response); // websocket
JSS(result); // RPC JSS(result); // RPC
JSS(ripple_lines); // out: NetworkOPs JSS(ripple_lines); // out: NetworkOPs
JSS(ripple_state); // in: LedgerEntr JSS(ripple_state); // in: LedgerEntr
JSS(ripplerpc); // ripple RPC version JSS(ripplerpc); // XRPL RPC version
JSS(role); // out: Ping.cpp JSS(role); // out: Ping.cpp
JSS(rpc); // JSS(rpc); //
JSS(rt_accounts); // in: Subscribe, Unsubscribe JSS(rt_accounts); // in: Subscribe, Unsubscribe

View File

@@ -117,6 +117,30 @@ public:
return this->sle_->isFieldPresent(sfTakerPaysIssuer); return this->sle_->isFieldPresent(sfTakerPaysIssuer);
} }
/**
* @brief Get sfTakerPaysMPT (soeOPTIONAL)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_UINT192::type::value_type>
getTakerPaysMPT() const
{
if (hasTakerPaysMPT())
return this->sle_->at(sfTakerPaysMPT);
return std::nullopt;
}
/**
* @brief Check if sfTakerPaysMPT is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasTakerPaysMPT() const
{
return this->sle_->isFieldPresent(sfTakerPaysMPT);
}
/** /**
* @brief Get sfTakerGetsCurrency (soeOPTIONAL) * @brief Get sfTakerGetsCurrency (soeOPTIONAL)
* @return The field value, or std::nullopt if not present. * @return The field value, or std::nullopt if not present.
@@ -165,6 +189,30 @@ public:
return this->sle_->isFieldPresent(sfTakerGetsIssuer); return this->sle_->isFieldPresent(sfTakerGetsIssuer);
} }
/**
* @brief Get sfTakerGetsMPT (soeOPTIONAL)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_UINT192::type::value_type>
getTakerGetsMPT() const
{
if (hasTakerGetsMPT())
return this->sle_->at(sfTakerGetsMPT);
return std::nullopt;
}
/**
* @brief Check if sfTakerGetsMPT is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasTakerGetsMPT() const
{
return this->sle_->isFieldPresent(sfTakerGetsMPT);
}
/** /**
* @brief Get sfExchangeRate (soeOPTIONAL) * @brief Get sfExchangeRate (soeOPTIONAL)
* @return The field value, or std::nullopt if not present. * @return The field value, or std::nullopt if not present.
@@ -427,6 +475,17 @@ public:
return *this; return *this;
} }
/**
* @brief Set sfTakerPaysMPT (soeOPTIONAL)
* @return Reference to this builder for method chaining.
*/
DirectoryNodeBuilder&
setTakerPaysMPT(std::decay_t<typename SF_UINT192::type::value_type> const& value)
{
object_[sfTakerPaysMPT] = value;
return *this;
}
/** /**
* @brief Set sfTakerGetsCurrency (soeOPTIONAL) * @brief Set sfTakerGetsCurrency (soeOPTIONAL)
* @return Reference to this builder for method chaining. * @return Reference to this builder for method chaining.
@@ -449,6 +508,17 @@ public:
return *this; return *this;
} }
/**
* @brief Set sfTakerGetsMPT (soeOPTIONAL)
* @return Reference to this builder for method chaining.
*/
DirectoryNodeBuilder&
setTakerGetsMPT(std::decay_t<typename SF_UINT192::type::value_type> const& value)
{
object_[sfTakerGetsMPT] = value;
return *this;
}
/** /**
* @brief Set sfExchangeRate (soeOPTIONAL) * @brief Set sfExchangeRate (soeOPTIONAL)
* @return Reference to this builder for method chaining. * @return Reference to this builder for method chaining.

View File

@@ -49,6 +49,7 @@ public:
/** /**
* @brief Get sfAsset (soeREQUIRED) * @brief Get sfAsset (soeREQUIRED)
* @note This field supports MPT (Multi-Purpose Token) amounts.
* @return The field value. * @return The field value.
*/ */
[[nodiscard]] [[nodiscard]]
@@ -60,6 +61,7 @@ public:
/** /**
* @brief Get sfAsset2 (soeREQUIRED) * @brief Get sfAsset2 (soeREQUIRED)
* @note This field supports MPT (Multi-Purpose Token) amounts.
* @return The field value. * @return The field value.
*/ */
[[nodiscard]] [[nodiscard]]
@@ -192,6 +194,7 @@ public:
/** /**
* @brief Set sfAsset (soeREQUIRED) * @brief Set sfAsset (soeREQUIRED)
* @note This field supports MPT (Multi-Purpose Token) amounts.
* @return Reference to this builder for method chaining. * @return Reference to this builder for method chaining.
*/ */
AMMBidBuilder& AMMBidBuilder&
@@ -203,6 +206,7 @@ public:
/** /**
* @brief Set sfAsset2 (soeREQUIRED) * @brief Set sfAsset2 (soeREQUIRED)
* @note This field supports MPT (Multi-Purpose Token) amounts.
* @return Reference to this builder for method chaining. * @return Reference to this builder for method chaining.
*/ */
AMMBidBuilder& AMMBidBuilder&

View File

@@ -21,7 +21,7 @@ class AMMClawbackBuilder;
* Type: ttAMM_CLAWBACK (31) * Type: ttAMM_CLAWBACK (31)
* Delegable: Delegation::delegable * Delegable: Delegation::delegable
* Amendment: featureAMMClawback * Amendment: featureAMMClawback
* Privileges: mayDeleteAcct | overrideFreeze * Privileges: mayDeleteAcct | overrideFreeze | mayAuthorizeMPT
* *
* Immutable wrapper around STTx providing type-safe field access. * Immutable wrapper around STTx providing type-safe field access.
* Use AMMClawbackBuilder to construct new transactions. * Use AMMClawbackBuilder to construct new transactions.
@@ -60,6 +60,7 @@ public:
/** /**
* @brief Get sfAsset (soeREQUIRED) * @brief Get sfAsset (soeREQUIRED)
* @note This field supports MPT (Multi-Purpose Token) amounts.
* @return The field value. * @return The field value.
*/ */
[[nodiscard]] [[nodiscard]]
@@ -71,6 +72,7 @@ public:
/** /**
* @brief Get sfAsset2 (soeREQUIRED) * @brief Get sfAsset2 (soeREQUIRED)
* @note This field supports MPT (Multi-Purpose Token) amounts.
* @return The field value. * @return The field value.
*/ */
[[nodiscard]] [[nodiscard]]
@@ -82,6 +84,7 @@ public:
/** /**
* @brief Get sfAmount (soeOPTIONAL) * @brief Get sfAmount (soeOPTIONAL)
* @note This field supports MPT (Multi-Purpose Token) amounts.
* @return The field value, or std::nullopt if not present. * @return The field value, or std::nullopt if not present.
*/ */
[[nodiscard]] [[nodiscard]]
@@ -166,6 +169,7 @@ public:
/** /**
* @brief Set sfAsset (soeREQUIRED) * @brief Set sfAsset (soeREQUIRED)
* @note This field supports MPT (Multi-Purpose Token) amounts.
* @return Reference to this builder for method chaining. * @return Reference to this builder for method chaining.
*/ */
AMMClawbackBuilder& AMMClawbackBuilder&
@@ -177,6 +181,7 @@ public:
/** /**
* @brief Set sfAsset2 (soeREQUIRED) * @brief Set sfAsset2 (soeREQUIRED)
* @note This field supports MPT (Multi-Purpose Token) amounts.
* @return Reference to this builder for method chaining. * @return Reference to this builder for method chaining.
*/ */
AMMClawbackBuilder& AMMClawbackBuilder&
@@ -188,6 +193,7 @@ public:
/** /**
* @brief Set sfAmount (soeOPTIONAL) * @brief Set sfAmount (soeOPTIONAL)
* @note This field supports MPT (Multi-Purpose Token) amounts.
* @return Reference to this builder for method chaining. * @return Reference to this builder for method chaining.
*/ */
AMMClawbackBuilder& AMMClawbackBuilder&

View File

@@ -21,7 +21,7 @@ class AMMCreateBuilder;
* Type: ttAMM_CREATE (35) * Type: ttAMM_CREATE (35)
* Delegable: Delegation::delegable * Delegable: Delegation::delegable
* Amendment: featureAMM * Amendment: featureAMM
* Privileges: createPseudoAcct * Privileges: createPseudoAcct | mayCreateMPT
* *
* Immutable wrapper around STTx providing type-safe field access. * Immutable wrapper around STTx providing type-safe field access.
* Use AMMCreateBuilder to construct new transactions. * Use AMMCreateBuilder to construct new transactions.
@@ -49,6 +49,7 @@ public:
/** /**
* @brief Get sfAmount (soeREQUIRED) * @brief Get sfAmount (soeREQUIRED)
* @note This field supports MPT (Multi-Purpose Token) amounts.
* @return The field value. * @return The field value.
*/ */
[[nodiscard]] [[nodiscard]]
@@ -60,6 +61,7 @@ public:
/** /**
* @brief Get sfAmount2 (soeREQUIRED) * @brief Get sfAmount2 (soeREQUIRED)
* @note This field supports MPT (Multi-Purpose Token) amounts.
* @return The field value. * @return The field value.
*/ */
[[nodiscard]] [[nodiscard]]
@@ -129,6 +131,7 @@ public:
/** /**
* @brief Set sfAmount (soeREQUIRED) * @brief Set sfAmount (soeREQUIRED)
* @note This field supports MPT (Multi-Purpose Token) amounts.
* @return Reference to this builder for method chaining. * @return Reference to this builder for method chaining.
*/ */
AMMCreateBuilder& AMMCreateBuilder&
@@ -140,6 +143,7 @@ public:
/** /**
* @brief Set sfAmount2 (soeREQUIRED) * @brief Set sfAmount2 (soeREQUIRED)
* @note This field supports MPT (Multi-Purpose Token) amounts.
* @return Reference to this builder for method chaining. * @return Reference to this builder for method chaining.
*/ */
AMMCreateBuilder& AMMCreateBuilder&

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