mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-16 00:42:28 +00:00
Compare commits
79 Commits
bthomee/no
...
ximinez/nu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e764cd172 | ||
|
|
d52d735543 | ||
|
|
371d3a6f30 | ||
|
|
6a0ce46755 | ||
|
|
2f029a2120 | ||
|
|
018e36f1ca | ||
|
|
ee9b486f8b | ||
|
|
61fbde3a71 | ||
|
|
47f6422ee7 | ||
|
|
e2e537b3bb | ||
|
|
8201d0330e | ||
|
|
a873250019 | ||
|
|
9ac062c5a0 | ||
|
|
f631d95585 | ||
|
|
56c9d1d497 | ||
|
|
d52dd29d20 | ||
|
|
efa3328aba | ||
|
|
7793b5f10b | ||
|
|
dfcad69155 | ||
|
|
9daa985bf1 | ||
|
|
6d1a5be8d2 | ||
|
|
b0fe2ec58a | ||
|
|
c00ed673a8 | ||
|
|
d3b1ee9ec0 | ||
|
|
f239256d87 | ||
|
|
e160b95aef | ||
|
|
00761dbb67 | ||
|
|
14843e15d8 | ||
|
|
077e03ff33 | ||
|
|
7d524a03b8 | ||
|
|
c0ee813666 | ||
|
|
8e05416211 | ||
|
|
81555d5456 | ||
|
|
6b55c4cdc8 | ||
|
|
3414a1776b | ||
|
|
6d9ed125f3 | ||
|
|
f8359d9b0c | ||
|
|
8ed8b52dfe | ||
|
|
62d0b07ee8 | ||
|
|
44ea0b24c8 | ||
|
|
e443a76d83 | ||
|
|
eef1f791e8 | ||
|
|
2191ef8d75 | ||
|
|
ea4f922492 | ||
|
|
9250ba9e27 | ||
|
|
61f38ba068 | ||
|
|
3d5ff2c8a2 | ||
|
|
e27249134a | ||
|
|
d79fdec886 | ||
|
|
024d05b70c | ||
|
|
ffb3e1da53 | ||
|
|
aef7e5b335 | ||
|
|
e2c09e79d0 | ||
|
|
c6f854bbd8 | ||
|
|
6a1e0b0f5a | ||
|
|
01f5ae0927 | ||
|
|
9b4587f9af | ||
|
|
fbc6f87983 | ||
|
|
0871eb0cb6 | ||
|
|
2ccf132f79 | ||
|
|
6600153958 | ||
|
|
fff73dac51 | ||
|
|
06ff77458a | ||
|
|
f19ecb3b80 | ||
|
|
cc2406bf3f | ||
|
|
30c65320e4 | ||
|
|
569d9ea94e | ||
|
|
02b7bcfa2b | ||
|
|
07c0c320a7 | ||
|
|
d57e37c34b | ||
|
|
154bb65c35 | ||
|
|
111eda22e9 | ||
|
|
f7b6834d2a | ||
|
|
e464adaee6 | ||
|
|
cca92dedca | ||
|
|
3d6f57a4df | ||
|
|
fc29fbe946 | ||
|
|
5e0a8d5c8a | ||
|
|
d27788f12a |
32
.clang-tidy
32
.clang-tidy
@@ -10,26 +10,26 @@ Checks: "-*,
|
||||
bugprone-chained-comparison,
|
||||
bugprone-compare-pointer-to-member-virtual-function,
|
||||
bugprone-copy-constructor-init,
|
||||
# bugprone-crtp-constructor-accessibility, # has issues
|
||||
bugprone-crtp-constructor-accessibility,
|
||||
bugprone-dangling-handle,
|
||||
bugprone-dynamic-static-initializers,
|
||||
# bugprone-empty-catch, # has issues
|
||||
bugprone-empty-catch,
|
||||
bugprone-fold-init-type,
|
||||
# bugprone-forward-declaration-namespace, # has issues
|
||||
# bugprone-inaccurate-erase,
|
||||
# bugprone-inc-dec-in-conditions,
|
||||
# bugprone-incorrect-enable-if,
|
||||
# bugprone-incorrect-roundings,
|
||||
# bugprone-infinite-loop,
|
||||
# bugprone-integer-division,
|
||||
bugprone-forward-declaration-namespace,
|
||||
bugprone-inaccurate-erase,
|
||||
bugprone-inc-dec-in-conditions,
|
||||
bugprone-incorrect-enable-if,
|
||||
bugprone-incorrect-roundings,
|
||||
bugprone-infinite-loop,
|
||||
bugprone-integer-division,
|
||||
bugprone-lambda-function-name,
|
||||
# bugprone-macro-parentheses, # has issues
|
||||
bugprone-macro-parentheses,
|
||||
bugprone-macro-repeated-side-effects,
|
||||
bugprone-misplaced-operator-in-strlen-in-alloc,
|
||||
bugprone-misplaced-pointer-arithmetic-in-alloc,
|
||||
bugprone-misplaced-widening-cast,
|
||||
bugprone-move-forwarding-reference,
|
||||
# bugprone-multi-level-implicit-pointer-conversion, # has issues
|
||||
bugprone-multi-level-implicit-pointer-conversion,
|
||||
bugprone-multiple-new-in-one-expression,
|
||||
bugprone-multiple-statement-macro,
|
||||
bugprone-no-escape,
|
||||
@@ -39,13 +39,13 @@ Checks: "-*,
|
||||
bugprone-pointer-arithmetic-on-polymorphic-object,
|
||||
bugprone-posix-return,
|
||||
bugprone-redundant-branch-condition,
|
||||
# bugprone-reserved-identifier, # has issues
|
||||
# bugprone-return-const-ref-from-parameter, # has issues
|
||||
bugprone-reserved-identifier,
|
||||
bugprone-return-const-ref-from-parameter,
|
||||
bugprone-shared-ptr-array-mismatch,
|
||||
bugprone-signal-handler,
|
||||
bugprone-signed-char-misuse,
|
||||
bugprone-sizeof-container,
|
||||
# bugprone-sizeof-expression, # has issues
|
||||
bugprone-sizeof-expression,
|
||||
bugprone-spuriously-wake-up-functions,
|
||||
bugprone-standalone-empty,
|
||||
bugprone-string-constructor,
|
||||
@@ -62,7 +62,7 @@ Checks: "-*,
|
||||
bugprone-suspicious-string-compare,
|
||||
bugprone-suspicious-stringview-data-usage,
|
||||
bugprone-swapped-arguments,
|
||||
# bugprone-switch-missing-default-case, # has issues
|
||||
bugprone-switch-missing-default-case,
|
||||
bugprone-terminating-continue,
|
||||
bugprone-throw-keyword-missing,
|
||||
bugprone-too-small-loop-variable,
|
||||
@@ -73,7 +73,7 @@ Checks: "-*,
|
||||
bugprone-unhandled-self-assignment,
|
||||
bugprone-unique-ptr-array-mismatch,
|
||||
bugprone-unsafe-functions,
|
||||
# bugprone-use-after-move, # has issues
|
||||
bugprone-use-after-move, # has issues
|
||||
bugprone-unused-raii,
|
||||
bugprone-unused-return-value,
|
||||
bugprone-unused-local-non-trivial-variable,
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/feature_request.md
vendored
4
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: Feature Request
|
||||
about: Suggest a new feature for the rippled project
|
||||
title: "[Title with short description] (Version: [rippled version])"
|
||||
about: Suggest a new feature for the xrpld project
|
||||
title: "[Title with short description] (Version: [xrpld version])"
|
||||
labels: Feature Request
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
12
.github/scripts/levelization/README.md
vendored
12
.github/scripts/levelization/README.md
vendored
@@ -1,14 +1,14 @@
|
||||
# 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.
|
||||
|
||||
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
|
||||
organized into "tiers" or "levels" such that a module from one level can
|
||||
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
|
||||
other than it's own.
|
||||
other than its own.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
modules listed first, and the higher level, higher numbered modules with
|
||||
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,
|
||||
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
|
||||
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.
|
||||
It generates many files of [results](results):
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@ libxrpl.tx > xrpl.server
|
||||
libxrpl.tx > xrpl.tx
|
||||
test.app > test.jtx
|
||||
test.app > test.rpc
|
||||
test.app > test.shamap
|
||||
test.app > test.toplevel
|
||||
test.app > test.unit_test
|
||||
test.app > xrpl.basics
|
||||
@@ -60,7 +59,6 @@ test.app > xrpl.protocol
|
||||
test.app > xrpl.rdb
|
||||
test.app > xrpl.resource
|
||||
test.app > xrpl.server
|
||||
test.app > xrpl.shamap
|
||||
test.app > xrpl.tx
|
||||
test.basics > test.jtx
|
||||
test.basics > test.unit_test
|
||||
|
||||
3
.github/scripts/rename/README.md
vendored
3
.github/scripts/rename/README.md
vendored
@@ -34,6 +34,8 @@ run from the repository root.
|
||||
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
|
||||
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:
|
||||
|
||||
@@ -44,4 +46,5 @@ You can run all these scripts from the repository root as follows:
|
||||
./.github/scripts/rename/binary.sh .
|
||||
./.github/scripts/rename/namespace.sh .
|
||||
./.github/scripts/rename/config.sh .
|
||||
./.github/scripts/rename/docs.sh .
|
||||
```
|
||||
|
||||
3
.github/scripts/rename/binary.sh
vendored
3
.github/scripts/rename/binary.sh
vendored
@@ -29,7 +29,7 @@ if [ ! -d "${DIRECTORY}" ]; then
|
||||
echo "Error: Directory '${DIRECTORY}' does not exist."
|
||||
exit 1
|
||||
fi
|
||||
pushd ${DIRECTORY}
|
||||
pushd "${DIRECTORY}"
|
||||
|
||||
# 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
|
||||
@@ -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@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' docs/build/install.md
|
||||
|
||||
popd
|
||||
echo "Processing complete."
|
||||
|
||||
2
.github/scripts/rename/cmake.sh
vendored
2
.github/scripts/rename/cmake.sh
vendored
@@ -38,7 +38,7 @@ if [ ! -d "${DIRECTORY}" ]; then
|
||||
echo "Error: Directory '${DIRECTORY}' does not exist."
|
||||
exit 1
|
||||
fi
|
||||
pushd ${DIRECTORY}
|
||||
pushd "${DIRECTORY}"
|
||||
|
||||
# Rename the files.
|
||||
find cmake -type f -name 'Rippled*.cmake' -exec bash -c 'mv "${1}" "${1/Rippled/Xrpl}"' - {} \;
|
||||
|
||||
5
.github/scripts/rename/config.sh
vendored
5
.github/scripts/rename/config.sh
vendored
@@ -28,7 +28,7 @@ if [ ! -d "${DIRECTORY}" ]; then
|
||||
echo "Error: Directory '${DIRECTORY}' does not exist."
|
||||
exit 1
|
||||
fi
|
||||
pushd ${DIRECTORY}
|
||||
pushd "${DIRECTORY}"
|
||||
|
||||
# Add the xrpld.cfg to the .gitignore.
|
||||
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
|
||||
echo "Processing file: ${FILE}"
|
||||
${SED_COMMAND} -i -E 's/rippled(-example)?[ .]cfg/xrpld\1.cfg/g' "${FILE}"
|
||||
${SED_COMMAND} -i 's/rippleConfig/xrpldConfig/g' "${FILE}"
|
||||
done
|
||||
done
|
||||
${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/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/Rippled/File/g' src/test/core/Config_test.cpp
|
||||
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
10
.github/scripts/rename/copyright.sh
vendored
10
.github/scripts/rename/copyright.sh
vendored
@@ -31,7 +31,7 @@ if [ ! -d "${DIRECTORY}" ]; then
|
||||
echo "Error: Directory '${DIRECTORY}' does not exist."
|
||||
exit 1
|
||||
fi
|
||||
pushd ${DIRECTORY}
|
||||
pushd "${DIRECTORY}"
|
||||
|
||||
# Prevent sed and echo from removing newlines and tabs in string literals by
|
||||
# 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
|
||||
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/rpc/ValidatorInfo_test.cpp)" > src/test/rpc/ValidatorInfo_test.cpp
|
||||
fi
|
||||
if ! grep -q 'Dev Null' src/xrpld/rpc/handlers/DoManifest.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
|
||||
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/server_info/Manifest.cpp)" > src/xrpld/rpc/handlers/server_info/Manifest.cpp
|
||||
fi
|
||||
if ! grep -q 'Dev Null' src/xrpld/rpc/handlers/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
|
||||
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/admin/status/ValidatorInfo.cpp)" > src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp
|
||||
fi
|
||||
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
|
||||
|
||||
96
.github/scripts/rename/docs.sh
vendored
Executable file
96
.github/scripts/rename/docs.sh
vendored
Executable 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."
|
||||
5
.github/scripts/rename/namespace.sh
vendored
5
.github/scripts/rename/namespace.sh
vendored
@@ -31,16 +31,17 @@ if [ ! -d "${DIRECTORY}" ]; then
|
||||
echo "Error: Directory '${DIRECTORY}' does not exist."
|
||||
exit 1
|
||||
fi
|
||||
pushd ${DIRECTORY}
|
||||
pushd "${DIRECTORY}"
|
||||
|
||||
DIRECTORIES=("include" "src" "tests")
|
||||
for DIRECTORY in "${DIRECTORIES[@]}"; do
|
||||
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}"
|
||||
${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 -E 's/(BEAST_DEFINE_TESTSUITE.+)ripple(.+)/\1xrpl\2/g' "${FILE}"
|
||||
done
|
||||
done
|
||||
|
||||
2
.github/scripts/strategy-matrix/generate.py
vendored
2
.github/scripts/strategy-matrix/generate.py
vendored
@@ -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
|
||||
# names get truncated.
|
||||
# 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 (
|
||||
os["distro_version"] == "bookworm"
|
||||
and f"{os['compiler_name']}-{os['compiler_version']}" == "clang-20"
|
||||
|
||||
2
.github/workflows/check-pr-commits.yml
vendored
2
.github/workflows/check-pr-commits.yml
vendored
@@ -10,4 +10,4 @@ permissions:
|
||||
|
||||
jobs:
|
||||
check_commits:
|
||||
uses: XRPLF/actions/.github/workflows/check-pr-commits.yml@481048b78b94ac3343d1292b4ef125a813879f2b
|
||||
uses: XRPLF/actions/.github/workflows/check-pr-commits.yml@e2c7f400d1e85ae65dad552fd425169fbacca4a3
|
||||
|
||||
2
.github/workflows/check-pr-title.yml
vendored
2
.github/workflows/check-pr-title.yml
vendored
@@ -11,4 +11,4 @@ on:
|
||||
jobs:
|
||||
check_title:
|
||||
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
|
||||
|
||||
2
.github/workflows/pre-commit.yml
vendored
2
.github/workflows/pre-commit.yml
vendored
@@ -14,7 +14,7 @@ on:
|
||||
jobs:
|
||||
# Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks.
|
||||
run-hooks:
|
||||
uses: XRPLF/actions/.github/workflows/pre-commit.yml@e7896f15cc60d0da1a272c77ee5c4026b424f9c7
|
||||
uses: XRPLF/actions/.github/workflows/pre-commit.yml@9307df762265e15c745ddcdb38a581c989f7f349
|
||||
with:
|
||||
runs_on: ubuntu-latest
|
||||
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-41ec7c1" }'
|
||||
|
||||
6
.github/workflows/publish-docs.yml
vendored
6
.github/workflows/publish-docs.yml
vendored
@@ -47,7 +47,7 @@ jobs:
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@2bbc2dc1abeec7bfaa886804ab86871ac201764e
|
||||
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
|
||||
with:
|
||||
enable_ccache: false
|
||||
|
||||
@@ -81,13 +81,13 @@ jobs:
|
||||
cmake --build . --target docs --parallel ${BUILD_NPROC}
|
||||
|
||||
- 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
|
||||
with:
|
||||
path: ${{ env.BUILD_DIR }}/docs/html
|
||||
|
||||
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
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
|
||||
53
.github/workflows/reusable-build-test-config.yml
vendored
53
.github/workflows/reusable-build-test-config.yml
vendored
@@ -107,7 +107,7 @@ jobs:
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@2bbc2dc1abeec7bfaa886804ab86871ac201764e
|
||||
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
|
||||
with:
|
||||
enable_ccache: ${{ inputs.ccache_enabled }}
|
||||
|
||||
@@ -153,6 +153,32 @@ jobs:
|
||||
${CMAKE_ARGS} \
|
||||
..
|
||||
|
||||
- name: Check protocol autogen files are up-to-date
|
||||
working-directory: ${{ env.BUILD_DIR }}
|
||||
env:
|
||||
MESSAGE: |
|
||||
|
||||
The generated protocol wrapper classes are out of date.
|
||||
|
||||
This typically happens when the macro files or generator scripts
|
||||
have changed but the generated files were not regenerated.
|
||||
|
||||
To fix this:
|
||||
1. Run: cmake --build . --target setup_code_gen
|
||||
2. Run: cmake --build . --target code_gen
|
||||
3. Commit and push the regenerated files
|
||||
run: |
|
||||
set -e
|
||||
cmake --build . --target setup_code_gen
|
||||
cmake --build . --target code_gen
|
||||
DIFF=$(git -C .. status --porcelain -- include/xrpl/protocol_autogen src/tests/libxrpl/protocol_autogen)
|
||||
if [ -n "${DIFF}" ]; then
|
||||
echo "::error::Generated protocol files are out of date"
|
||||
git -C .. diff -- include/xrpl/protocol_autogen src/tests/libxrpl/protocol_autogen
|
||||
echo "${MESSAGE}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Build the binary
|
||||
working-directory: ${{ env.BUILD_DIR }}
|
||||
env:
|
||||
@@ -166,29 +192,6 @@ jobs:
|
||||
--parallel "${BUILD_NPROC}" \
|
||||
--target "${CMAKE_TARGET}"
|
||||
|
||||
- name: Check protocol autogen files are up-to-date
|
||||
env:
|
||||
MESSAGE: |
|
||||
|
||||
The generated protocol wrapper classes are out of date.
|
||||
|
||||
This typically happens when your branch is behind develop and
|
||||
the macro files or generator scripts have changed.
|
||||
|
||||
To fix this:
|
||||
1. Update your branch from develop (merge or rebase)
|
||||
2. Build with code generation enabled (XRPL_NO_CODEGEN=OFF)
|
||||
3. Commit and push the regenerated files
|
||||
run: |
|
||||
set -e
|
||||
DIFF=$(git status --porcelain -- include/xrpl/protocol_autogen src/tests/libxrpl/protocol_autogen)
|
||||
if [ -n "${DIFF}" ]; then
|
||||
echo "::error::Generated protocol files are out of date"
|
||||
git diff -- include/xrpl/protocol_autogen src/tests/libxrpl/protocol_autogen
|
||||
echo "${MESSAGE}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Show ccache statistics
|
||||
if: ${{ inputs.ccache_enabled }}
|
||||
run: |
|
||||
@@ -199,7 +202,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- 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
|
||||
with:
|
||||
name: xrpld-${{ inputs.config_name }}
|
||||
|
||||
2
.github/workflows/reusable-check-rename.yml
vendored
2
.github/workflows/reusable-check-rename.yml
vendored
@@ -33,6 +33,8 @@ jobs:
|
||||
run: .github/scripts/rename/config.sh .
|
||||
- name: Check include guards
|
||||
run: .github/scripts/rename/include.sh .
|
||||
- name: Check documentation
|
||||
run: .github/scripts/rename/docs.sh .
|
||||
- name: Check for differences
|
||||
env:
|
||||
MESSAGE: |
|
||||
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@2bbc2dc1abeec7bfaa886804ab86871ac201764e
|
||||
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
|
||||
with:
|
||||
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
|
||||
|
||||
- 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
|
||||
with:
|
||||
name: clang-tidy-results
|
||||
|
||||
2
.github/workflows/upload-conan-deps.yml
vendored
2
.github/workflows/upload-conan-deps.yml
vendored
@@ -70,7 +70,7 @@ jobs:
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@2bbc2dc1abeec7bfaa886804ab86871ac201764e
|
||||
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
|
||||
with:
|
||||
enable_ccache: false
|
||||
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -13,6 +13,7 @@
|
||||
Debug/
|
||||
Release/
|
||||
/.build/
|
||||
/.venv/
|
||||
/build/
|
||||
/db/
|
||||
/out.txt
|
||||
|
||||
@@ -17,7 +17,6 @@ repos:
|
||||
args: [--maxkb=400, --enforce-all]
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: mixed-line-ending
|
||||
- id: check-merge-conflict
|
||||
args: [--assume-in-merge]
|
||||
|
||||
@@ -38,6 +37,7 @@ repos:
|
||||
rev: c2bc67fe8f8f549cc489e00ba8b45aa18ee713b1 # frozen: v3.8.1
|
||||
hooks:
|
||||
- id: prettier
|
||||
args: [--end-of-line=auto]
|
||||
|
||||
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||
rev: ea488cebbfd88a5f50b8bd95d5c829d0bb76feb8 # frozen: 26.1.0
|
||||
|
||||
@@ -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.
|
||||
|
||||
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.
|
||||
|
||||
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 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 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
|
||||
|
||||
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
|
||||
|
||||
@@ -38,6 +38,8 @@ This section contains changes targeting a future version.
|
||||
### 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)
|
||||
- `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
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 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.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 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.
|
||||
|
||||
|
||||
19
BUILD.md
19
BUILD.md
@@ -459,6 +459,21 @@ install ccache --version 4.11.3 --allow-downgrade`.
|
||||
The location of `xrpld` binary in your build directory depends on your
|
||||
CMake generator. Pass `--help` to see the rest of the command line options.
|
||||
|
||||
## Code generation
|
||||
|
||||
The protocol wrapper classes in `include/xrpl/protocol_autogen/` are generated
|
||||
from macro definition files in `include/xrpl/protocol/detail/`. If you modify
|
||||
the macro files (e.g. `transactions.macro`, `ledger_entries.macro`) or the
|
||||
generation scripts/templates in `cmake/scripts/codegen/`, you need to regenerate the
|
||||
files:
|
||||
|
||||
```
|
||||
cmake --build . --target setup_code_gen # create venv and install dependencies (once)
|
||||
cmake --build . --target code_gen # regenerate code
|
||||
```
|
||||
|
||||
The regenerated files should be committed alongside your changes.
|
||||
|
||||
## Coverage report
|
||||
|
||||
The coverage report is intended for developers using compilers GCC
|
||||
@@ -603,8 +618,8 @@ If you want to experiment with a new package, follow these steps:
|
||||
`default_options` property (with syntax `'$package:$option': $value`).
|
||||
3. Modify [`CMakeLists.txt`](./CMakeLists.txt):
|
||||
- Add a call to `find_package($package REQUIRED)`.
|
||||
- Link a library from the package to the target `ripple_libs`
|
||||
(search for the existing call to `target_link_libraries(ripple_libs INTERFACE ...)`).
|
||||
- Link a library from the package to the target `xrpl_libs`
|
||||
(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.
|
||||
|
||||
[1]: https://github.com/conan-io/conan-center-index/issues/13168
|
||||
|
||||
@@ -132,6 +132,7 @@ if(coverage)
|
||||
endif()
|
||||
|
||||
include(XrplCore)
|
||||
include(XrplProtocolAutogen)
|
||||
include(XrplInstall)
|
||||
include(XrplValidatorKeys)
|
||||
|
||||
|
||||
@@ -533,7 +533,7 @@ All releases, including release candidates and betas, are handled
|
||||
differently from typical PRs. Most importantly, never use
|
||||
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.
|
||||
2. Periodically, a maintainer will build and tag a beta version from
|
||||
|
||||
22
README.md
22
README.md
@@ -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.
|
||||
|
||||
## 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
|
||||
|
||||
@@ -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:
|
||||
|
||||
- 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.
|
||||
- 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
|
||||
|
||||
| Folder | Contents |
|
||||
| :--------- | :----------------------------------------------- |
|
||||
| `./bin` | Scripts and data files for Ripple integrators. |
|
||||
| `./Builds` | Platform-specific guides for building `rippled`. |
|
||||
| `./docs` | Source documentation files and doxygen config. |
|
||||
| `./cfg` | Example configuration files. |
|
||||
| `./src` | Source code. |
|
||||
| Folder | Contents |
|
||||
| :--------- | :--------------------------------------------- |
|
||||
| `./bin` | Scripts and data files for XRPL developers. |
|
||||
| `./Builds` | Platform-specific guides for building `xrpld`. |
|
||||
| `./docs` | Source documentation files and doxygen config. |
|
||||
| `./cfg` | Example configuration files. |
|
||||
| `./src` | Source code. |
|
||||
|
||||
Some of the directories under `src` are external repositories included using
|
||||
git-subtree. See those directories' README files for more details.
|
||||
|
||||
@@ -6,7 +6,7 @@ For more details on operating an XRP Ledger server securely, please visit https:
|
||||
|
||||
## 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
|
||||
|
||||
@@ -59,11 +59,11 @@ While we commit to responding with 24 hours of your initial report with our tria
|
||||
|
||||
## 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:
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
# https://vl.ripple.com
|
||||
# https://unl.xrplf.org
|
||||
# http://127.0.0.1:8000
|
||||
# file:///etc/opt/ripple/vl.txt
|
||||
# file:///etc/opt/xrpld/vl.txt
|
||||
#
|
||||
# [validator_list_keys]
|
||||
#
|
||||
@@ -43,11 +43,11 @@
|
||||
# ED307A760EE34F2D0CAA103377B1969117C38B8AA0AA1E2A24DAC1F32FC97087ED
|
||||
#
|
||||
|
||||
# The default validator list publishers that the rippled instance
|
||||
# The default validator list publishers that the xrpld instance
|
||||
# trusts.
|
||||
#
|
||||
# WARNING: Changing these values can cause your rippled instance to see a
|
||||
# validated ledger that contradicts other rippled instances'
|
||||
# WARNING: Changing these values can cause your xrpld instance to see a
|
||||
# validated ledger that contradicts other xrpld instances'
|
||||
# validated ledgers (aka a ledger fork) if your validator list(s)
|
||||
# do not sufficiently overlap with the list(s) used by others.
|
||||
# See: https://arxiv.org/pdf/1802.07242.pdf
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#
|
||||
# 2. Peer Protocol
|
||||
#
|
||||
# 3. Ripple Protocol
|
||||
# 3. XRPL protocol
|
||||
#
|
||||
# 4. HTTPS Client
|
||||
#
|
||||
@@ -383,7 +383,7 @@
|
||||
#
|
||||
# These settings control security and access attributes of the Peer to Peer
|
||||
# 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
|
||||
# contents of validated ledgers.
|
||||
#
|
||||
@@ -406,7 +406,7 @@
|
||||
#
|
||||
# [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
|
||||
# available.
|
||||
#
|
||||
@@ -435,7 +435,7 @@
|
||||
# List of IP addresses or hostnames to which xrpld should always attempt to
|
||||
# maintain peer connections with. This is useful for manually forming private
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# Examples:
|
||||
# /home/ripple/validators.txt
|
||||
# C:/home/ripple/validators.txt
|
||||
# /home/username/validators.txt
|
||||
# C:/home/username/validators.txt
|
||||
#
|
||||
# Example content:
|
||||
# [validators]
|
||||
@@ -840,7 +840,7 @@
|
||||
#
|
||||
# 0: Disable the ledger replay feature [default]
|
||||
# 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.
|
||||
# And the ledger is built by applying the transactions to the parent
|
||||
# ledger.
|
||||
@@ -853,7 +853,7 @@
|
||||
#
|
||||
# The xrpld server instance uses HTTPS GET requests in a variety of
|
||||
# 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.
|
||||
#
|
||||
# [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
|
||||
# settings, these choices become part of the instance's vote during the
|
||||
# consensus process for each voting ledger.
|
||||
|
||||
@@ -108,24 +108,12 @@ target_link_libraries(
|
||||
)
|
||||
|
||||
# Level 05
|
||||
## Set up code generation for protocol_autogen module
|
||||
include(XrplProtocolAutogen)
|
||||
# Must call setup_protocol_autogen before add_module so that:
|
||||
# 1. Stale generated files are cleared before GLOB runs
|
||||
# 2. Output file list is known for custom commands
|
||||
setup_protocol_autogen()
|
||||
|
||||
add_module(xrpl protocol_autogen)
|
||||
target_link_libraries(
|
||||
xrpl.libxrpl.protocol_autogen
|
||||
PUBLIC xrpl.libxrpl.protocol
|
||||
)
|
||||
|
||||
# Ensure code generation runs before compiling protocol_autogen
|
||||
if(TARGET protocol_autogen_generate)
|
||||
add_dependencies(xrpl.libxrpl.protocol_autogen protocol_autogen_generate)
|
||||
endif()
|
||||
|
||||
# Level 06
|
||||
add_module(xrpl core)
|
||||
target_link_libraries(
|
||||
|
||||
@@ -2,308 +2,145 @@
|
||||
Protocol Autogen - Code generation for protocol wrapper classes
|
||||
#]===================================================================]
|
||||
|
||||
# Options for code generation
|
||||
option(
|
||||
XRPL_NO_CODEGEN
|
||||
"Disable code generation (use pre-generated files from repository)"
|
||||
OFF
|
||||
)
|
||||
set(CODEGEN_VENV_DIR
|
||||
""
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/.venv"
|
||||
CACHE PATH
|
||||
"Path to Python virtual environment for code generation. If provided, automatic venv setup is skipped."
|
||||
"Path to a Python virtual environment for code generation. A venv will be created here by setup_code_gen and used to run generation scripts."
|
||||
)
|
||||
|
||||
# Function to set up code generation for protocol_autogen module
|
||||
# This runs at configure time to generate C++ wrapper classes from macro files
|
||||
function(setup_protocol_autogen)
|
||||
# Directory paths
|
||||
set(MACRO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include/xrpl/protocol/detail")
|
||||
set(AUTOGEN_HEADER_DIR
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/xrpl/protocol_autogen"
|
||||
)
|
||||
set(AUTOGEN_TEST_DIR
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/tests/libxrpl/protocol_autogen"
|
||||
)
|
||||
set(SCRIPTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/scripts")
|
||||
# Directory paths
|
||||
set(MACRO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include/xrpl/protocol/detail")
|
||||
set(AUTOGEN_HEADER_DIR
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/xrpl/protocol_autogen"
|
||||
)
|
||||
set(AUTOGEN_TEST_DIR
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/tests/libxrpl/protocol_autogen"
|
||||
)
|
||||
set(SCRIPTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake/scripts/codegen")
|
||||
|
||||
# Input macro files
|
||||
set(TRANSACTIONS_MACRO "${MACRO_DIR}/transactions.macro")
|
||||
set(LEDGER_ENTRIES_MACRO "${MACRO_DIR}/ledger_entries.macro")
|
||||
set(SFIELDS_MACRO "${MACRO_DIR}/sfields.macro")
|
||||
# Input macro files
|
||||
set(TRANSACTIONS_MACRO "${MACRO_DIR}/transactions.macro")
|
||||
set(LEDGER_ENTRIES_MACRO "${MACRO_DIR}/ledger_entries.macro")
|
||||
set(SFIELDS_MACRO "${MACRO_DIR}/sfields.macro")
|
||||
|
||||
# Python scripts and templates
|
||||
set(GENERATE_TX_SCRIPT "${SCRIPTS_DIR}/generate_tx_classes.py")
|
||||
set(GENERATE_LEDGER_SCRIPT "${SCRIPTS_DIR}/generate_ledger_classes.py")
|
||||
set(REQUIREMENTS_FILE "${SCRIPTS_DIR}/requirements.txt")
|
||||
set(MACRO_PARSER_COMMON "${SCRIPTS_DIR}/macro_parser_common.py")
|
||||
set(TX_TEMPLATE "${SCRIPTS_DIR}/templates/Transaction.h.mako")
|
||||
set(TX_TEST_TEMPLATE "${SCRIPTS_DIR}/templates/TransactionTests.cpp.mako")
|
||||
set(LEDGER_TEMPLATE "${SCRIPTS_DIR}/templates/LedgerEntry.h.mako")
|
||||
set(LEDGER_TEST_TEMPLATE
|
||||
"${SCRIPTS_DIR}/templates/LedgerEntryTests.cpp.mako"
|
||||
# Python scripts and templates
|
||||
set(GENERATE_TX_SCRIPT "${SCRIPTS_DIR}/generate_tx_classes.py")
|
||||
set(GENERATE_LEDGER_SCRIPT "${SCRIPTS_DIR}/generate_ledger_classes.py")
|
||||
set(REQUIREMENTS_FILE "${SCRIPTS_DIR}/requirements.txt")
|
||||
set(MACRO_PARSER_COMMON "${SCRIPTS_DIR}/macro_parser_common.py")
|
||||
set(TX_TEMPLATE "${SCRIPTS_DIR}/templates/Transaction.h.mako")
|
||||
set(TX_TEST_TEMPLATE "${SCRIPTS_DIR}/templates/TransactionTests.cpp.mako")
|
||||
set(LEDGER_TEMPLATE "${SCRIPTS_DIR}/templates/LedgerEntry.h.mako")
|
||||
set(LEDGER_TEST_TEMPLATE "${SCRIPTS_DIR}/templates/LedgerEntryTests.cpp.mako")
|
||||
set(ALL_INPUT_FILES
|
||||
"${TRANSACTIONS_MACRO}"
|
||||
"${LEDGER_ENTRIES_MACRO}"
|
||||
"${SFIELDS_MACRO}"
|
||||
"${GENERATE_TX_SCRIPT}"
|
||||
"${GENERATE_LEDGER_SCRIPT}"
|
||||
"${REQUIREMENTS_FILE}"
|
||||
"${MACRO_PARSER_COMMON}"
|
||||
"${TX_TEMPLATE}"
|
||||
"${TX_TEST_TEMPLATE}"
|
||||
"${LEDGER_TEMPLATE}"
|
||||
"${LEDGER_TEST_TEMPLATE}"
|
||||
)
|
||||
|
||||
# Create output directories
|
||||
file(MAKE_DIRECTORY "${AUTOGEN_HEADER_DIR}/transactions")
|
||||
file(MAKE_DIRECTORY "${AUTOGEN_HEADER_DIR}/ledger_entries")
|
||||
file(MAKE_DIRECTORY "${AUTOGEN_TEST_DIR}/ledger_entries")
|
||||
file(MAKE_DIRECTORY "${AUTOGEN_TEST_DIR}/transactions")
|
||||
|
||||
# Find Python3
|
||||
if(NOT Python3_EXECUTABLE)
|
||||
find_package(Python3 COMPONENTS Interpreter QUIET)
|
||||
endif()
|
||||
|
||||
if(NOT Python3_EXECUTABLE)
|
||||
find_program(Python3_EXECUTABLE NAMES python3 python)
|
||||
endif()
|
||||
|
||||
if(NOT Python3_EXECUTABLE)
|
||||
message(
|
||||
WARNING
|
||||
"Python3 not found. The 'code_gen' and 'setup_code_gen' targets will not be available."
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Check if code generation is disabled
|
||||
if(XRPL_NO_CODEGEN)
|
||||
# Warn if pip is configured with a non-default index (may need VPN).
|
||||
execute_process(
|
||||
COMMAND ${Python3_EXECUTABLE} -m pip config get global.index-url
|
||||
OUTPUT_VARIABLE PIP_INDEX_URL
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET
|
||||
RESULT_VARIABLE PIP_CONFIG_RESULT
|
||||
)
|
||||
if(PIP_CONFIG_RESULT EQUAL 0 AND PIP_INDEX_URL)
|
||||
if(
|
||||
NOT PIP_INDEX_URL STREQUAL "https://pypi.org/simple"
|
||||
AND NOT PIP_INDEX_URL STREQUAL "https://pypi.python.org/simple"
|
||||
)
|
||||
message(
|
||||
WARNING
|
||||
"Protocol autogen: Code generation is disabled (XRPL_NO_CODEGEN=ON). "
|
||||
"Generated files may be out of date."
|
||||
"Private pip index URL detected: ${PIP_INDEX_URL}\n"
|
||||
"You may need to connect to VPN to access this URL."
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Create output directories
|
||||
file(MAKE_DIRECTORY "${AUTOGEN_HEADER_DIR}/transactions")
|
||||
file(MAKE_DIRECTORY "${AUTOGEN_HEADER_DIR}/ledger_entries")
|
||||
file(MAKE_DIRECTORY "${AUTOGEN_TEST_DIR}/ledger_entries")
|
||||
file(MAKE_DIRECTORY "${AUTOGEN_TEST_DIR}/transactions")
|
||||
|
||||
# Find Python3 - check if already found by Conan or find it ourselves
|
||||
if(NOT Python3_EXECUTABLE)
|
||||
find_package(Python3 COMPONENTS Interpreter QUIET)
|
||||
endif()
|
||||
|
||||
if(NOT Python3_EXECUTABLE)
|
||||
# Try finding python3 executable directly
|
||||
find_program(Python3_EXECUTABLE NAMES python3 python)
|
||||
endif()
|
||||
|
||||
if(NOT Python3_EXECUTABLE)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Python3 not found. Code generation cannot proceed.\n"
|
||||
"Please install Python 3, or set -DXRPL_NO_CODEGEN=ON to use existing generated files."
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "Using Python3 for code generation: ${Python3_EXECUTABLE}")
|
||||
|
||||
# Set up Python virtual environment for code generation
|
||||
if(CODEGEN_VENV_DIR)
|
||||
# User-provided venv - skip automatic setup
|
||||
set(VENV_DIR "${CODEGEN_VENV_DIR}")
|
||||
message(STATUS "Using user-provided Python venv: ${VENV_DIR}")
|
||||
else()
|
||||
# Use default venv in build directory
|
||||
set(VENV_DIR "${CMAKE_CURRENT_BINARY_DIR}/codegen_venv")
|
||||
endif()
|
||||
|
||||
# Determine the Python executable path in the venv
|
||||
# Determine which Python interpreter to use for code generation.
|
||||
if(CODEGEN_VENV_DIR)
|
||||
if(WIN32)
|
||||
set(VENV_PYTHON "${VENV_DIR}/Scripts/python.exe")
|
||||
set(VENV_PIP "${VENV_DIR}/Scripts/pip.exe")
|
||||
set(CODEGEN_PYTHON "${CODEGEN_VENV_DIR}/Scripts/python.exe")
|
||||
else()
|
||||
set(VENV_PYTHON "${VENV_DIR}/bin/python")
|
||||
set(VENV_PIP "${VENV_DIR}/bin/pip")
|
||||
set(CODEGEN_PYTHON "${CODEGEN_VENV_DIR}/bin/python")
|
||||
endif()
|
||||
|
||||
# Only auto-setup venv if not user-provided
|
||||
if(NOT CODEGEN_VENV_DIR)
|
||||
# Check if venv needs to be created or updated
|
||||
set(VENV_NEEDS_UPDATE FALSE)
|
||||
if(NOT EXISTS "${VENV_PYTHON}")
|
||||
set(VENV_NEEDS_UPDATE TRUE)
|
||||
message(
|
||||
STATUS
|
||||
"Creating Python virtual environment for code generation..."
|
||||
)
|
||||
elseif(
|
||||
"${REQUIREMENTS_FILE}"
|
||||
IS_NEWER_THAN
|
||||
"${VENV_DIR}/.requirements_installed"
|
||||
)
|
||||
set(VENV_NEEDS_UPDATE TRUE)
|
||||
message(
|
||||
STATUS
|
||||
"Updating Python virtual environment (requirements changed)..."
|
||||
)
|
||||
endif()
|
||||
|
||||
# Create/update virtual environment if needed
|
||||
if(VENV_NEEDS_UPDATE)
|
||||
message(
|
||||
STATUS
|
||||
"Setting up Python virtual environment at ${VENV_DIR}"
|
||||
)
|
||||
execute_process(
|
||||
COMMAND ${Python3_EXECUTABLE} -m venv "${VENV_DIR}"
|
||||
RESULT_VARIABLE VENV_RESULT
|
||||
ERROR_VARIABLE VENV_ERROR
|
||||
)
|
||||
if(NOT VENV_RESULT EQUAL 0)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Failed to create virtual environment: ${VENV_ERROR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Check pip index URL configuration
|
||||
execute_process(
|
||||
COMMAND ${VENV_PIP} config get global.index-url
|
||||
OUTPUT_VARIABLE PIP_INDEX_URL
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET
|
||||
)
|
||||
|
||||
# Default PyPI URL
|
||||
set(DEFAULT_PIP_INDEX "https://pypi.org/simple")
|
||||
|
||||
# Show warning if using non-default index
|
||||
if(PIP_INDEX_URL AND NOT PIP_INDEX_URL STREQUAL "")
|
||||
if(NOT PIP_INDEX_URL STREQUAL DEFAULT_PIP_INDEX)
|
||||
message(
|
||||
WARNING
|
||||
"Private pip index URL detected: ${PIP_INDEX_URL}\n"
|
||||
"You may need to connect to VPN to access this URL."
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message(STATUS "Installing Python dependencies...")
|
||||
execute_process(
|
||||
COMMAND ${VENV_PIP} install --upgrade pip
|
||||
RESULT_VARIABLE PIP_UPGRADE_RESULT
|
||||
OUTPUT_QUIET
|
||||
ERROR_VARIABLE PIP_UPGRADE_ERROR
|
||||
)
|
||||
if(NOT PIP_UPGRADE_RESULT EQUAL 0)
|
||||
message(WARNING "Failed to upgrade pip: ${PIP_UPGRADE_ERROR}")
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${VENV_PIP} install -r "${REQUIREMENTS_FILE}"
|
||||
RESULT_VARIABLE PIP_INSTALL_RESULT
|
||||
ERROR_VARIABLE PIP_INSTALL_ERROR
|
||||
)
|
||||
if(NOT PIP_INSTALL_RESULT EQUAL 0)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Failed to install Python dependencies: ${PIP_INSTALL_ERROR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Mark requirements as installed
|
||||
file(TOUCH "${VENV_DIR}/.requirements_installed")
|
||||
message(STATUS "Python virtual environment ready")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# At configure time - get list of output files for transactions
|
||||
execute_process(
|
||||
COMMAND
|
||||
${VENV_PYTHON} "${GENERATE_TX_SCRIPT}" "${TRANSACTIONS_MACRO}"
|
||||
--header-dir "${AUTOGEN_HEADER_DIR}/transactions" --test-dir
|
||||
"${AUTOGEN_TEST_DIR}/transactions" --list-outputs
|
||||
OUTPUT_VARIABLE TX_OUTPUT_FILES
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE TX_LIST_RESULT
|
||||
ERROR_VARIABLE TX_LIST_ERROR
|
||||
else()
|
||||
set(CODEGEN_PYTHON "${Python3_EXECUTABLE}")
|
||||
message(
|
||||
WARNING
|
||||
"CODEGEN_VENV_DIR is not set. Dependencies will be installed globally.\n"
|
||||
"If this is not intended, reconfigure with:\n"
|
||||
" cmake . -UCODEGEN_VENV_DIR"
|
||||
)
|
||||
if(NOT TX_LIST_RESULT EQUAL 0)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Failed to list transaction output files:\n${TX_LIST_ERROR}"
|
||||
)
|
||||
endif()
|
||||
# Convert newline-separated list to CMake list
|
||||
string(REPLACE "\\" "/" TX_OUTPUT_FILES "${TX_OUTPUT_FILES}")
|
||||
string(REPLACE "\n" ";" TX_OUTPUT_FILES "${TX_OUTPUT_FILES}")
|
||||
endif()
|
||||
|
||||
# At configure time - get list of output files for ledger entries
|
||||
execute_process(
|
||||
COMMAND
|
||||
${VENV_PYTHON} "${GENERATE_LEDGER_SCRIPT}" "${LEDGER_ENTRIES_MACRO}"
|
||||
--header-dir "${AUTOGEN_HEADER_DIR}/ledger_entries" --test-dir
|
||||
"${AUTOGEN_TEST_DIR}/ledger_entries" --list-outputs
|
||||
OUTPUT_VARIABLE LEDGER_OUTPUT_FILES
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE LEDGER_LIST_RESULT
|
||||
ERROR_VARIABLE LEDGER_LIST_ERROR
|
||||
)
|
||||
if(NOT LEDGER_LIST_RESULT EQUAL 0)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Failed to list ledger entry output files:\n${LEDGER_LIST_ERROR}"
|
||||
)
|
||||
endif()
|
||||
# Convert newline-separated list to CMake list
|
||||
string(REPLACE "\\" "/" LEDGER_OUTPUT_FILES "${LEDGER_OUTPUT_FILES}")
|
||||
string(REPLACE "\n" ";" LEDGER_OUTPUT_FILES "${LEDGER_OUTPUT_FILES}")
|
||||
|
||||
# Custom command to generate transaction classes at build time
|
||||
add_custom_command(
|
||||
OUTPUT ${TX_OUTPUT_FILES}
|
||||
COMMAND
|
||||
${VENV_PYTHON} "${GENERATE_TX_SCRIPT}" "${TRANSACTIONS_MACRO}"
|
||||
--header-dir "${AUTOGEN_HEADER_DIR}/transactions" --test-dir
|
||||
"${AUTOGEN_TEST_DIR}/transactions" --sfields-macro
|
||||
"${SFIELDS_MACRO}"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
DEPENDS
|
||||
"${TRANSACTIONS_MACRO}"
|
||||
"${SFIELDS_MACRO}"
|
||||
"${GENERATE_TX_SCRIPT}"
|
||||
"${MACRO_PARSER_COMMON}"
|
||||
"${TX_TEMPLATE}"
|
||||
"${TX_TEST_TEMPLATE}"
|
||||
"${REQUIREMENTS_FILE}"
|
||||
COMMENT "Generating transaction classes from transactions.macro..."
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
# Custom command to generate ledger entry classes at build time
|
||||
add_custom_command(
|
||||
OUTPUT ${LEDGER_OUTPUT_FILES}
|
||||
COMMAND
|
||||
${VENV_PYTHON} "${GENERATE_LEDGER_SCRIPT}" "${LEDGER_ENTRIES_MACRO}"
|
||||
--header-dir "${AUTOGEN_HEADER_DIR}/ledger_entries" --test-dir
|
||||
"${AUTOGEN_TEST_DIR}/ledger_entries" --sfields-macro
|
||||
"${SFIELDS_MACRO}"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
DEPENDS
|
||||
"${LEDGER_ENTRIES_MACRO}"
|
||||
"${SFIELDS_MACRO}"
|
||||
"${GENERATE_LEDGER_SCRIPT}"
|
||||
"${MACRO_PARSER_COMMON}"
|
||||
"${LEDGER_TEMPLATE}"
|
||||
"${LEDGER_TEST_TEMPLATE}"
|
||||
"${REQUIREMENTS_FILE}"
|
||||
COMMENT "Generating ledger entry classes from ledger_entries.macro..."
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
# Create a custom target that depends on all generated files
|
||||
# Custom target to create a venv and install Python dependencies.
|
||||
# Run manually with: cmake --build . --target setup_code_gen
|
||||
if(CODEGEN_VENV_DIR)
|
||||
add_custom_target(
|
||||
protocol_autogen_generate
|
||||
DEPENDS ${TX_OUTPUT_FILES} ${LEDGER_OUTPUT_FILES}
|
||||
COMMENT "Protocol autogen code generation"
|
||||
setup_code_gen
|
||||
COMMAND ${Python3_EXECUTABLE} -m venv "${CODEGEN_VENV_DIR}"
|
||||
COMMAND ${CODEGEN_PYTHON} -m pip install -r "${REQUIREMENTS_FILE}"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
COMMENT "Creating venv and installing code generation dependencies..."
|
||||
)
|
||||
else()
|
||||
add_custom_target(
|
||||
setup_code_gen
|
||||
COMMAND ${Python3_EXECUTABLE} -m pip install -r "${REQUIREMENTS_FILE}"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
COMMENT "Installing code generation dependencies..."
|
||||
)
|
||||
endif()
|
||||
|
||||
# Extract test files from output lists (files ending in Tests.cpp)
|
||||
set(PROTOCOL_AUTOGEN_TEST_SOURCES "")
|
||||
foreach(FILE ${TX_OUTPUT_FILES} ${LEDGER_OUTPUT_FILES})
|
||||
if(FILE MATCHES "Tests\\.cpp$")
|
||||
list(APPEND PROTOCOL_AUTOGEN_TEST_SOURCES "${FILE}")
|
||||
endif()
|
||||
endforeach()
|
||||
# Export test sources to parent scope for use in test CMakeLists.txt
|
||||
set(PROTOCOL_AUTOGEN_TEST_SOURCES
|
||||
"${PROTOCOL_AUTOGEN_TEST_SOURCES}"
|
||||
CACHE INTERNAL
|
||||
"Generated protocol_autogen test sources"
|
||||
)
|
||||
|
||||
# Register dependencies so CMake reconfigures when macro files change
|
||||
# (to update the list of output files)
|
||||
set_property(
|
||||
DIRECTORY
|
||||
APPEND
|
||||
PROPERTY
|
||||
CMAKE_CONFIGURE_DEPENDS
|
||||
"${TRANSACTIONS_MACRO}"
|
||||
"${LEDGER_ENTRIES_MACRO}"
|
||||
)
|
||||
endfunction()
|
||||
# Custom target for code generation, excluded from ALL.
|
||||
# Run manually with: cmake --build . --target code_gen
|
||||
add_custom_target(
|
||||
code_gen
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -DCODEGEN_PYTHON=${CODEGEN_PYTHON}
|
||||
-DGENERATE_TX_SCRIPT=${GENERATE_TX_SCRIPT}
|
||||
-DGENERATE_LEDGER_SCRIPT=${GENERATE_LEDGER_SCRIPT}
|
||||
-DTRANSACTIONS_MACRO=${TRANSACTIONS_MACRO}
|
||||
-DLEDGER_ENTRIES_MACRO=${LEDGER_ENTRIES_MACRO}
|
||||
-DSFIELDS_MACRO=${SFIELDS_MACRO}
|
||||
-DAUTOGEN_HEADER_DIR=${AUTOGEN_HEADER_DIR}
|
||||
-DAUTOGEN_TEST_DIR=${AUTOGEN_TEST_DIR} -P
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/XrplProtocolAutogenRun.cmake"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
COMMENT "Running protocol code generation..."
|
||||
SOURCES ${ALL_INPUT_FILES}
|
||||
)
|
||||
|
||||
39
cmake/XrplProtocolAutogenRun.cmake
Normal file
39
cmake/XrplProtocolAutogenRun.cmake
Normal file
@@ -0,0 +1,39 @@
|
||||
#[===================================================================[
|
||||
Protocol Autogen - Run script invoked by the 'code_gen' target
|
||||
#]===================================================================]
|
||||
|
||||
# Generate transaction classes.
|
||||
execute_process(
|
||||
COMMAND
|
||||
${CODEGEN_PYTHON} "${GENERATE_TX_SCRIPT}" "${TRANSACTIONS_MACRO}"
|
||||
--header-dir "${AUTOGEN_HEADER_DIR}/transactions" --test-dir
|
||||
"${AUTOGEN_TEST_DIR}/transactions" --sfields-macro "${SFIELDS_MACRO}"
|
||||
RESULT_VARIABLE TX_RESULT
|
||||
OUTPUT_VARIABLE TX_OUTPUT
|
||||
ERROR_VARIABLE TX_ERROR
|
||||
)
|
||||
if(NOT TX_RESULT EQUAL 0)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Transaction code generation failed:\n${TX_OUTPUT}\n${TX_ERROR}\n${TX_RESULT}"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Generate ledger entry classes.
|
||||
execute_process(
|
||||
COMMAND
|
||||
${CODEGEN_PYTHON} "${GENERATE_LEDGER_SCRIPT}" "${LEDGER_ENTRIES_MACRO}"
|
||||
--header-dir "${AUTOGEN_HEADER_DIR}/ledger_entries" --test-dir
|
||||
"${AUTOGEN_TEST_DIR}/ledger_entries" --sfields-macro "${SFIELDS_MACRO}"
|
||||
RESULT_VARIABLE LEDGER_RESULT
|
||||
OUTPUT_VARIABLE LEDGER_OUTPUT
|
||||
ERROR_VARIABLE LEDGER_ERROR
|
||||
)
|
||||
if(NOT LEDGER_RESULT EQUAL 0)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Ledger entry code generation failed:\n${LEDGER_OUTPUT}\n${LEDGER_ERROR}\n${TX_RESULT}"
|
||||
)
|
||||
endif()
|
||||
|
||||
message(STATUS "Protocol autogen: code generation complete")
|
||||
@@ -138,28 +138,12 @@ def main():
|
||||
"--sfields-macro",
|
||||
help="Path to sfields.macro (default: auto-detect from macro_path)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--list-outputs",
|
||||
action="store_true",
|
||||
help="List output files without generating (one per line)",
|
||||
)
|
||||
|
||||
parser.add_argument("--venv-dir", help=argparse.SUPPRESS)
|
||||
args = parser.parse_args()
|
||||
|
||||
# Parse the macro file to get ledger entry names
|
||||
entries = parse_macro_file(args.macro_path)
|
||||
|
||||
# If --list-outputs, just print the output file paths and exit
|
||||
if args.list_outputs:
|
||||
header_dir = Path(args.header_dir)
|
||||
for entry in entries:
|
||||
print(header_dir / f"{entry['name']}.h")
|
||||
if args.test_dir:
|
||||
test_dir = Path(args.test_dir)
|
||||
for entry in entries:
|
||||
print(test_dir / f"{entry['name']}Tests.cpp")
|
||||
return
|
||||
|
||||
# Auto-detect sfields.macro path if not provided
|
||||
if args.sfields_macro:
|
||||
sfields_path = Path(args.sfields_macro)
|
||||
@@ -147,28 +147,12 @@ def main():
|
||||
"--sfields-macro",
|
||||
help="Path to sfields.macro (default: auto-detect from macro_path)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--list-outputs",
|
||||
action="store_true",
|
||||
help="List output files without generating (one per line)",
|
||||
)
|
||||
|
||||
parser.add_argument("--venv-dir", help=argparse.SUPPRESS)
|
||||
args = parser.parse_args()
|
||||
|
||||
# Parse the macro file to get transaction names
|
||||
transactions = parse_macro_file(args.macro_path)
|
||||
|
||||
# If --list-outputs, just print the output file paths and exit
|
||||
if args.list_outputs:
|
||||
header_dir = Path(args.header_dir)
|
||||
for tx in transactions:
|
||||
print(header_dir / f"{tx['name']}.h")
|
||||
if args.test_dir:
|
||||
test_dir = Path(args.test_dir)
|
||||
for tx in transactions:
|
||||
print(test_dir / f"{tx['name']}Tests.cpp")
|
||||
return
|
||||
|
||||
# Auto-detect sfields.macro path if not provided
|
||||
if args.sfields_macro:
|
||||
sfields_path = Path(args.sfields_macro)
|
||||
@@ -44,6 +44,10 @@ suggestWords:
|
||||
words:
|
||||
- abempty
|
||||
- AMMID
|
||||
- AMMMPT
|
||||
- AMMMPToken
|
||||
- AMMMPTokens
|
||||
- AMMXRP
|
||||
- amt
|
||||
- amts
|
||||
- asnode
|
||||
@@ -96,6 +100,7 @@ words:
|
||||
- distro
|
||||
- doxyfile
|
||||
- dxrpl
|
||||
- enabled
|
||||
- endmacro
|
||||
- exceptioned
|
||||
- Falco
|
||||
@@ -148,6 +153,8 @@ words:
|
||||
- ltype
|
||||
- mcmodel
|
||||
- MEMORYSTATUSEX
|
||||
- MPTAMM
|
||||
- MPTDEX
|
||||
- Merkle
|
||||
- Metafuncton
|
||||
- misprediction
|
||||
@@ -157,6 +164,7 @@ words:
|
||||
- mptid
|
||||
- mptissuance
|
||||
- mptissuanceid
|
||||
- mptissue
|
||||
- mptoken
|
||||
- mptokenid
|
||||
- mptokenissuance
|
||||
|
||||
@@ -558,7 +558,7 @@ network delay. A test case specifies:
|
||||
1. a UNL with different number of validators for different test cases,
|
||||
1. a network with zero or more non-validator nodes,
|
||||
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),
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
[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
|
||||
as in the paper: [Analysis of the XRP Ledger Consensus
|
||||
Protocol](https://arxiv.org/abs/1802.07242).
|
||||
|
||||
@@ -4,7 +4,7 @@ skinparam sequenceArrowThickness 2
|
||||
skinparam roundcorner 20
|
||||
skinparam maxmessagesize 160
|
||||
|
||||
actor "Rippled Start" as RS
|
||||
actor "Xrpld Start" as RS
|
||||
participant "Timer" as T
|
||||
participant "NetworkOPs" as NOP
|
||||
participant "ValidatorList" as VL #lightgreen
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# `rippled` Docker Image
|
||||
# `xrpld` Docker Image
|
||||
|
||||
- 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/)
|
||||
- These images do not have rippled. They have all the tools necessary to build rippled.
|
||||
- Images for building and testing xrpld can be found here: [thejohnfreeman/rippled-docker](https://github.com/thejohnfreeman/rippled-docker/)
|
||||
- These images do not have xrpld. They have all the tools necessary to build xrpld.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "rippled"
|
||||
PROJECT_NAME = "xrpld"
|
||||
PROJECT_NUMBER =
|
||||
PROJECT_BRIEF =
|
||||
PROJECT_LOGO =
|
||||
|
||||
@@ -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,
|
||||
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:
|
||||
[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
|
||||
source release with default options, it will install the library and header
|
||||
under `/usr/local/lib` and `/usr/local/include`, respectively. Heap
|
||||
profiling has been tested with rippled on a Linux platform. It should
|
||||
work on platforms on which both rippled and jemalloc are available.
|
||||
profiling has been tested with xrpld on a Linux platform. It should
|
||||
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.
|
||||
The `<jemalloc_dir>` argument should be the same as that of the
|
||||
`--prefix` parameter passed to the jemalloc configure script when building.
|
||||
|
||||
## 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:
|
||||
|
||||
$ 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:
|
||||
|
||||
$ scons clang profile-jemalloc=/opt/local
|
||||
|
||||
@@ -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`.
|
||||
8
docs/build/depend.md
vendored
8
docs/build/depend.md
vendored
@@ -20,7 +20,7 @@ CMakeToolchain
|
||||
|
||||
```
|
||||
# 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>
|
||||
```
|
||||
|
||||
@@ -49,9 +49,9 @@ cmake --build . --parallel
|
||||
|
||||
## 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].
|
||||
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][].
|
||||
It's good for when you want to make changes to libxrpl as part of your own
|
||||
project.
|
||||
@@ -90,6 +90,6 @@ cmake --build . --parallel
|
||||
|
||||
[add_subdirectory]: https://cmake.org/cmake/help/latest/command/add_subdirectory.html
|
||||
[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/
|
||||
[CMake]: https://cmake.org/cmake/help/latest/
|
||||
|
||||
2
docs/build/environment.md
vendored
2
docs/build/environment.md
vendored
@@ -55,7 +55,7 @@ clang --version
|
||||
### Install Xcode Specific Version (Optional)
|
||||
|
||||
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**
|
||||
- Visit [Apple Developer Downloads](https://developer.apple.com/download/more/)
|
||||
|
||||
58
docs/build/install.md
vendored
58
docs/build/install.md
vendored
@@ -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
|
||||
Ubuntu,
|
||||
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 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:
|
||||
|
||||
```
|
||||
@@ -16,7 +16,7 @@ cmake --install . --prefix /opt/local
|
||||
```
|
||||
|
||||
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
|
||||
|
||||
@@ -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`.)
|
||||
|
||||
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
|
||||
|
||||
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**
|
||||
- `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`:
|
||||
- `unstable` - Pre-release builds ([`release` branch](https://github.com/ripple/rippled/tree/release))
|
||||
- `nightly` - Experimental/development builds ([`develop` branch](https://github.com/ripple/rippled/tree/develop))
|
||||
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/XRPLF/rippled/tree/release))
|
||||
- `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.
|
||||
|
||||
6. Fetch the Ripple repository.
|
||||
6. Fetch the XRPL repository.
|
||||
|
||||
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.)
|
||||
|
||||
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
|
||||
|
||||
@@ -106,8 +106,8 @@ The default [prefix][1] is typically `/usr/local` on Linux and macOS and
|
||||
enabled=1
|
||||
gpgcheck=0
|
||||
repo_gpgcheck=1
|
||||
baseurl=https://repos.ripple.com/repos/rippled-rpm/stable/
|
||||
gpgkey=https://repos.ripple.com/repos/rippled-rpm/stable/repodata/repomd.xml.key
|
||||
baseurl=https://repos.ripple.com/repos/xrpld-rpm/stable/
|
||||
gpgkey=https://repos.ripple.com/repos/xrpld-rpm/stable/repodata/repomd.xml.key
|
||||
REPOFILE
|
||||
|
||||
_Unstable_
|
||||
@@ -118,8 +118,8 @@ The default [prefix][1] is typically `/usr/local` on Linux and macOS and
|
||||
enabled=1
|
||||
gpgcheck=0
|
||||
repo_gpgcheck=1
|
||||
baseurl=https://repos.ripple.com/repos/rippled-rpm/unstable/
|
||||
gpgkey=https://repos.ripple.com/repos/rippled-rpm/unstable/repodata/repomd.xml.key
|
||||
baseurl=https://repos.ripple.com/repos/xrpld-rpm/unstable/
|
||||
gpgkey=https://repos.ripple.com/repos/xrpld-rpm/unstable/repodata/repomd.xml.key
|
||||
REPOFILE
|
||||
|
||||
_Nightly_
|
||||
@@ -130,22 +130,22 @@ The default [prefix][1] is typically `/usr/local` on Linux and macOS and
|
||||
enabled=1
|
||||
gpgcheck=0
|
||||
repo_gpgcheck=1
|
||||
baseurl=https://repos.ripple.com/repos/rippled-rpm/nightly/
|
||||
gpgkey=https://repos.ripple.com/repos/rippled-rpm/nightly/repodata/repomd.xml.key
|
||||
baseurl=https://repos.ripple.com/repos/xrpld-rpm/nightly/
|
||||
gpgkey=https://repos.ripple.com/repos/xrpld-rpm/nightly/repodata/repomd.xml.key
|
||||
REPOFILE
|
||||
|
||||
2. Fetch the latest repo updates:
|
||||
|
||||
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
|
||||
|
||||
6
docs/build/sanitizers.md
vendored
6
docs/build/sanitizers.md
vendored
@@ -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.
|
||||
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)
|
||||
- [Summary](#summary)
|
||||
- [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 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.
|
||||
- See: https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow
|
||||
- More such flags are detailed [here](https://github.com/google/sanitizers/wiki/AddressSanitizerFlags)
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
Consensus is the task of reaching agreement within a distributed system in the
|
||||
presence of faulty or even malicious participants. This document outlines the
|
||||
[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
|
||||
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
|
||||
network, or even a fixed network topology, but instead achieves consensus via
|
||||
collectively trusted subnetworks.
|
||||
@@ -15,7 +15,7 @@ collectively trusted subnetworks.
|
||||
## Distributed Agreement
|
||||
|
||||
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
|
||||
refer to shared distributed state as a /ledger/ throughout the remainder of this
|
||||
document.
|
||||
@@ -23,7 +23,7 @@ document.
|
||||

|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
how they integrate within `rippled` to support the Ripple Consensus Ledger.
|
||||
how they integrate within `xrpld` to support the XRPL consensus Ledger.
|
||||
|
||||
## Consensus Overview
|
||||
|
||||
|
||||
2
external/README.md
vendored
2
external/README.md
vendored
@@ -1,6 +1,6 @@
|
||||
# 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 |
|
||||
| :--------------- | :------------------------------------------------------------- | :------------------------------------------------------------------------------------------- |
|
||||
|
||||
4
external/antithesis-sdk/CMakeLists.txt
vendored
4
external/antithesis-sdk/CMakeLists.txt
vendored
@@ -1,11 +1,11 @@
|
||||
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)
|
||||
|
||||
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
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
|
||||
@@ -296,7 +296,7 @@ set(T& target, std::string const& name, Section const& section)
|
||||
if ((found_and_valid = val.has_value()))
|
||||
target = *val;
|
||||
}
|
||||
catch (boost::bad_lexical_cast&)
|
||||
catch (boost::bad_lexical_cast const&) // NOLINT(bugprone-empty-catch)
|
||||
{
|
||||
}
|
||||
return found_and_valid;
|
||||
@@ -330,7 +330,7 @@ get(Section const& section, std::string const& name, T const& defaultValue = T{}
|
||||
{
|
||||
return section.value_or<T>(name, defaultValue);
|
||||
}
|
||||
catch (boost::bad_lexical_cast&)
|
||||
catch (boost::bad_lexical_cast const&) // NOLINT(bugprone-empty-catch)
|
||||
{
|
||||
}
|
||||
return defaultValue;
|
||||
@@ -345,7 +345,7 @@ get(Section const& section, std::string const& name, char const* defaultValue)
|
||||
if (val.has_value())
|
||||
return *val;
|
||||
}
|
||||
catch (boost::bad_lexical_cast&)
|
||||
catch (boost::bad_lexical_cast const&) // NOLINT(bugprone-empty-catch)
|
||||
{
|
||||
}
|
||||
return defaultValue;
|
||||
|
||||
@@ -99,7 +99,7 @@ private:
|
||||
Derived classes have their instances counted automatically. This is used
|
||||
for reporting purposes.
|
||||
|
||||
@ingroup ripple_basics
|
||||
@ingroup basics
|
||||
*/
|
||||
template <class Object>
|
||||
class CountedObject
|
||||
@@ -112,7 +112,6 @@ private:
|
||||
return c;
|
||||
}
|
||||
|
||||
public:
|
||||
CountedObject() noexcept
|
||||
{
|
||||
getCounter().increment();
|
||||
@@ -126,10 +125,13 @@ public:
|
||||
CountedObject&
|
||||
operator=(CountedObject const&) noexcept = default;
|
||||
|
||||
public:
|
||||
~CountedObject() noexcept
|
||||
{
|
||||
getCounter().decrement();
|
||||
}
|
||||
|
||||
friend Object;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -59,7 +59,7 @@ concept CAdoptTag = std::is_same_v<T, SharedIntrusiveAdoptIncrementStrongTag> ||
|
||||
still retaining the reference counts. For example, for SHAMapInnerNodes the
|
||||
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
|
||||
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
|
||||
that is used, the memory is not reclaimed until the weak count reaches zero.
|
||||
*/
|
||||
|
||||
@@ -33,7 +33,7 @@ enum class ReleaseWeakRefAction { noop, destroy };
|
||||
/** Implement the strong count, weak count, and bit flags for an intrusive
|
||||
pointer.
|
||||
|
||||
A class can satisfy the requirements of a xrpl::IntrusivePointer by
|
||||
A class can satisfy the requirements of an xrpl::IntrusivePointer by
|
||||
inheriting from this class.
|
||||
*/
|
||||
struct IntrusiveRefCounts
|
||||
|
||||
@@ -226,7 +226,7 @@ private:
|
||||
// expensive argument lists if the stream is not active.
|
||||
#ifndef JLOG
|
||||
#define JLOG(x) \
|
||||
if (!x) \
|
||||
if (!(x)) \
|
||||
{ \
|
||||
} \
|
||||
else \
|
||||
@@ -235,7 +235,7 @@ private:
|
||||
|
||||
#ifndef CLOG
|
||||
#define CLOG(ss) \
|
||||
if (!ss) \
|
||||
if (!(ss)) \
|
||||
; \
|
||||
else \
|
||||
*ss
|
||||
|
||||
@@ -2,13 +2,19 @@
|
||||
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
#include <concepts>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <boost/multiprecision/cpp_int.hpp>
|
||||
#endif // !defined(_MSC_VER)
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class Number;
|
||||
@@ -16,18 +22,39 @@ class Number;
|
||||
std::string
|
||||
to_string(Number const& amount);
|
||||
|
||||
/** Returns a rough estimate of log10(value).
|
||||
*
|
||||
* The return value is a pair (log, rem), where log is the estimated
|
||||
* base-10 logarithm (roughly floor(log10(value))), and rem is value with
|
||||
* all trailing 0s removed (i.e., divided by the largest power of 10 that
|
||||
* evenly divides value). If rem is 1, then value is an exact power of ten, and
|
||||
* log is the exact log10(value).
|
||||
*
|
||||
* This function only works for positive values.
|
||||
*/
|
||||
template <std::unsigned_integral T>
|
||||
constexpr std::pair<int, T>
|
||||
logTenEstimate(T value)
|
||||
{
|
||||
int log = 0;
|
||||
T remainder = value;
|
||||
while (value >= 10)
|
||||
{
|
||||
if (value % 10 == 0)
|
||||
remainder = remainder / 10;
|
||||
value /= 10;
|
||||
++log;
|
||||
}
|
||||
return {log, remainder};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr std::optional<int>
|
||||
logTen(T value)
|
||||
{
|
||||
int log = 0;
|
||||
while (value >= 10 && value % 10 == 0)
|
||||
{
|
||||
value /= 10;
|
||||
++log;
|
||||
}
|
||||
if (value == 1)
|
||||
return log;
|
||||
auto const est = logTenEstimate(value);
|
||||
if (est.second == 1)
|
||||
return est.first;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
@@ -41,12 +68,10 @@ isPowerOfTen(T value)
|
||||
/** MantissaRange defines a range for the mantissa of a normalized Number.
|
||||
*
|
||||
* The mantissa is in the range [min, max], where
|
||||
* * min is a power of 10, and
|
||||
* * max = min * 10 - 1.
|
||||
*
|
||||
* The mantissa_scale enum indicates whether the range is "small" or "large".
|
||||
* This intentionally restricts the number of MantissaRanges that can be
|
||||
* instantiated to two: one for each scale.
|
||||
* The mantissa_scale enum indicates whether the range is "small" or
|
||||
* "large". This intentionally prevents the creation of any
|
||||
* MantissaRanges representing other values.
|
||||
*
|
||||
* The "small" scale is based on the behavior of STAmount for IOUs. It has a min
|
||||
* value of 10^15, and a max value of 10^16-1. This was sufficient for
|
||||
@@ -60,8 +85,8 @@ isPowerOfTen(T value)
|
||||
* "large" scale.
|
||||
*
|
||||
* The "large" scale is intended to represent all values that can be represented
|
||||
* by an STAmount - IOUs, XRP, and MPTs. It has a min value of 10^18, and a max
|
||||
* value of 10^19-1.
|
||||
* by an STAmount - IOUs, XRP, and MPTs. It has a min value of 2^63/10+1
|
||||
* (truncated), and a max value of 2^63-1.
|
||||
*
|
||||
* Note that if the mentioned amendments are eventually retired, this class
|
||||
* should be left in place, but the "small" scale option should be removed. This
|
||||
@@ -73,25 +98,52 @@ struct MantissaRange
|
||||
enum mantissa_scale { small, large };
|
||||
|
||||
explicit constexpr MantissaRange(mantissa_scale scale_)
|
||||
: min(getMin(scale_)), log(logTen(min).value_or(-1)), scale(scale_)
|
||||
: max(getMax(scale_)), internalMin(getInternalMin(scale_, min)), scale(scale_)
|
||||
{
|
||||
// Keep the error messages terse. Since this is constexpr, if any of these throw, it won't
|
||||
// compile, so there's no real need to worry about runtime exceptions here.
|
||||
if (min * 10 <= max)
|
||||
throw std::out_of_range("Invalid mantissa range: min * 10 <= max");
|
||||
if (max / 10 >= min)
|
||||
throw std::out_of_range("Invalid mantissa range: max / 10 >= min");
|
||||
if ((min - 1) * 10 > max)
|
||||
throw std::out_of_range("Invalid mantissa range: (min - 1) * 10 > max");
|
||||
// This is a little hacky
|
||||
if ((max + 10) / 10 < min)
|
||||
throw std::out_of_range("Invalid mantissa range: (max + 10) / 10 < min");
|
||||
if (computeLog(internalMin) != log)
|
||||
throw std::out_of_range("Invalid mantissa range: computeLog(internalMin) != log");
|
||||
}
|
||||
|
||||
rep min;
|
||||
rep max{min * 10 - 1};
|
||||
int log;
|
||||
// Explicitly delete copy and move operations
|
||||
MantissaRange(MantissaRange const&) = delete;
|
||||
MantissaRange(MantissaRange&&) = delete;
|
||||
MantissaRange&
|
||||
operator=(MantissaRange const&) = delete;
|
||||
MantissaRange&
|
||||
operator=(MantissaRange&&) = delete;
|
||||
|
||||
rep max;
|
||||
rep min{computeMin(max)};
|
||||
/* Used to determine if mantissas are in range, but have fewer digits than max.
|
||||
*
|
||||
* Unlike min, internalMin is always an exact power of 10, so a mantissa in the internal
|
||||
* representation will always have a consistent number of digits.
|
||||
*/
|
||||
rep internalMin;
|
||||
rep log{computeLog(min)};
|
||||
mantissa_scale scale;
|
||||
|
||||
private:
|
||||
static constexpr rep
|
||||
getMin(mantissa_scale scale_)
|
||||
getMax(mantissa_scale scale)
|
||||
{
|
||||
switch (scale_)
|
||||
switch (scale)
|
||||
{
|
||||
case small:
|
||||
return 1'000'000'000'000'000ULL;
|
||||
return 9'999'999'999'999'999ULL;
|
||||
case large:
|
||||
return 1'000'000'000'000'000'000ULL;
|
||||
return std::numeric_limits<std::int64_t>::max();
|
||||
default:
|
||||
// Since this can never be called outside a non-constexpr
|
||||
// context, this throw assures that the build fails if an
|
||||
@@ -99,19 +151,59 @@ private:
|
||||
throw std::runtime_error("Unknown mantissa scale");
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr rep
|
||||
computeMin(rep max)
|
||||
{
|
||||
return max / 10 + 1;
|
||||
}
|
||||
|
||||
static constexpr rep
|
||||
getInternalMin(mantissa_scale scale, rep min)
|
||||
{
|
||||
switch (scale)
|
||||
{
|
||||
case large:
|
||||
return 1'000'000'000'000'000'000ULL;
|
||||
default:
|
||||
if (isPowerOfTen(min))
|
||||
return min;
|
||||
throw std::runtime_error("Unknown/bad mantissa scale");
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr rep
|
||||
computeLog(rep min)
|
||||
{
|
||||
auto const estimate = logTenEstimate(min);
|
||||
return estimate.first + (estimate.second == 1 ? 0 : 1);
|
||||
}
|
||||
};
|
||||
|
||||
// Like std::integral, but only 64-bit integral types.
|
||||
template <class T>
|
||||
concept Integral64 = std::is_same_v<T, std::int64_t> || std::is_same_v<T, std::uint64_t>;
|
||||
|
||||
namespace detail {
|
||||
#ifdef _MSC_VER
|
||||
using uint128_t = boost::multiprecision::uint128_t;
|
||||
using int128_t = boost::multiprecision::int128_t;
|
||||
#else // !defined(_MSC_VER)
|
||||
using uint128_t = __uint128_t;
|
||||
using int128_t = __int128_t;
|
||||
#endif // !defined(_MSC_VER)
|
||||
|
||||
template <class T>
|
||||
concept UnsignedMantissa = std::is_unsigned_v<T> || std::is_same_v<T, uint128_t>;
|
||||
} // namespace detail
|
||||
|
||||
/** Number is a floating point type that can represent a wide range of values.
|
||||
*
|
||||
* It can represent all values that can be represented by an STAmount -
|
||||
* regardless of asset type - XRPAmount, MPTAmount, and IOUAmount, with at least
|
||||
* as much precision as those types require.
|
||||
*
|
||||
* ---- Internal Representation ----
|
||||
* ---- Internal Operational Representation ----
|
||||
*
|
||||
* Internally, Number is represented with three values:
|
||||
* 1. a bool sign flag,
|
||||
@@ -126,15 +218,21 @@ concept Integral64 = std::is_same_v<T, std::int64_t> || std::is_same_v<T, std::u
|
||||
*
|
||||
* A non-zero mantissa is (almost) always normalized, meaning it and the
|
||||
* exponent are grown or shrunk until the mantissa is in the range
|
||||
* [MantissaRange.min, MantissaRange.max].
|
||||
* [MantissaRange.internalMin, MantissaRange.internalMin * 10 - 1].
|
||||
*
|
||||
* This internal representation is only used during some operations to ensure
|
||||
* that the mantissa is a known, predictable size. The class itself stores the
|
||||
* values using the external representation described below.
|
||||
*
|
||||
* Note:
|
||||
* 1. Normalization can be disabled by using the "unchecked" ctor tag. This
|
||||
* should only be used at specific conversion points, some constexpr
|
||||
* values, and in unit tests.
|
||||
* 2. The max of the "large" range, 10^19-1, is the largest 10^X-1 value that
|
||||
* fits in an unsigned 64-bit number. (10^19-1 < 2^64-1 and
|
||||
* 10^20-1 > 2^64-1). This avoids under- and overflows.
|
||||
* 2. Unlike MantissaRange.min, internalMin is always an exact power of 10,
|
||||
* so a mantissa in the internal representation will always have a
|
||||
* consistent number of digits.
|
||||
* 3. The functions toInternal() and fromInternal() are used to convert
|
||||
* between the two representations.
|
||||
*
|
||||
* ---- External Interface ----
|
||||
*
|
||||
@@ -147,13 +245,12 @@ concept Integral64 = std::is_same_v<T, std::int64_t> || std::is_same_v<T, std::u
|
||||
* represent the full range of valid XRP and MPT integer values accurately.
|
||||
*
|
||||
* Note:
|
||||
* 1. 2^63-1 is between 10^18 and 10^19-1, which are the limits of the "large"
|
||||
* mantissa range.
|
||||
* 1. The "large" mantissa range is (2^63/10+1) to 2^63-1. 2^63-1 is between
|
||||
* 10^18 and 10^19-1, and (2^63/10+1) is between 10^17 and 10^18-1. Thus,
|
||||
* the mantissa may have 18 or 19 digits. This value will be modified to
|
||||
* always have 19 digits before some operations to ensure consistency.
|
||||
* 2. The functions mantissa() and exponent() return the external view of the
|
||||
* Number value, specifically using a signed 63-bit mantissa. This may
|
||||
* require altering the internal representation to fit into that range
|
||||
* before the value is returned. The interface guarantees consistency of
|
||||
* the two values.
|
||||
* Number value, specifically using a signed 63-bit mantissa.
|
||||
* 3. Number cannot represent -2^63 (std::numeric_limits<std::int64_t>::min())
|
||||
* as an exact integer, but it doesn't need to, because all asset values
|
||||
* on-ledger are non-negative. This is due to implementation details of
|
||||
@@ -208,8 +305,7 @@ class Number
|
||||
using rep = std::int64_t;
|
||||
using internalrep = MantissaRange::rep;
|
||||
|
||||
bool negative_{false};
|
||||
internalrep mantissa_{0};
|
||||
rep mantissa_{0};
|
||||
int exponent_{std::numeric_limits<int>::lowest()};
|
||||
|
||||
public:
|
||||
@@ -217,10 +313,6 @@ public:
|
||||
constexpr static int minExponent = -32768;
|
||||
constexpr static int maxExponent = 32768;
|
||||
|
||||
constexpr static internalrep maxRep = std::numeric_limits<rep>::max();
|
||||
static_assert(maxRep == 9'223'372'036'854'775'807);
|
||||
static_assert(-maxRep == std::numeric_limits<rep>::min() + 1);
|
||||
|
||||
// May need to make unchecked private
|
||||
struct unchecked
|
||||
{
|
||||
@@ -298,8 +390,7 @@ public:
|
||||
friend constexpr bool
|
||||
operator==(Number const& x, Number const& y) noexcept
|
||||
{
|
||||
return x.negative_ == y.negative_ && x.mantissa_ == y.mantissa_ &&
|
||||
x.exponent_ == y.exponent_;
|
||||
return x.mantissa_ == y.mantissa_ && x.exponent_ == y.exponent_;
|
||||
}
|
||||
|
||||
friend constexpr bool
|
||||
@@ -313,8 +404,8 @@ public:
|
||||
{
|
||||
// If the two amounts have different signs (zero is treated as positive)
|
||||
// then the comparison is true iff the left is negative.
|
||||
bool const lneg = x.negative_;
|
||||
bool const rneg = y.negative_;
|
||||
bool const lneg = x.mantissa_ < 0;
|
||||
bool const rneg = y.mantissa_ < 0;
|
||||
|
||||
if (lneg != rneg)
|
||||
return lneg;
|
||||
@@ -342,7 +433,7 @@ public:
|
||||
constexpr int
|
||||
signum() const noexcept
|
||||
{
|
||||
return negative_ ? -1 : (mantissa_ ? 1 : 0);
|
||||
return mantissa_ < 0 ? -1 : (mantissa_ ? 1 : 0);
|
||||
}
|
||||
|
||||
Number
|
||||
@@ -381,6 +472,9 @@ public:
|
||||
friend Number
|
||||
root2(Number f);
|
||||
|
||||
friend Number
|
||||
power(Number const& f, unsigned n, unsigned d);
|
||||
|
||||
// Thread local rounding control. Default is to_nearest
|
||||
enum rounding_mode { to_nearest, towards_zero, downward, upward };
|
||||
static rounding_mode
|
||||
@@ -445,22 +539,39 @@ private:
|
||||
static_assert(isPowerOfTen(smallRange.min));
|
||||
static_assert(smallRange.min == 1'000'000'000'000'000LL);
|
||||
static_assert(smallRange.max == 9'999'999'999'999'999LL);
|
||||
static_assert(smallRange.internalMin == smallRange.min);
|
||||
static_assert(smallRange.log == 15);
|
||||
static_assert(smallRange.min < maxRep);
|
||||
static_assert(smallRange.max < maxRep);
|
||||
constexpr static MantissaRange largeRange{MantissaRange::large};
|
||||
static_assert(isPowerOfTen(largeRange.min));
|
||||
static_assert(largeRange.min == 1'000'000'000'000'000'000ULL);
|
||||
static_assert(largeRange.max == internalrep(9'999'999'999'999'999'999ULL));
|
||||
static_assert(!isPowerOfTen(largeRange.min));
|
||||
static_assert(largeRange.min == 922'337'203'685'477'581ULL);
|
||||
static_assert(largeRange.max == internalrep(9'223'372'036'854'775'807ULL));
|
||||
static_assert(largeRange.max == std::numeric_limits<rep>::max());
|
||||
static_assert(largeRange.internalMin == 1'000'000'000'000'000'000ULL);
|
||||
static_assert(largeRange.log == 18);
|
||||
static_assert(largeRange.min < maxRep);
|
||||
static_assert(largeRange.max > maxRep);
|
||||
// There are 2 values that will not fit in largeRange without some extra
|
||||
// work
|
||||
// * 9223372036854775808
|
||||
// * 9223372036854775809
|
||||
// They both end up < min, but with a leftover. If they round up, everything
|
||||
// will be fine. If they don't, we'll need to bring them up into range.
|
||||
// Guard::bringIntoRange handles this situation.
|
||||
|
||||
// The range for the mantissa when normalized.
|
||||
// Use reference_wrapper to avoid making copies, and prevent accidentally
|
||||
// changing the values inside the range.
|
||||
static thread_local std::reference_wrapper<MantissaRange const> range_;
|
||||
|
||||
// And one is needed because it needs to choose between oneSmall and
|
||||
// oneLarge based on the current range
|
||||
static Number
|
||||
one(MantissaRange const& range);
|
||||
|
||||
static Number
|
||||
root(MantissaRange const& range, Number f, unsigned d);
|
||||
|
||||
void
|
||||
normalize(MantissaRange const& range);
|
||||
|
||||
void
|
||||
normalize();
|
||||
|
||||
@@ -483,11 +594,14 @@ private:
|
||||
friend void
|
||||
doNormalize(
|
||||
bool& negative,
|
||||
T& mantissa_,
|
||||
int& exponent_,
|
||||
T& mantissa,
|
||||
int& exponent,
|
||||
MantissaRange::rep const& minMantissa,
|
||||
MantissaRange::rep const& maxMantissa);
|
||||
|
||||
bool
|
||||
isnormal(MantissaRange const& range) const noexcept;
|
||||
|
||||
bool
|
||||
isnormal() const noexcept;
|
||||
|
||||
@@ -497,14 +611,60 @@ private:
|
||||
Number
|
||||
shiftExponent(int exponentDelta) const;
|
||||
|
||||
// Safely convert rep (int64) mantissa to internalrep (uint64). If the rep
|
||||
// is negative, returns the positive value. This takes a little extra work
|
||||
// because converting std::numeric_limits<std::int64_t>::min() flirts with
|
||||
// UB, and can vary across compilers.
|
||||
// Safely return the absolute value of a rep (int64) mantissa as an internalrep (uint64).
|
||||
static internalrep
|
||||
externalToInternal(rep mantissa);
|
||||
|
||||
/** Breaks down the number into components, potentially de-normalizing it.
|
||||
*
|
||||
* Ensures that the mantissa always has range_.log + 1 digits.
|
||||
*
|
||||
*/
|
||||
template <detail::UnsignedMantissa Rep = internalrep>
|
||||
std::tuple<bool, Rep, int>
|
||||
toInternal(MantissaRange const& range) const;
|
||||
|
||||
/** Breaks down the number into components, potentially de-normalizing it.
|
||||
*
|
||||
* Ensures that the mantissa always has range_.log + 1 digits.
|
||||
*
|
||||
*/
|
||||
template <detail::UnsignedMantissa Rep = internalrep>
|
||||
std::tuple<bool, Rep, int>
|
||||
toInternal() const;
|
||||
|
||||
/** Rebuilds the number from components.
|
||||
*
|
||||
* If "expectNormal" is true, the values are expected to be normalized - all
|
||||
* in their valid ranges.
|
||||
*
|
||||
* If "expectNormal" is false, the values are expected to be "near
|
||||
* normalized", meaning that the mantissa has to be modified at most once to
|
||||
* bring it back into range.
|
||||
*
|
||||
*/
|
||||
template <bool expectNormal = true, detail::UnsignedMantissa Rep = internalrep>
|
||||
void
|
||||
fromInternal(bool negative, Rep mantissa, int exponent, MantissaRange const* pRange);
|
||||
|
||||
/** Rebuilds the number from components.
|
||||
*
|
||||
* If "expectNormal" is true, the values are expected to be normalized - all
|
||||
* in their valid ranges.
|
||||
*
|
||||
* If "expectNormal" is false, the values are expected to be "near
|
||||
* normalized", meaning that the mantissa has to be modified at most once to
|
||||
* bring it back into range.
|
||||
*
|
||||
*/
|
||||
template <bool expectNormal = true, detail::UnsignedMantissa Rep = internalrep>
|
||||
void
|
||||
fromInternal(bool negative, Rep mantissa, int exponent);
|
||||
|
||||
class Guard;
|
||||
|
||||
public:
|
||||
constexpr static internalrep largestMantissa = largeRange.max;
|
||||
};
|
||||
|
||||
inline constexpr Number::Number(
|
||||
@@ -512,7 +672,8 @@ inline constexpr Number::Number(
|
||||
internalrep mantissa,
|
||||
int exponent,
|
||||
unchecked) noexcept
|
||||
: negative_(negative), mantissa_{mantissa}, exponent_{exponent}
|
||||
: mantissa_{negative ? -static_cast<rep>(mantissa) : static_cast<rep>(mantissa)}
|
||||
, exponent_{exponent}
|
||||
{
|
||||
}
|
||||
|
||||
@@ -523,12 +684,6 @@ inline constexpr Number::Number(internalrep mantissa, int exponent, unchecked) n
|
||||
|
||||
constexpr static Number numZero{};
|
||||
|
||||
inline Number::Number(bool negative, internalrep mantissa, int exponent, normalized)
|
||||
: Number(negative, mantissa, exponent, unchecked{})
|
||||
{
|
||||
normalize();
|
||||
}
|
||||
|
||||
inline Number::Number(internalrep mantissa, int exponent, normalized)
|
||||
: Number(false, mantissa, exponent, normalized{})
|
||||
{
|
||||
@@ -551,17 +706,7 @@ inline Number::Number(rep mantissa) : Number{mantissa, 0}
|
||||
inline constexpr Number::rep
|
||||
Number::mantissa() const noexcept
|
||||
{
|
||||
auto m = mantissa_;
|
||||
if (m > maxRep)
|
||||
{
|
||||
XRPL_ASSERT_PARTS(
|
||||
!isnormal() || (m % 10 == 0 && m / 10 <= maxRep),
|
||||
"xrpl::Number::mantissa",
|
||||
"large normalized mantissa has no remainder");
|
||||
m /= 10;
|
||||
}
|
||||
auto const sign = negative_ ? -1 : 1;
|
||||
return sign * static_cast<Number::rep>(m);
|
||||
return mantissa_;
|
||||
}
|
||||
|
||||
/** Returns the exponent of the external view of the Number.
|
||||
@@ -572,16 +717,7 @@ Number::mantissa() const noexcept
|
||||
inline constexpr int
|
||||
Number::exponent() const noexcept
|
||||
{
|
||||
auto e = exponent_;
|
||||
if (mantissa_ > maxRep)
|
||||
{
|
||||
XRPL_ASSERT_PARTS(
|
||||
!isnormal() || (mantissa_ % 10 == 0 && mantissa_ / 10 <= maxRep),
|
||||
"xrpl::Number::exponent",
|
||||
"large normalized mantissa has no remainder");
|
||||
++e;
|
||||
}
|
||||
return e;
|
||||
return exponent_;
|
||||
}
|
||||
|
||||
inline constexpr Number
|
||||
@@ -596,7 +732,7 @@ Number::operator-() const noexcept
|
||||
if (mantissa_ == 0)
|
||||
return Number{};
|
||||
auto x = *this;
|
||||
x.negative_ = !x.negative_;
|
||||
x.mantissa_ = -x.mantissa_;
|
||||
return x;
|
||||
}
|
||||
|
||||
@@ -677,42 +813,58 @@ Number::min() noexcept
|
||||
inline Number
|
||||
Number::max() noexcept
|
||||
{
|
||||
return Number{false, std::min(range_.get().max, maxRep), maxExponent, unchecked{}};
|
||||
return Number{false, range_.get().max, maxExponent, unchecked{}};
|
||||
}
|
||||
|
||||
inline Number
|
||||
Number::lowest() noexcept
|
||||
{
|
||||
return Number{true, std::min(range_.get().max, maxRep), maxExponent, unchecked{}};
|
||||
return Number{true, range_.get().max, maxExponent, unchecked{}};
|
||||
}
|
||||
|
||||
inline bool
|
||||
Number::isnormal(MantissaRange const& range) const noexcept
|
||||
{
|
||||
auto const abs_m = externalToInternal(mantissa_);
|
||||
|
||||
return *this == Number{} ||
|
||||
(range.min <= abs_m && abs_m <= range.max && //
|
||||
minExponent <= exponent_ && exponent_ <= maxExponent);
|
||||
}
|
||||
|
||||
inline bool
|
||||
Number::isnormal() const noexcept
|
||||
{
|
||||
MantissaRange const& range = range_;
|
||||
auto const abs_m = mantissa_;
|
||||
return *this == Number{} ||
|
||||
(range.min <= abs_m && abs_m <= range.max && (abs_m <= maxRep || abs_m % 10 == 0) &&
|
||||
minExponent <= exponent_ && exponent_ <= maxExponent);
|
||||
return isnormal(range_);
|
||||
}
|
||||
|
||||
template <Integral64 T>
|
||||
std::pair<T, int>
|
||||
Number::normalizeToRange(T minMantissa, T maxMantissa) const
|
||||
{
|
||||
bool negative = negative_;
|
||||
internalrep mantissa = mantissa_;
|
||||
bool negative = mantissa_ < 0;
|
||||
internalrep mantissa = externalToInternal(mantissa_);
|
||||
int exponent = exponent_;
|
||||
|
||||
if constexpr (std::is_unsigned_v<T>)
|
||||
{
|
||||
XRPL_ASSERT_PARTS(
|
||||
!negative,
|
||||
"xrpl::Number::normalizeToRange",
|
||||
"Number is non-negative for unsigned range.");
|
||||
// To avoid logical errors in release builds, throw if the Number is
|
||||
// negative for an unsigned range.
|
||||
if (negative)
|
||||
throw std::runtime_error(
|
||||
"Number::normalizeToRange: Number is negative for "
|
||||
"unsigned range.");
|
||||
}
|
||||
Number::normalize(negative, mantissa, exponent, minMantissa, maxMantissa);
|
||||
|
||||
auto const sign = negative ? -1 : 1;
|
||||
return std::make_pair(static_cast<T>(sign * mantissa), exponent);
|
||||
// Cast mantissa to signed type first (if T is a signed type) to avoid
|
||||
// unsigned integer overflow when multiplying by negative sign
|
||||
T signedMantissa = negative ? -static_cast<T>(mantissa) : static_cast<T>(mantissa);
|
||||
return std::make_pair(signedMantissa, exponent);
|
||||
}
|
||||
|
||||
inline constexpr Number
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
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`
|
||||
- For ordered containers with most insertions or erases at the end.
|
||||
|
||||
@@ -60,7 +60,7 @@ class SlabAllocator
|
||||
{
|
||||
// Use memcpy to avoid unaligned UB
|
||||
// (will optimize to equivalent code)
|
||||
std::memcpy(data, &l_, sizeof(std::uint8_t*));
|
||||
std::memcpy(data, static_cast<void const*>(&l_), sizeof(std::uint8_t*));
|
||||
l_ = data;
|
||||
data += item;
|
||||
}
|
||||
@@ -102,7 +102,7 @@ class SlabAllocator
|
||||
{
|
||||
// Use memcpy to avoid unaligned UB
|
||||
// (will optimize to equivalent code)
|
||||
std::memcpy(&l_, ret, sizeof(std::uint8_t*));
|
||||
std::memcpy(static_cast<void*>(&l_), ret, sizeof(std::uint8_t*));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ class SlabAllocator
|
||||
|
||||
// Use memcpy to avoid unaligned UB
|
||||
// (will optimize to equivalent code)
|
||||
std::memcpy(ptr, &l_, sizeof(std::uint8_t*));
|
||||
std::memcpy(ptr, static_cast<void const*>(&l_), sizeof(std::uint8_t*));
|
||||
l_ = ptr;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
@@ -232,11 +231,4 @@ makeSlice(std::basic_string<char, Traits, Alloc> const& s)
|
||||
return Slice(s.data(), s.size());
|
||||
}
|
||||
|
||||
template <class Traits>
|
||||
Slice
|
||||
makeSlice(std::basic_string_view<char, Traits> const& s)
|
||||
{
|
||||
return Slice(s.data(), s.size());
|
||||
}
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -26,7 +26,7 @@ public:
|
||||
explicit UptimeClock() = default;
|
||||
|
||||
static time_point
|
||||
now(); // seconds since rippled program start
|
||||
now(); // seconds since xrpld program start
|
||||
|
||||
private:
|
||||
static std::atomic<rep> now_;
|
||||
|
||||
@@ -17,13 +17,13 @@ static_assert(
|
||||
// NOLINTNEXTLINE(misc-redundant-expression)
|
||||
std::is_integral<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(
|
||||
// NOLINTNEXTLINE(misc-redundant-expression)
|
||||
std::numeric_limits<beast::xor_shift_engine::result_type>::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
|
||||
|
||||
namespace detail {
|
||||
|
||||
@@ -26,7 +26,7 @@ struct aged_associative_container_extract_t<false>
|
||||
Value const&
|
||||
operator()(Value const& value) const
|
||||
{
|
||||
return value;
|
||||
return value; // NOLINT(bugprone-return-const-ref-from-parameter)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -257,7 +257,8 @@ private:
|
||||
|
||||
config_t(config_t&& other)
|
||||
: KeyValueCompare(std::move(other.key_compare()))
|
||||
, beast::detail::empty_base_optimization<ElementAllocator>(std::move(other))
|
||||
, beast::detail::empty_base_optimization<ElementAllocator>(std::move(
|
||||
static_cast<beast::detail::empty_base_optimization<ElementAllocator>&>(other)))
|
||||
, clock(other.clock)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -35,9 +35,11 @@ struct CopyConst<T const, U>
|
||||
template <typename T, typename Tag>
|
||||
class ListNode
|
||||
{
|
||||
private:
|
||||
ListNode() = default;
|
||||
|
||||
using value_type = T;
|
||||
|
||||
friend T;
|
||||
friend class List<T, Tag>;
|
||||
|
||||
template <typename>
|
||||
|
||||
@@ -203,7 +203,8 @@ template <class Hasher, class T>
|
||||
inline std::enable_if_t<is_contiguously_hashable<T, Hasher>::value>
|
||||
hash_append(Hasher& h, T const& t) noexcept
|
||||
{
|
||||
h(std::addressof(t), sizeof(t));
|
||||
// NOLINTNEXTLINE(bugprone-sizeof-expression)
|
||||
h(static_cast<void const*>(std::addressof(t)), sizeof(t));
|
||||
}
|
||||
|
||||
template <class Hasher, class T>
|
||||
|
||||
@@ -53,8 +53,9 @@ is_white(char c)
|
||||
case '\t':
|
||||
case '\v':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
};
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class FwdIter>
|
||||
|
||||
@@ -118,18 +118,18 @@ private:
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class _>
|
||||
template <class Unused>
|
||||
void
|
||||
reporter<_>::suite_results::add(case_results const& r)
|
||||
reporter<Unused>::suite_results::add(case_results const& r)
|
||||
{
|
||||
++cases;
|
||||
total += r.total;
|
||||
failed += r.failed;
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template <class Unused>
|
||||
void
|
||||
reporter<_>::results::add(suite_results const& r)
|
||||
reporter<Unused>::results::add(suite_results const& r)
|
||||
{
|
||||
++suites;
|
||||
total += r.total;
|
||||
@@ -160,13 +160,13 @@ reporter<_>::results::add(suite_results const& r)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class _>
|
||||
reporter<_>::reporter(std::ostream& os) : os_(os)
|
||||
template <class Unused>
|
||||
reporter<Unused>::reporter(std::ostream& os) : os_(os)
|
||||
{
|
||||
}
|
||||
|
||||
template <class _>
|
||||
reporter<_>::~reporter()
|
||||
template <class Unused>
|
||||
reporter<Unused>::~reporter()
|
||||
{
|
||||
if (results_.top.size() > 0)
|
||||
{
|
||||
@@ -180,9 +180,9 @@ reporter<_>::~reporter()
|
||||
<< amount{results_.failed, "failure"} << std::endl;
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template <class Unused>
|
||||
std::string
|
||||
reporter<_>::fmtdur(typename clock_type::duration const& d)
|
||||
reporter<Unused>::fmtdur(typename clock_type::duration const& d)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
auto const ms = duration_cast<milliseconds>(d);
|
||||
@@ -193,46 +193,46 @@ reporter<_>::fmtdur(typename clock_type::duration const& d)
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template <class Unused>
|
||||
void
|
||||
reporter<_>::on_suite_begin(suite_info const& info)
|
||||
reporter<Unused>::on_suite_begin(suite_info const& info)
|
||||
{
|
||||
suite_results_ = suite_results{info.full_name()};
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template <class Unused>
|
||||
void
|
||||
reporter<_>::on_suite_end()
|
||||
reporter<Unused>::on_suite_end()
|
||||
{
|
||||
results_.add(suite_results_);
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template <class Unused>
|
||||
void
|
||||
reporter<_>::on_case_begin(std::string const& name)
|
||||
reporter<Unused>::on_case_begin(std::string const& name)
|
||||
{
|
||||
case_results_ = case_results(name);
|
||||
os_ << suite_results_.name << (case_results_.name.empty() ? "" : (" " + case_results_.name))
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template <class Unused>
|
||||
void
|
||||
reporter<_>::on_case_end()
|
||||
reporter<Unused>::on_case_end()
|
||||
{
|
||||
suite_results_.add(case_results_);
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template <class Unused>
|
||||
void
|
||||
reporter<_>::on_pass()
|
||||
reporter<Unused>::on_pass()
|
||||
{
|
||||
++case_results_.total;
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template <class Unused>
|
||||
void
|
||||
reporter<_>::on_fail(std::string const& reason)
|
||||
reporter<Unused>::on_fail(std::string const& reason)
|
||||
{
|
||||
++case_results_.failed;
|
||||
++case_results_.total;
|
||||
@@ -240,9 +240,9 @@ reporter<_>::on_fail(std::string const& reason)
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template <class Unused>
|
||||
void
|
||||
reporter<_>::on_log(std::string const& s)
|
||||
reporter<Unused>::on_log(std::string const& s)
|
||||
{
|
||||
os_ << s;
|
||||
}
|
||||
|
||||
@@ -145,9 +145,9 @@ public:
|
||||
void
|
||||
insert(case_results&& r)
|
||||
{
|
||||
cont().emplace_back(std::move(r));
|
||||
total_ += r.tests.total();
|
||||
failed_ += r.tests.failed();
|
||||
cont().emplace_back(std::move(r));
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -36,7 +36,7 @@ make_reason(String const& reason, char const* file, int line)
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class thread;
|
||||
class Thread;
|
||||
|
||||
enum abort_t { no_abort_on_fail, abort_on_fail };
|
||||
|
||||
@@ -295,7 +295,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
friend class thread;
|
||||
friend class Thread;
|
||||
|
||||
static suite**
|
||||
p_this_suite()
|
||||
@@ -538,7 +538,7 @@ suite::run(runner& r)
|
||||
{
|
||||
run();
|
||||
}
|
||||
catch (abort_exception const&)
|
||||
catch (abort_exception const&) // NOLINT(bugprone-empty-catch)
|
||||
{
|
||||
// ends the suite
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace beast {
|
||||
namespace unit_test {
|
||||
|
||||
/** Replacement for std::thread that handles exceptions in unit tests. */
|
||||
class thread
|
||||
class Thread
|
||||
{
|
||||
private:
|
||||
suite* s_ = nullptr;
|
||||
@@ -24,17 +24,17 @@ public:
|
||||
using id = std::thread::id;
|
||||
using native_handle_type = std::thread::native_handle_type;
|
||||
|
||||
thread() = default;
|
||||
thread(thread const&) = delete;
|
||||
thread&
|
||||
operator=(thread const&) = delete;
|
||||
Thread() = default;
|
||||
Thread(Thread const&) = delete;
|
||||
Thread&
|
||||
operator=(Thread const&) = delete;
|
||||
|
||||
thread(thread&& other) : s_(other.s_), t_(std::move(other.t_))
|
||||
Thread(Thread&& other) : s_(other.s_), t_(std::move(other.t_))
|
||||
{
|
||||
}
|
||||
|
||||
thread&
|
||||
operator=(thread&& other)
|
||||
Thread&
|
||||
operator=(Thread&& other)
|
||||
{
|
||||
s_ = other.s_;
|
||||
t_ = std::move(other.t_);
|
||||
@@ -42,10 +42,10 @@ public:
|
||||
}
|
||||
|
||||
template <class F, class... Args>
|
||||
explicit thread(suite& s, F&& f, Args&&... args) : s_(&s)
|
||||
explicit Thread(suite& s, F&& f, Args&&... args) : s_(&s)
|
||||
{
|
||||
std::function<void(void)> b = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
|
||||
t_ = std::thread(&thread::run, this, std::move(b));
|
||||
t_ = std::thread(&Thread::run, this, std::move(b));
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
swap(thread& other)
|
||||
swap(Thread& other)
|
||||
{
|
||||
std::swap(s_, other.s_);
|
||||
std::swap(t_, other.t_);
|
||||
@@ -94,7 +94,7 @@ private:
|
||||
{
|
||||
f();
|
||||
}
|
||||
catch (suite::abort_exception const&)
|
||||
catch (suite::abort_exception const&) // NOLINT(bugprone-empty-catch)
|
||||
{
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
|
||||
@@ -43,15 +43,15 @@ private:
|
||||
murmurhash3(result_type x);
|
||||
};
|
||||
|
||||
template <class _>
|
||||
xor_shift_engine<_>::xor_shift_engine(result_type val)
|
||||
template <class Unused>
|
||||
xor_shift_engine<Unused>::xor_shift_engine(result_type val)
|
||||
{
|
||||
seed(val);
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template <class Unused>
|
||||
void
|
||||
xor_shift_engine<_>::seed(result_type seed)
|
||||
xor_shift_engine<Unused>::seed(result_type seed)
|
||||
{
|
||||
if (seed == 0)
|
||||
throw std::domain_error("invalid seed");
|
||||
@@ -59,9 +59,9 @@ xor_shift_engine<_>::seed(result_type seed)
|
||||
s_[1] = murmurhash3(s_[0]);
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template <class Unused>
|
||||
auto
|
||||
xor_shift_engine<_>::operator()() -> result_type
|
||||
xor_shift_engine<Unused>::operator()() -> result_type
|
||||
{
|
||||
result_type s1 = s_[0];
|
||||
result_type const s0 = s_[1];
|
||||
@@ -70,9 +70,9 @@ xor_shift_engine<_>::operator()() -> result_type
|
||||
return (s_[1] = (s1 ^ s0 ^ (s1 >> 17) ^ (s0 >> 26))) + s0;
|
||||
}
|
||||
|
||||
template <class _>
|
||||
template <class Unused>
|
||||
auto
|
||||
xor_shift_engine<_>::murmurhash3(result_type x) -> result_type
|
||||
xor_shift_engine<Unused>::murmurhash3(result_type x) -> result_type
|
||||
{
|
||||
x ^= x >> 33;
|
||||
x *= 0xff51afd7ed558ccdULL;
|
||||
|
||||
@@ -213,11 +213,60 @@ public:
|
||||
// Called when a credit is made to an account
|
||||
// This is required to support PaymentSandbox
|
||||
virtual void
|
||||
creditHook(
|
||||
creditHookIOU(
|
||||
AccountID const& from,
|
||||
AccountID const& to,
|
||||
STAmount const& amount,
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ auto constexpr decreaseLedgerTimeResolutionEvery = 1;
|
||||
|
||||
/** 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,
|
||||
without the need for perfectly synchronized clocks.
|
||||
The time resolution (i.e. the size of the intervals) is adjusted dynamically
|
||||
@@ -62,7 +62,7 @@ getNextLedgerTimeResolution(
|
||||
bool previousAgree,
|
||||
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;
|
||||
// Find the current resolution:
|
||||
@@ -72,7 +72,7 @@ getNextLedgerTimeResolution(
|
||||
previousResolution);
|
||||
XRPL_ASSERT(
|
||||
iter != std::end(ledgerPossibleTimeResolutions),
|
||||
"ripple:getNextLedgerTimeResolution : found time resolution");
|
||||
"xrpl::getNextLedgerTimeResolution : found time resolution");
|
||||
|
||||
// This should never happen, but just as a precaution
|
||||
if (iter == std::end(ledgerPossibleTimeResolutions))
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#include <xrpl/ledger/AcceptedLedgerTx.h>
|
||||
#include <xrpl/ledger/BookListeners.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/Asset.h>
|
||||
#include <xrpl/protocol/Book.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/MultiApiJson.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
|
||||
@@ -53,30 +53,30 @@ public:
|
||||
issue. This is useful for pathfinding to find all possible next hops
|
||||
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
|
||||
@return Vector of books that want this issue
|
||||
*/
|
||||
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.
|
||||
|
||||
@param issue The issue to search for
|
||||
@param asset The asset to search for
|
||||
@param domain Optional domain restriction for the order book
|
||||
@return Number of books that want this issue
|
||||
*/
|
||||
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.
|
||||
|
||||
@param issue The issue to check
|
||||
@param asset The asset to check
|
||||
@param domain Optional domain restriction for the order book
|
||||
@return true if a book from this issue to XRP exists
|
||||
*/
|
||||
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.
|
||||
|
||||
@@ -15,10 +15,55 @@ namespace detail {
|
||||
// into the PaymentSandbox class itself
|
||||
class DeferredCredits
|
||||
{
|
||||
public:
|
||||
struct Adjustment
|
||||
private:
|
||||
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)
|
||||
{
|
||||
}
|
||||
@@ -29,16 +74,30 @@ public:
|
||||
|
||||
// Get the adjustments for the balance between main and other.
|
||||
// Returns the debits, credits and the original balance
|
||||
std::optional<Adjustment>
|
||||
adjustments(AccountID const& main, AccountID const& other, Currency const& currency) const;
|
||||
std::optional<AdjustmentIOU>
|
||||
adjustmentsIOU(AccountID const& main, AccountID const& other, Currency const& currency) const;
|
||||
|
||||
std::optional<AdjustmentMPT>
|
||||
adjustmentsMPT(MPTID const& mptID) const;
|
||||
|
||||
void
|
||||
credit(
|
||||
creditIOU(
|
||||
AccountID const& sender,
|
||||
AccountID const& receiver,
|
||||
STAmount const& amount,
|
||||
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
|
||||
ownerCount(AccountID const& id, std::uint32_t cur, std::uint32_t next);
|
||||
|
||||
@@ -52,21 +111,11 @@ public:
|
||||
apply(DeferredCredits& to);
|
||||
|
||||
private:
|
||||
// lowAccount, highAccount
|
||||
using Key = std::tuple<AccountID, AccountID, Currency>;
|
||||
struct Value
|
||||
{
|
||||
explicit Value() = default;
|
||||
static KeyIOU
|
||||
makeKeyIOU(AccountID const& a1, AccountID const& a2, Currency const& currency);
|
||||
|
||||
STAmount lowAcctCredits;
|
||||
STAmount highAcctCredits;
|
||||
STAmount lowAcctOrigBalance;
|
||||
};
|
||||
|
||||
static Key
|
||||
makeKey(AccountID const& a1, AccountID const& a2, Currency const& c);
|
||||
|
||||
std::map<Key, Value> credits_;
|
||||
std::map<KeyIOU, ValueIOU> creditsIOU_;
|
||||
std::map<MPTID, IssuerValueMPT> creditsMPT_;
|
||||
std::map<AccountID, std::uint32_t> ownerCounts_;
|
||||
};
|
||||
|
||||
@@ -131,16 +180,35 @@ public:
|
||||
/** @} */
|
||||
|
||||
STAmount
|
||||
balanceHook(AccountID const& account, AccountID const& issuer, STAmount const& amount)
|
||||
balanceHookIOU(AccountID const& account, AccountID const& issuer, STAmount const& amount)
|
||||
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
|
||||
creditHook(
|
||||
creditHookIOU(
|
||||
AccountID const& from,
|
||||
AccountID const& to,
|
||||
STAmount const& amount,
|
||||
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
|
||||
adjustOwnerCountHook(AccountID const& account, std::uint32_t cur, std::uint32_t next) override;
|
||||
|
||||
|
||||
@@ -148,15 +148,35 @@ public:
|
||||
|
||||
// Accounts in a payment are not allowed to use assets acquired during that
|
||||
// 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.
|
||||
// This is required to support PaymentSandbox.
|
||||
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;
|
||||
}
|
||||
|
||||
// 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
|
||||
// payment. The PaymentSandbox tracks the debits, credits, and owner count
|
||||
// changes that accounts make during a payment. `ownerCountHook` adjusts the
|
||||
|
||||
@@ -30,10 +30,10 @@ enum class SkipEntry : bool { No = false, Yes };
|
||||
/** Determines whether the given expiration time has passed.
|
||||
|
||||
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).
|
||||
|
||||
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.
|
||||
|
||||
See https://xrpl.org/basic-data-types.html#specifying-time
|
||||
@@ -63,8 +63,8 @@ isVaultPseudoAccountFrozen(
|
||||
isLPTokenFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
Issue const& asset,
|
||||
Issue const& asset2);
|
||||
Asset const& asset,
|
||||
Asset const& asset2);
|
||||
|
||||
// Return the list of enabled amendments
|
||||
[[nodiscard]] std::set<uint256>
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/Expected.h>
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/Number.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/AmountConversions.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
@@ -11,6 +16,7 @@
|
||||
#include <xrpl/protocol/Quality.h>
|
||||
#include <xrpl/protocol/Rules.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -36,7 +42,7 @@ enum class IsDeposit : bool { No = false, Yes = true };
|
||||
* @return LP Tokens as IOU
|
||||
*/
|
||||
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.
|
||||
* @param asset1Balance current AMM asset1 balance
|
||||
@@ -124,7 +130,8 @@ withinRelativeDistance(Quality const& calcQuality, Quality const& reqQuality, Nu
|
||||
template <typename Amt>
|
||||
requires(
|
||||
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
|
||||
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.
|
||||
// This has the most impact when takerGets is XRP.
|
||||
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};
|
||||
};
|
||||
|
||||
@@ -262,7 +269,7 @@ getAMMOfferStartWithTakerPays(
|
||||
// Round downward to minimize the offer and to maximize the quality.
|
||||
// This has the most impact when takerPays is XRP.
|
||||
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)};
|
||||
};
|
||||
|
||||
@@ -331,7 +338,7 @@ changeSpotPriceQuality(
|
||||
<< " " << to_string(pool.out) << " " << quality << " " << tfee;
|
||||
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
|
||||
if (auto amounts = TAmounts<TIn, TOut>{takerPays, swapAssetIn(pool, takerPays, tfee)};
|
||||
Quality{amounts} < quality &&
|
||||
@@ -360,7 +367,7 @@ changeSpotPriceQuality(
|
||||
// Generate the offer starting with XRP side. Return seated offer amounts
|
||||
// if the offer can be generated, otherwise nullopt.
|
||||
auto amounts = [&]() {
|
||||
if (isXRP(getIssue(pool.out)))
|
||||
if (isXRP(getAsset(pool.out)))
|
||||
return getAMMOfferStartWithTakerGets(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);
|
||||
|
||||
if (denom.signum() <= 0)
|
||||
return toAmount<TOut>(getIssue(pool.out), 0);
|
||||
return toAmount<TOut>(getAsset(pool.out), 0);
|
||||
|
||||
Number::setround(Number::upward);
|
||||
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;
|
||||
|
||||
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
|
||||
{
|
||||
return toAmount<TOut>(
|
||||
getIssue(pool.out),
|
||||
getAsset(pool.out),
|
||||
pool.out - (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)),
|
||||
Number::downward);
|
||||
}
|
||||
@@ -508,7 +515,7 @@ swapAssetOut(TAmounts<TIn, TOut> const& pool, TOut const& assetOut, std::uint16_
|
||||
auto const denom = pool.out - assetOut;
|
||||
if (denom.signum() <= 0)
|
||||
{
|
||||
return toMaxAmount<TIn>(getIssue(pool.in));
|
||||
return toMaxAmount<TIn>(getAsset(pool.in));
|
||||
}
|
||||
|
||||
Number::setround(Number::upward);
|
||||
@@ -522,14 +529,14 @@ swapAssetOut(TAmounts<TIn, TOut> const& pool, TOut const& assetOut, std::uint16_
|
||||
Number::setround(Number::upward);
|
||||
auto const swapIn = numerator2 / feeMult;
|
||||
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
|
||||
{
|
||||
return toAmount<TIn>(
|
||||
getIssue(pool.in),
|
||||
getAsset(pool.in),
|
||||
((pool.in * pool.out) / (pool.out - assetOut) - pool.in) / feeMult(tfee),
|
||||
Number::upward);
|
||||
}
|
||||
@@ -616,9 +623,9 @@ getRoundedAsset(Rules const& rules, STAmount const& balance, A const& frac, IsDe
|
||||
if (!rules.enabled(fixAMMv1_3))
|
||||
{
|
||||
if constexpr (std::is_same_v<A, STAmount>)
|
||||
return multiply(balance, frac, balance.issue());
|
||||
return multiply(balance, frac, balance.asset());
|
||||
else
|
||||
return toSTAmount(balance.issue(), balance * frac);
|
||||
return toSTAmount(balance.asset(), balance * frac);
|
||||
}
|
||||
auto const rm = detail::getAssetRounding(isDeposit);
|
||||
return multiply(balance, frac, rm);
|
||||
@@ -712,4 +719,94 @@ adjustFracByTokens(
|
||||
STAmount const& tokens,
|
||||
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
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/MPTAmount.h>
|
||||
#include <xrpl/protocol/Rate.h>
|
||||
#include <xrpl/tx/transactors/token/MPTokenAuthorize.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -42,7 +41,8 @@ escrowUnlockApplyHelper<Issue>(
|
||||
bool createAsset,
|
||||
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 senderIssuer = issuer == sender;
|
||||
bool const receiverIssuer = issuer == receiver;
|
||||
@@ -65,9 +65,9 @@ escrowUnlockApplyHelper<Issue>(
|
||||
return tecNO_LINE_INSUF_RESERVE;
|
||||
}
|
||||
|
||||
Currency const currency = amount.getCurrency();
|
||||
STAmount initialBalance(amount.issue());
|
||||
initialBalance.setIssuer(noAccount());
|
||||
Currency const currency = issue.currency;
|
||||
STAmount initialBalance(issue);
|
||||
initialBalance.get<Issue>().account = noAccount();
|
||||
|
||||
if (TER const ter = trustCreate(
|
||||
view, // payment sandbox
|
||||
@@ -114,7 +114,8 @@ escrowUnlockApplyHelper<Issue>(
|
||||
if ((!senderIssuer && !receiverIssuer) && lockedRate != parityRate)
|
||||
{
|
||||
// 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
|
||||
finalAmt = amount.value() - xferFee;
|
||||
}
|
||||
@@ -149,7 +150,7 @@ escrowUnlockApplyHelper<Issue>(
|
||||
// if destination is not the issuer then transfer funds
|
||||
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))
|
||||
return ter; // LCOV_EXCL_LINE
|
||||
}
|
||||
@@ -183,8 +184,7 @@ escrowUnlockApplyHelper<MPTIssue>(
|
||||
return tecINSUFFICIENT_RESERVE;
|
||||
}
|
||||
|
||||
if (auto const ter = MPTokenAuthorize::createMPToken(view, mptID, receiver, 0);
|
||||
!isTesSuccess(ter))
|
||||
if (auto const ter = createMPToken(view, mptID, receiver, 0); !isTesSuccess(ter))
|
||||
{
|
||||
return ter; // LCOV_EXCL_LINE
|
||||
}
|
||||
@@ -218,7 +218,7 @@ escrowUnlockApplyHelper<MPTIssue>(
|
||||
// compute balance to transfer
|
||||
finalAmt = amount.value() - xferFee;
|
||||
}
|
||||
return rippleUnlockEscrowMPT(
|
||||
return unlockEscrowMPT(
|
||||
view,
|
||||
sender,
|
||||
receiver,
|
||||
@@ -80,6 +80,7 @@ authorizeMPToken(
|
||||
* requireAuth check is recursive for MPT shares in a vault, descending to
|
||||
* assets in the vault, up to maxAssetCheckDepth recursion depth. This is
|
||||
* purely defensive, as we currently do not allow such vaults to be created.
|
||||
* WeakAuth intentionally allows missing MPTokens under MPToken V2.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
requireAuth(
|
||||
@@ -114,6 +115,12 @@ canTransfer(
|
||||
AccountID const& from,
|
||||
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)
|
||||
@@ -142,14 +149,14 @@ removeEmptyHolding(
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
TER
|
||||
rippleLockEscrowMPT(
|
||||
lockEscrowMPT(
|
||||
ApplyView& view,
|
||||
AccountID const& uGrantorID,
|
||||
STAmount const& saAmount,
|
||||
beast::Journal j);
|
||||
|
||||
TER
|
||||
rippleUnlockEscrowMPT(
|
||||
unlockEscrowMPT(
|
||||
ApplyView& view,
|
||||
AccountID const& uGrantorID,
|
||||
AccountID const& uGranteeID,
|
||||
@@ -157,4 +164,80 @@ rippleUnlockEscrowMPT(
|
||||
STAmount const& grossAmount,
|
||||
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
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/TxFlags.h>
|
||||
#include <xrpl/protocol/nft.h>
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -20,10 +20,6 @@ removeTokenOffersWithLimit(
|
||||
Keylet const& directory,
|
||||
std::size_t maxDeletableOffers);
|
||||
|
||||
/** Returns tesSUCCESS if NFToken has few enough offers that it can be burned */
|
||||
TER
|
||||
notTooManyOffers(ReadView const& view, uint256 const& nftokenID);
|
||||
|
||||
/** Finds the specified token in the owner's token directory. */
|
||||
std::optional<STObject>
|
||||
findToken(ReadView const& view, AccountID const& owner, uint256 const& nftokenID);
|
||||
@@ -252,4 +252,14 @@ deleteAMMTrustLine(
|
||||
std::optional<AccountID> const& ammAccountID,
|
||||
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
|
||||
|
||||
@@ -31,6 +31,9 @@ enum SpendableHandling { shSIMPLE_BALANCE, shFULL_BALANCE };
|
||||
|
||||
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:
|
||||
* - StrongAuth - before checking if authorization is required
|
||||
* - WeakAuth
|
||||
@@ -176,6 +179,16 @@ accountFunds(
|
||||
FreezeHandling freezeHandling,
|
||||
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
|
||||
* @param view The ledger view
|
||||
* @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.
|
||||
// [[nodiscard]] // nodiscard commented out so DirectStep.cpp compiles.
|
||||
|
||||
/** Calls static rippleCreditIOU if saAmount represents Issue.
|
||||
* Calls static rippleCreditMPT if saAmount represents MPTIssue.
|
||||
/** Calls static directSendNoFeeIOU if saAmount represents Issue.
|
||||
* Calls static directSendNoFeeMPT if saAmount represents MPTIssue.
|
||||
*/
|
||||
TER
|
||||
rippleCredit(
|
||||
directSendNoFee(
|
||||
ApplyView& view,
|
||||
AccountID const& uSenderID,
|
||||
AccountID const& uReceiverID,
|
||||
@@ -257,7 +270,8 @@ accountSend(
|
||||
AccountID const& to,
|
||||
STAmount const& saAmount,
|
||||
beast::Journal j,
|
||||
WaiveTransferFee waiveFee = WaiveTransferFee::No);
|
||||
WaiveTransferFee waiveFee = WaiveTransferFee::No,
|
||||
AllowMPTOverflow allowOverflow = AllowMPTOverflow::No);
|
||||
|
||||
using MultiplePaymentDestinations = std::vector<std::pair<AccountID, Number>>;
|
||||
/** Like accountSend, except one account is sending multiple payments (with the
|
||||
|
||||
@@ -134,7 +134,7 @@ public:
|
||||
{
|
||||
lowest_layer().shutdown(plain_socket::shutdown_both);
|
||||
}
|
||||
catch (boost::system::system_error& e)
|
||||
catch (boost::system::system_error const& e)
|
||||
{
|
||||
ec = e.code();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
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
|
||||
to be persisted between launches. If a NodeObject is accessed and is not in
|
||||
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:
|
||||
|
||||
```
|
||||
$rippled --unittest=NodeStoreTiming
|
||||
$xrpld --unittest=NodeStoreTiming
|
||||
```
|
||||
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
- 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
|
||||
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
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 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.
|
||||
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.
|
||||
|
||||
### Making Changes
|
||||
@@ -63,7 +63,7 @@ templated `CallData` class in GRPCServerImpl::setupListeners(). The template
|
||||
parameters should be the request type and the response type.
|
||||
|
||||
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
|
||||
into helper functions (see Tx.cpp or AccountTx.cpp for an example).
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ enum MessageType {
|
||||
|
||||
/* Provides the current ephemeral key for a validator. */
|
||||
message TMManifest {
|
||||
// A Manifest object in the Ripple serialization format.
|
||||
// A Manifest object in the XRPL serialization format.
|
||||
required bytes stobject = 1;
|
||||
}
|
||||
|
||||
@@ -244,15 +244,7 @@ message TMGetObjectByHash {
|
||||
|
||||
message TMLedgerNode {
|
||||
required bytes nodedata = 1;
|
||||
|
||||
// Used when protocol version <2.3. Not set for ledger base data.
|
||||
optional bytes nodeid = 2;
|
||||
|
||||
// Used when protocol version >=2.3. Neither value is set for ledger base data.
|
||||
oneof reference {
|
||||
bytes id = 3; // Set for inner nodes.
|
||||
uint32 depth = 4; // Set for leaf nodes.
|
||||
}
|
||||
optional bytes nodeid = 2; // missing for ledger base data
|
||||
}
|
||||
|
||||
enum TMLedgerInfoType {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <xrpl/basics/Number.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/Asset.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
|
||||
@@ -31,12 +31,12 @@ class Rules;
|
||||
/** Calculate Liquidity Provider Token (LPT) Currency.
|
||||
*/
|
||||
Currency
|
||||
ammLPTCurrency(Currency const& cur1, Currency const& cur2);
|
||||
ammLPTCurrency(Asset const& asset1, Asset const& asset2);
|
||||
|
||||
/** Calculate LPT Issue from AMM asset pair.
|
||||
*/
|
||||
Issue
|
||||
ammLPTIssue(Currency const& cur1, Currency const& cur2, AccountID const& ammAccountID);
|
||||
ammLPTIssue(Asset const& asset1, Asset const& asset2, AccountID const& ammAccountID);
|
||||
|
||||
/** Validate the 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
|
||||
invalidAMMAmount(
|
||||
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);
|
||||
|
||||
NotTEC
|
||||
invalidAMMAsset(
|
||||
Issue const& issue,
|
||||
std::optional<std::pair<Issue, Issue>> const& pair = std::nullopt);
|
||||
Asset const& asset,
|
||||
std::optional<std::pair<Asset, Asset>> const& pair = std::nullopt);
|
||||
|
||||
NotTEC
|
||||
invalidAMMAssetPair(
|
||||
Issue const& issue1,
|
||||
Issue const& issue2,
|
||||
std::optional<std::pair<Issue, Issue>> const& pair = std::nullopt);
|
||||
Asset const& asset1,
|
||||
Asset const& asset2,
|
||||
std::optional<std::pair<Asset, Asset>> const& pair = std::nullopt);
|
||||
|
||||
/** Get time slot of the auction slot.
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <xrpl/protocol/tokens.h>
|
||||
// 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/base_uint.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/protocol/IOUAmount.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
|
||||
@@ -9,11 +10,12 @@
|
||||
namespace xrpl {
|
||||
|
||||
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;
|
||||
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
|
||||
@@ -31,12 +33,25 @@ toSTAmount(XRPAmount const& xrp)
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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>
|
||||
T
|
||||
toAmount(STAmount const& amt) = delete;
|
||||
@@ -76,6 +91,21 @@ toAmount<XRPAmount>(STAmount const& amt)
|
||||
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>
|
||||
T
|
||||
toAmount(IOUAmount const& amt) = delete;
|
||||
@@ -98,23 +128,36 @@ toAmount<XRPAmount>(XRPAmount const& 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>
|
||||
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());
|
||||
if (isXRP(issue))
|
||||
if (isXRP(asset))
|
||||
Number::setround(mode);
|
||||
|
||||
if constexpr (std::is_same_v<IOUAmount, T>)
|
||||
return IOUAmount(n);
|
||||
else if constexpr (std::is_same_v<XRPAmount, T>)
|
||||
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>)
|
||||
{
|
||||
if (isXRP(issue))
|
||||
return STAmount(issue, static_cast<std::int64_t>(n));
|
||||
return STAmount(issue, n);
|
||||
if (isXRP(asset))
|
||||
return STAmount(asset, static_cast<std::int64_t>(n));
|
||||
return STAmount(asset, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -125,17 +168,23 @@ toAmount(Issue const& issue, Number const& n, Number::rounding_mode mode = Numbe
|
||||
|
||||
template <typename T>
|
||||
T
|
||||
toMaxAmount(Issue const& issue)
|
||||
toMaxAmount(Asset const& asset)
|
||||
{
|
||||
if constexpr (std::is_same_v<IOUAmount, T>)
|
||||
return IOUAmount(STAmount::cMaxValue, STAmount::cMaxOffset);
|
||||
else if constexpr (std::is_same_v<XRPAmount, T>)
|
||||
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>)
|
||||
{
|
||||
if (isXRP(issue))
|
||||
return STAmount(issue, static_cast<std::int64_t>(STAmount::cMaxNativeN));
|
||||
return STAmount(issue, STAmount::cMaxValue, STAmount::cMaxOffset);
|
||||
return asset.visit(
|
||||
[](Issue const& issue) {
|
||||
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
|
||||
{
|
||||
@@ -145,21 +194,23 @@ toMaxAmount(Issue const& issue)
|
||||
}
|
||||
|
||||
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>
|
||||
Issue
|
||||
getIssue(T const& amt)
|
||||
Asset
|
||||
getAsset(T const& amt)
|
||||
{
|
||||
if constexpr (std::is_same_v<IOUAmount, T>)
|
||||
return noIssue();
|
||||
else if constexpr (std::is_same_v<XRPAmount, T>)
|
||||
return xrpIssue();
|
||||
else if constexpr (std::is_same_v<MPTAmount, T>)
|
||||
return noMPT();
|
||||
else if constexpr (std::is_same_v<STAmount, T>)
|
||||
return amt.issue();
|
||||
return amt.asset();
|
||||
else
|
||||
{
|
||||
constexpr bool alwaysFalse = !std::is_same_v<T, T>;
|
||||
@@ -175,6 +226,8 @@ get(STAmount const& a)
|
||||
return a.iou();
|
||||
else if constexpr (std::is_same_v<XRPAmount, T>)
|
||||
return a.xrp();
|
||||
else if constexpr (std::is_same_v<MPTAmount, T>)
|
||||
return a.mpt();
|
||||
else if constexpr (std::is_same_v<STAmount, T>)
|
||||
return a;
|
||||
else
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user