Compare commits

...

104 Commits

Author SHA1 Message Date
Ed Hennis
945c362559 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-11-03 12:41:52 -05:00
Jingchen
8ac8a47c99 refactor: Retire ImmediateOfferKilled amendment (#5973)
Amendments activated for more than 2 years can be retired. This change retires the ImmediateOfferKilled amendment.
2025-11-03 17:26:12 +00:00
Bart
12c4b5a632 ci: Update CI image hashes to use netstat (#5987)
To debug test failures we would like to use `netstat`, but that package wasn't installed yet in the CI images. This change uses the new CI images created by https://github.com/XRPLF/ci/pull/79.
2025-11-03 16:57:24 +00:00
Bart
25c5e3b17f chore: Remove version number in find_dependency for OpenSSL (#5985)
We are already using OpenSSL 3.5.2. The version number in the `find_dependency` statement is optional, and belongs in `conanfile.py` anyway.
2025-11-03 13:53:19 +00:00
Jingchen
8eb233c2ea refactor: Modularize shamap and nodestore (#5668)
This change moves the shamap and nodestore from `xrpld` to `libxrpl`.
2025-10-31 22:25:16 +00:00
Jingchen
50fc93f742 refactor: Retire fixMasterKeyAsRegularKey amendment (#5959)
Amendments activated for more than 2 years can be retired. This change retires the fixMasterKeyAsRegularKey amendment.
2025-10-31 21:01:44 +00:00
Jingchen
ab45a8a737 refactor: Retire fixReducedOffersV1 amendment (#5972)
Amendments activated for more than 2 years can be retired. This change retires the fixReducedOffersV1 amendment.
2025-10-31 20:25:05 +00:00
Jingchen
dfafb141cc refactor: Retire fixAmendmentMajorityCalc amendment (#5961)
Amendments activated for more than 2 years can be retired. This change retires the fixAmendmentMajorityCalc amendment.
2025-10-31 20:01:12 +00:00
Mayukha Vadari
4e32d2ed98 refactor: Clean up TxMeta (#5845)
This change:
* Simplifies the `TxMeta` constructors - both were setting the same set of fields, and to make it harder for future bugs to arise and keep the code DRY, we can combine those into one helper function.
* Removes an unused constructor.
* Renames the variables to avoid Hungarian naming.
* Removes a bunch of now-unnecessary helper functions.
2025-10-31 19:29:30 +00:00
yinyiqian1
fa69918124 fix: Address permission delegation vulnerability (#5825)
This change introduces the `featurePermissionDelegationV1_1` amendment, which is designed to supersede both `featurePermissionDelegation` and `fixDelegateV1_1 amendments, which should be considered deprecated. The `checkPermission` function will now return `terNO_DELEGATE_PERMISSION` when a delegate transaction lacks the necessary permissions.
2025-10-31 15:01:06 -04:00
Ed Hennis
9546c52013 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-10-31 13:51:19 -04:00
Ed Hennis
cbbb2b1be0 test: Count crashed test suites (#5924)
When outputting the unit test summary, this change counts crashed tests as failures.
2025-10-31 17:10:53 +00:00
Ed Hennis
3a099aeb64 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-10-31 12:51:28 -04:00
Vlad
cf2d763fa1 refactor: Improve txset handling (#5951) 2025-10-31 16:10:14 +00:00
Bronek Kozicki
2dd1d682ac Remove directory size limit (#5935)
This change introduces the `fixDirectoryLimit` amendment to remove the directory pages limit. We found that the directory size limit is easier to hit than originally assumed, and there is no good reason to keep this limit, since the object reserve provides the necessary incentive to avoid creating unnecessary objects on the ledger.
2025-10-30 21:31:03 +00:00
Bronek Kozicki
4cb1084c02 fix: Change Credential sfSubjectNode to optional (#5936)
Field `sfSubjectNode` is not populated by `CredentialCreate` in self-issued credentials. Rather than fixup the Credentials already on the ledger, we can in this case safely change the object template for this field from `soeREQUIRED` to `soeOPTIONAL`.
2025-10-30 21:04:55 +00:00
Ed Hennis
8d1b3b3994 refactor: Add support for extra transaction signature validation (#5851)
- Restructures `STTx` signature checking code to be able to handle
  a `sigObject`, which may be the full transaction, or may be an object
  field containing a separate signature. Either way, the `sigObject` can
  be a single- or multi-sign signature.
- This is distinct from 550f90a75e (#5594), which changed the check in
  Transactor, which validates whether a given account is allowed to sign
  for the given transaction. This cryptographically checks the signature
  validity.
2025-10-30 15:39:56 -04:00
Pratik Mankawde
b39d7a6519 refactor: Retire fixQualityUpperBound amendment (#5960)
Amendments activated for more than 2 years can be retired. This change retires the fixQualityUpperBound amendment.
2025-10-30 18:47:47 +00:00
Pratik Mankawde
b0910e359e refactor: Retire fix1623 amendment (#5928)
Amendments activated for more than 2 years can be retired. This change retires the fix1623 amendment.
2025-10-30 17:33:08 +00:00
Pratik Mankawde
44e027e516 refactor: Retire fixTakerDryOfferRemoval amendment (#5958)
Amendments activated for more than 2 years can be retired. This change retires the fixTakerDryOfferRemoval amendment.
2025-10-30 11:27:01 -04:00
Bart
a10f42a3aa ci: Check whether test failures are caused by port exhaustion (#5938)
This change adds an extra step to the CI test job that outputs network info, which may allow us to confirm whether random test failures are caused by port exhaustion.
2025-10-30 13:19:51 +00:00
Ayaz Salikhov
efd4c1b95d chore: Use new prepare-runner (#5970)
See: XRPLF/actions#19.
2025-10-30 08:49:44 -04:00
Ed Hennis
8567bd0d12 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-10-29 14:23:15 -04:00
Pratik Mankawde
f8b4f692f1 refactor: Retire fixSTAmountCanonicalize code (#5956)
Amendments activated for more than 2 years can be retired. This change retires the fixSTAmountCanonicalize amendment.
2025-10-29 18:17:50 +00:00
Ed Hennis
3cb1851537 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-10-29 13:42:25 -04:00
Pratik Mankawde
80a3ae6386 refactor: Retire fixRmSmallIncreasedQOffers amendment (#5955)
Amendments activated for more than 2 years can be retired. This change retires the fixRmSmallIncreasedQOffers amendment.
2025-10-29 17:34:06 +00:00
Bart
48d38c1e2c refactor: Sorts retired amendments to reduce conflicts (#5966)
We are on an amendment retiring spree, but each change results in conflicts in `features.macro` because currently they all add the retired amendment to the end of the list. By sorting the list the number of conflicts should be reduced, making it easier to merge them.
2025-10-29 17:03:16 +00:00
Ed Hennis
55feea308e Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-10-29 12:54:20 -04:00
Jingchen
553fb5be3b refactor: Retire fixCheckThreading amendment (#5957)
Amendments activated for more than 2 years can be retired. This change retires the fixCheckThreading amendment.
2025-10-29 16:36:51 +00:00
Pratik Mankawde
efa917d9f3 refactor: Retire fix1578 amendment (#5927)
Amendments activated for more than 2 years can be retired. This change retires the fix1578 amendment.
2025-10-29 16:08:17 +00:00
Pratik Mankawde
bd3bc917f8 refactor: Retire fix1571 amendment (#5925)
Amendments activated for more than 2 years can be retired. This change retires the fix1571 amendment.

Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-29 14:21:50 +00:00
Jingchen
ed5d6f3e22 feat: Add public key to log messages (#5678)
To protect the identity of UNL validators, the IP addresses are redacted from the log messages sent to the common Grafana instance. However, without such identifying information it is challenging to debug issues. This change adds a node's public key to logs to improve our ability to debug issues.

Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-29 14:16:37 +00:00
Pratik Mankawde
a8e4da0b11 Retire fix1781 amendment (#5931)
* Retired fix1781 amendment

Signed-off-by: Pratik Mankawde <pmankawde@ripple.com>

* refactor: Retire fix1781 amendment

Amendments activated for more than 2 years can be retired. This change retires the fix1781 amendment.

---------

Signed-off-by: Pratik Mankawde <pmankawde@ripple.com>
Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-29 11:32:43 +00:00
Bart
1dd60242de ci: Use nproc-2 to set parallelism for builds and tests (#5939)
This change reduces the number of cores used to build and test, as using all cores may be contributing to occasional build and test failures.

Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-29 00:07:09 +00:00
Ed Hennis
a6692af17a Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-10-28 17:38:25 -04:00
Bart
76611c3f46 ci: Use commit hash so workflows are not canceled when merging multiple PRs (#5950)
This change changes the CI concurrency group for pushes to the `develop` branch to use the commit hash instead of the target branch.

Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-28 20:08:08 +00:00
Bart
5efaf0c328 ci: Only upload codecov reports in the original repo, not in forks (#5953)
Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-28 19:52:52 +00:00
Bart
0aa23933ea ci: Only log into Conan when uploading packages (#5952)
There are separate steps for logging into Conan and uploading packages. However, at the moment sometimes the login step is executed even though no packages will be uploaded. The condition for performing both steps should be the same.

Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-28 19:52:13 +00:00
Bronek Kozicki
21f3c12d85 fix: invariant error in fee-sized VaultWithdraw (#5876)
This changes fixes an invariant error where the amount withdrawn is equal to the transaction fee.

Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-28 18:12:11 +00:00
Copilot
7d5ed0cd8d fix: account_tx limit parameter validation for malformed values (#5891)
This change fixes the `account_tx` RPC method to properly validate malformed limit parameter values. Previously, invalid values like `0`, `1.2`, `"10"`, `true`, `false`, `-1`, `[]`, `{}`, etc. were either accepted without errors or caused internal errors. Now all malformed values correctly return the `invalidParams` error.

Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-28 17:42:43 +00:00
Pratik Mankawde
d9960d5ba0 refactor: Retire fix1543 amendment (#5926)
Amendments activated for more than 2 years can be retired. This change retires the fix1543 amendment.

Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-28 15:10:38 +00:00
Ayaz Salikhov
91fa6b2295 ci: Only run .exe files during test phase on Windows (#5947) 2025-10-28 14:26:25 +00:00
Jingchen
76f774e22d refactor: Migrate json unit tests to use doctest (#5533)
Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-28 14:19:39 +00:00
Shawn Xie
f4f7618173 Change fixMPTDeliveredAmount to Supported::yes (#5833)
Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-27 19:04:14 +00:00
Ayaz Salikhov
66f16469f9 fix: Upload all test binaries (#5932) 2025-10-27 17:27:56 +00:00
Ayaz Salikhov
1845b1c656 chore: Better pre-commit failure message (#5940) 2025-10-27 14:43:45 +00:00
Ed Hennis
1d058a5d78 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-10-26 19:12:36 -04:00
Ayaz Salikhov
e192ffe964 fix: Clean up build profile options (#5934)
The `-Wno-missing-template-arg-list-after-template-kw` flag is only needed for the grpc library. Use `+=` for the default build flags to make it easier to extend in the future.

Co-authored-by: Bart Thomee <11445373+bthomee@users.noreply.github.com>
2025-10-24 15:16:15 +00:00
Ed Hennis
a70821adc5 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-10-23 13:24:29 -04:00
Ed Hennis
bfeb60d3f5 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-10-22 11:38:53 -04:00
Ed Hennis
c86bfa32f7 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-10-21 22:20:09 -04:00
Ed Hennis
0f44d619b6 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-10-17 18:21:41 -04:00
Ed Hennis
2add6a7917 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-10-16 13:12:12 -04:00
Ed Hennis
d21c4f3218 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-10-16 10:48:48 -04:00
Ed Hennis
265a504301 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-10-10 13:01:37 -04:00
Ed Hennis
b1e576d3d1 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-10-09 15:14:51 -04:00
Ed Hennis
d2d3039ce6 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-10-08 14:21:37 -04:00
Ed Hennis
16e85a7b79 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-10-02 11:03:12 -04:00
Ed Hennis
4ae1c01e13 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-10-01 18:11:01 -04:00
Ed Hennis
8807afc074 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-10-01 13:14:26 -04:00
Ed Hennis
a4e13e07d5 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-30 22:28:57 -04:00
Ed Hennis
6067d59336 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-29 18:34:47 -04:00
Ed Hennis
e14aecee66 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-29 13:32:16 -04:00
Ed Hennis
0e4c3e3427 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-26 19:26:10 -04:00
Ed Hennis
da5c563426 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-26 13:41:39 -04:00
Ed Hennis
b9f5d8b1c5 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-26 12:09:21 -04:00
Ed Hennis
5ea7b562a2 Review feedback from @mvadari: Document test lambdas 2025-09-25 14:23:10 -04:00
Ed Hennis
8450970b80 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-25 13:27:21 -04:00
Ed Hennis
14d4cff530 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-24 15:50:03 -04:00
Ed Hennis
88ac659d86 Move the lambda to the top so that the parse functions stay alphabetical 2025-09-24 12:54:47 -04:00
Ed Hennis
43fdbf27b9 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-20 15:44:43 -04:00
Ed Hennis
1e33f8e868 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-18 14:08:38 -04:00
Ed Hennis
a6e30857df Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-18 12:26:54 -04:00
Ed Hennis
563f24edb0 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-17 10:49:24 -04:00
Ed Hennis
a89f6d5da2 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-16 11:15:08 -04:00
Ed Hennis
5b2e91986a Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-15 11:13:49 -04:00
Ed Hennis
fbc5056817 Gate the new "index: special_case" on the current beta apiVersion 3 2025-09-12 14:02:38 -04:00
Ed Hennis
b7cafed040 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-11 10:33:34 -04:00
Ed Hennis
b6ebd34b30 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-10 19:40:02 -04:00
Ed Hennis
74c2765159 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-09 17:14:37 -04:00
Ed Hennis
62c7fdadba Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-08 11:42:06 -04:00
Ed Hennis
372c66e684 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-05 17:44:24 -04:00
Ed Hennis
a2fab5bcaf Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-04 20:25:13 -04:00
Ed Hennis
2e4f41571c Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-04 16:44:07 -04:00
Ed Hennis
8799a6dbfd Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-04 12:36:56 -04:00
Ed Hennis
e655087027 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-09-03 14:04:19 -04:00
Ed Hennis
46bd2a4090 Merge remote-tracking branch 'upstream/develop' into ximinez/fixed-ledger-entries
* upstream/develop:
  Refactor `ledger_entry` RPC source code and tests (5237)
2025-08-29 17:55:45 -04:00
Ed Hennis
f3b8a8aef3 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-08-29 10:43:07 -04:00
Ed Hennis
ee0c917e95 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-08-28 18:17:43 -04:00
Ed Hennis
375aedd340 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-08-27 11:15:17 -04:00
Ed Hennis
95397a7710 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-08-25 19:51:08 -04:00
Ed Hennis
7af8a52d27 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-08-22 20:34:53 -04:00
Ed Hennis
326a8093c9 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-08-22 19:31:27 -04:00
Ed Hennis
9f0e159205 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-08-22 19:08:59 -04:00
Ed Hennis
2fda101b44 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-08-21 11:39:13 -04:00
Ed Hennis
e6e1e4f9dd Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-08-19 16:05:38 -04:00
Ed Hennis
70591265e5 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-08-18 12:26:01 -04:00
Ed Hennis
ed1d477a45 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-08-08 18:23:40 -04:00
Ed Hennis
cd58f636d3 Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-08-06 21:03:20 -04:00
Ed Hennis
3152f2233f Merge branch 'develop' into ximinez/fixed-ledger-entries 2025-08-05 21:17:03 -04:00
Ed Hennis
0c147a895c Restrict which values are valid for fixed types.
- True or a ledger index for those that can't parameters
- Number, true, or a ledger index for "hashes".
2025-08-04 19:23:59 -04:00
Ed Hennis
cf80710ef1 Refactor a little bit to reduce future conflicts
- Specifically #5237
2025-08-04 17:38:52 -04:00
Ed Hennis
fc929ab984 Add support for "index":"fixed type" lookups in ledger_entry
- For example "index":"amendments" will return the amendments object as
  if the request was
  "index":"7DB0788C020F02780A673DC74757F23823FA3014C1866E72CC4CD8B226CD6EF4"
- Works for amendments, fee, nunl, and hashes (for the recent history
  list only).
- Always returns the valid computed index, even if the object is not
  found.
2025-08-04 17:23:45 -04:00
Ed Hennis
145a8817dc Add ledger_entry options for fee, amendments, NUNL, and hashes
- Request format for fee, amendments, and nunl is
  "fieldName":<any valid json>, including null. Because these types
  have no inputs to the index computation, any value
  works.
- Request format for hashes is "hashes":<uint value or any valid
  json>. If the value is numeric, and evaluates to a uint, return the
  hashes history page for that ledger sequence. (AKA "long" skip list.)
  Any other valid json value will return the "short" skip list.
2025-08-04 17:23:43 -04:00
234 changed files with 4972 additions and 4038 deletions

View File

@@ -4,20 +4,23 @@ description: "Install Conan dependencies, optionally forcing a rebuild of all de
# Note that actions do not support 'type' and all inputs are strings, see # Note that actions do not support 'type' and all inputs are strings, see
# https://docs.github.com/en/actions/reference/workflows-and-actions/metadata-syntax#inputs. # https://docs.github.com/en/actions/reference/workflows-and-actions/metadata-syntax#inputs.
inputs: inputs:
verbosity:
description: "The build verbosity."
required: false
default: "verbose"
build_dir: build_dir:
description: "The directory where to build." description: "The directory where to build."
required: true required: true
build_type: build_type:
description: 'The build type to use ("Debug", "Release").' description: 'The build type to use ("Debug", "Release").'
required: true required: true
build_nproc:
description: "The number of processors to use for building."
required: true
force_build: force_build:
description: 'Force building of all dependencies ("true", "false").' description: 'Force building of all dependencies ("true", "false").'
required: false required: false
default: "false" default: "false"
log_verbosity:
description: "The logging verbosity."
required: false
default: "verbose"
runs: runs:
using: composite using: composite
@@ -26,9 +29,10 @@ runs:
shell: bash shell: bash
env: env:
BUILD_DIR: ${{ inputs.build_dir }} BUILD_DIR: ${{ inputs.build_dir }}
BUILD_NPROC: ${{ inputs.build_nproc }}
BUILD_OPTION: ${{ inputs.force_build == 'true' && '*' || 'missing' }} BUILD_OPTION: ${{ inputs.force_build == 'true' && '*' || 'missing' }}
BUILD_TYPE: ${{ inputs.build_type }} BUILD_TYPE: ${{ inputs.build_type }}
VERBOSITY: ${{ inputs.verbosity }} LOG_VERBOSITY: ${{ inputs.log_verbosity }}
run: | run: |
echo 'Installing dependencies.' echo 'Installing dependencies.'
mkdir -p "${BUILD_DIR}" mkdir -p "${BUILD_DIR}"
@@ -39,6 +43,7 @@ runs:
--options:host='&:tests=True' \ --options:host='&:tests=True' \
--options:host='&:xrpld=True' \ --options:host='&:xrpld=True' \
--settings:all build_type="${BUILD_TYPE}" \ --settings:all build_type="${BUILD_TYPE}" \
--conf:all tools.build:verbosity="${VERBOSITY}" \ --conf:all tools.build:jobs=${BUILD_NPROC} \
--conf:all tools.compilation:verbosity="${VERBOSITY}" \ --conf:all tools.build:verbosity="${LOG_VERBOSITY}" \
--conf:all tools.compilation:verbosity="${LOG_VERBOSITY}" \
.. ..

View File

@@ -17,7 +17,7 @@ Loop: xrpld.app xrpld.rpc
xrpld.rpc > xrpld.app xrpld.rpc > xrpld.app
Loop: xrpld.app xrpld.shamap Loop: xrpld.app xrpld.shamap
xrpld.app > xrpld.shamap xrpld.shamap ~= xrpld.app
Loop: xrpld.core xrpld.perflog Loop: xrpld.core xrpld.perflog
xrpld.perflog == xrpld.core xrpld.perflog == xrpld.core

View File

@@ -8,6 +8,10 @@ libxrpl.ledger > xrpl.ledger
libxrpl.ledger > xrpl.protocol libxrpl.ledger > xrpl.protocol
libxrpl.net > xrpl.basics libxrpl.net > xrpl.basics
libxrpl.net > xrpl.net libxrpl.net > xrpl.net
libxrpl.nodestore > xrpl.basics
libxrpl.nodestore > xrpl.json
libxrpl.nodestore > xrpl.nodestore
libxrpl.nodestore > xrpl.protocol
libxrpl.protocol > xrpl.basics libxrpl.protocol > xrpl.basics
libxrpl.protocol > xrpl.json libxrpl.protocol > xrpl.json
libxrpl.protocol > xrpl.protocol libxrpl.protocol > xrpl.protocol
@@ -18,6 +22,9 @@ libxrpl.server > xrpl.basics
libxrpl.server > xrpl.json libxrpl.server > xrpl.json
libxrpl.server > xrpl.protocol libxrpl.server > xrpl.protocol
libxrpl.server > xrpl.server libxrpl.server > xrpl.server
libxrpl.shamap > xrpl.basics
libxrpl.shamap > xrpl.protocol
libxrpl.shamap > xrpl.shamap
test.app > test.jtx test.app > test.jtx
test.app > test.rpc test.app > test.rpc
test.app > test.toplevel test.app > test.toplevel
@@ -25,11 +32,11 @@ test.app > test.unit_test
test.app > xrpl.basics test.app > xrpl.basics
test.app > xrpld.app test.app > xrpld.app
test.app > xrpld.core test.app > xrpld.core
test.app > xrpld.nodestore
test.app > xrpld.overlay test.app > xrpld.overlay
test.app > xrpld.rpc test.app > xrpld.rpc
test.app > xrpl.json test.app > xrpl.json
test.app > xrpl.ledger test.app > xrpl.ledger
test.app > xrpl.nodestore
test.app > xrpl.protocol test.app > xrpl.protocol
test.app > xrpl.resource test.app > xrpl.resource
test.basics > test.jtx test.basics > test.jtx
@@ -86,8 +93,7 @@ test.nodestore > test.toplevel
test.nodestore > test.unit_test test.nodestore > test.unit_test
test.nodestore > xrpl.basics test.nodestore > xrpl.basics
test.nodestore > xrpld.core test.nodestore > xrpld.core
test.nodestore > xrpld.nodestore test.nodestore > xrpl.nodestore
test.nodestore > xrpld.unity
test.overlay > test.jtx test.overlay > test.jtx
test.overlay > test.toplevel test.overlay > test.toplevel
test.overlay > test.unit_test test.overlay > test.unit_test
@@ -95,8 +101,8 @@ test.overlay > xrpl.basics
test.overlay > xrpld.app test.overlay > xrpld.app
test.overlay > xrpld.overlay test.overlay > xrpld.overlay
test.overlay > xrpld.peerfinder test.overlay > xrpld.peerfinder
test.overlay > xrpld.shamap
test.overlay > xrpl.protocol test.overlay > xrpl.protocol
test.overlay > xrpl.shamap
test.peerfinder > test.beast test.peerfinder > test.beast
test.peerfinder > test.unit_test test.peerfinder > test.unit_test
test.peerfinder > xrpl.basics test.peerfinder > xrpl.basics
@@ -131,18 +137,21 @@ test.server > xrpl.json
test.server > xrpl.server test.server > xrpl.server
test.shamap > test.unit_test test.shamap > test.unit_test
test.shamap > xrpl.basics test.shamap > xrpl.basics
test.shamap > xrpld.nodestore test.shamap > xrpl.nodestore
test.shamap > xrpld.shamap
test.shamap > xrpl.protocol test.shamap > xrpl.protocol
test.shamap > xrpl.shamap
test.toplevel > test.csf test.toplevel > test.csf
test.toplevel > xrpl.json test.toplevel > xrpl.json
test.unit_test > xrpl.basics test.unit_test > xrpl.basics
tests.libxrpl > xrpl.basics tests.libxrpl > xrpl.basics
tests.libxrpl > xrpl.json
tests.libxrpl > xrpl.net tests.libxrpl > xrpl.net
xrpl.json > xrpl.basics xrpl.json > xrpl.basics
xrpl.ledger > xrpl.basics xrpl.ledger > xrpl.basics
xrpl.ledger > xrpl.protocol xrpl.ledger > xrpl.protocol
xrpl.net > xrpl.basics xrpl.net > xrpl.basics
xrpl.nodestore > xrpl.basics
xrpl.nodestore > xrpl.protocol
xrpl.protocol > xrpl.basics xrpl.protocol > xrpl.basics
xrpl.protocol > xrpl.json xrpl.protocol > xrpl.json
xrpl.resource > xrpl.basics xrpl.resource > xrpl.basics
@@ -151,17 +160,21 @@ xrpl.resource > xrpl.protocol
xrpl.server > xrpl.basics xrpl.server > xrpl.basics
xrpl.server > xrpl.json xrpl.server > xrpl.json
xrpl.server > xrpl.protocol xrpl.server > xrpl.protocol
xrpl.shamap > xrpl.basics
xrpl.shamap > xrpl.nodestore
xrpl.shamap > xrpl.protocol
xrpld.app > test.unit_test xrpld.app > test.unit_test
xrpld.app > xrpl.basics xrpld.app > xrpl.basics
xrpld.app > xrpld.conditions xrpld.app > xrpld.conditions
xrpld.app > xrpld.consensus xrpld.app > xrpld.consensus
xrpld.app > xrpld.nodestore
xrpld.app > xrpld.perflog xrpld.app > xrpld.perflog
xrpld.app > xrpl.json xrpld.app > xrpl.json
xrpld.app > xrpl.ledger xrpld.app > xrpl.ledger
xrpld.app > xrpl.net xrpld.app > xrpl.net
xrpld.app > xrpl.nodestore
xrpld.app > xrpl.protocol xrpld.app > xrpl.protocol
xrpld.app > xrpl.resource xrpld.app > xrpl.resource
xrpld.app > xrpl.shamap
xrpld.conditions > xrpl.basics xrpld.conditions > xrpl.basics
xrpld.conditions > xrpl.protocol xrpld.conditions > xrpl.protocol
xrpld.consensus > xrpl.basics xrpld.consensus > xrpl.basics
@@ -171,11 +184,6 @@ xrpld.core > xrpl.basics
xrpld.core > xrpl.json xrpld.core > xrpl.json
xrpld.core > xrpl.net xrpld.core > xrpl.net
xrpld.core > xrpl.protocol xrpld.core > xrpl.protocol
xrpld.nodestore > xrpl.basics
xrpld.nodestore > xrpld.core
xrpld.nodestore > xrpld.unity
xrpld.nodestore > xrpl.json
xrpld.nodestore > xrpl.protocol
xrpld.overlay > xrpl.basics xrpld.overlay > xrpl.basics
xrpld.overlay > xrpld.core xrpld.overlay > xrpld.core
xrpld.overlay > xrpld.peerfinder xrpld.overlay > xrpld.peerfinder
@@ -191,13 +199,11 @@ xrpld.perflog > xrpl.basics
xrpld.perflog > xrpl.json xrpld.perflog > xrpl.json
xrpld.rpc > xrpl.basics xrpld.rpc > xrpl.basics
xrpld.rpc > xrpld.core xrpld.rpc > xrpld.core
xrpld.rpc > xrpld.nodestore
xrpld.rpc > xrpl.json xrpld.rpc > xrpl.json
xrpld.rpc > xrpl.ledger xrpld.rpc > xrpl.ledger
xrpld.rpc > xrpl.net xrpld.rpc > xrpl.net
xrpld.rpc > xrpl.nodestore
xrpld.rpc > xrpl.protocol xrpld.rpc > xrpl.protocol
xrpld.rpc > xrpl.resource xrpld.rpc > xrpl.resource
xrpld.rpc > xrpl.server xrpld.rpc > xrpl.server
xrpld.shamap > xrpl.basics xrpld.shamap > xrpl.shamap
xrpld.shamap > xrpld.nodestore
xrpld.shamap > xrpl.protocol

View File

@@ -15,168 +15,168 @@
"distro_version": "bookworm", "distro_version": "bookworm",
"compiler_name": "gcc", "compiler_name": "gcc",
"compiler_version": "12", "compiler_version": "12",
"image_sha": "6948666" "image_sha": "97ba375"
}, },
{ {
"distro_name": "debian", "distro_name": "debian",
"distro_version": "bookworm", "distro_version": "bookworm",
"compiler_name": "gcc", "compiler_name": "gcc",
"compiler_version": "13", "compiler_version": "13",
"image_sha": "6948666" "image_sha": "97ba375"
}, },
{ {
"distro_name": "debian", "distro_name": "debian",
"distro_version": "bookworm", "distro_version": "bookworm",
"compiler_name": "gcc", "compiler_name": "gcc",
"compiler_version": "14", "compiler_version": "14",
"image_sha": "6948666" "image_sha": "97ba375"
}, },
{ {
"distro_name": "debian", "distro_name": "debian",
"distro_version": "bookworm", "distro_version": "bookworm",
"compiler_name": "gcc", "compiler_name": "gcc",
"compiler_version": "15", "compiler_version": "15",
"image_sha": "6948666" "image_sha": "97ba375"
}, },
{ {
"distro_name": "debian", "distro_name": "debian",
"distro_version": "bookworm", "distro_version": "bookworm",
"compiler_name": "clang", "compiler_name": "clang",
"compiler_version": "16", "compiler_version": "16",
"image_sha": "6948666" "image_sha": "97ba375"
}, },
{ {
"distro_name": "debian", "distro_name": "debian",
"distro_version": "bookworm", "distro_version": "bookworm",
"compiler_name": "clang", "compiler_name": "clang",
"compiler_version": "17", "compiler_version": "17",
"image_sha": "6948666" "image_sha": "97ba375"
}, },
{ {
"distro_name": "debian", "distro_name": "debian",
"distro_version": "bookworm", "distro_version": "bookworm",
"compiler_name": "clang", "compiler_name": "clang",
"compiler_version": "18", "compiler_version": "18",
"image_sha": "6948666" "image_sha": "97ba375"
}, },
{ {
"distro_name": "debian", "distro_name": "debian",
"distro_version": "bookworm", "distro_version": "bookworm",
"compiler_name": "clang", "compiler_name": "clang",
"compiler_version": "19", "compiler_version": "19",
"image_sha": "6948666" "image_sha": "97ba375"
}, },
{ {
"distro_name": "debian", "distro_name": "debian",
"distro_version": "bookworm", "distro_version": "bookworm",
"compiler_name": "clang", "compiler_name": "clang",
"compiler_version": "20", "compiler_version": "20",
"image_sha": "6948666" "image_sha": "97ba375"
}, },
{ {
"distro_name": "rhel", "distro_name": "rhel",
"distro_version": "8", "distro_version": "8",
"compiler_name": "gcc", "compiler_name": "gcc",
"compiler_version": "14", "compiler_version": "14",
"image_sha": "10e69b4" "image_sha": "97ba375"
}, },
{ {
"distro_name": "rhel", "distro_name": "rhel",
"distro_version": "8", "distro_version": "8",
"compiler_name": "clang", "compiler_name": "clang",
"compiler_version": "any", "compiler_version": "any",
"image_sha": "10e69b4" "image_sha": "97ba375"
}, },
{ {
"distro_name": "rhel", "distro_name": "rhel",
"distro_version": "9", "distro_version": "9",
"compiler_name": "gcc", "compiler_name": "gcc",
"compiler_version": "12", "compiler_version": "12",
"image_sha": "10e69b4" "image_sha": "97ba375"
}, },
{ {
"distro_name": "rhel", "distro_name": "rhel",
"distro_version": "9", "distro_version": "9",
"compiler_name": "gcc", "compiler_name": "gcc",
"compiler_version": "13", "compiler_version": "13",
"image_sha": "10e69b4" "image_sha": "97ba375"
}, },
{ {
"distro_name": "rhel", "distro_name": "rhel",
"distro_version": "9", "distro_version": "9",
"compiler_name": "gcc", "compiler_name": "gcc",
"compiler_version": "14", "compiler_version": "14",
"image_sha": "10e69b4" "image_sha": "97ba375"
}, },
{ {
"distro_name": "rhel", "distro_name": "rhel",
"distro_version": "9", "distro_version": "9",
"compiler_name": "clang", "compiler_name": "clang",
"compiler_version": "any", "compiler_version": "any",
"image_sha": "10e69b4" "image_sha": "97ba375"
}, },
{ {
"distro_name": "rhel", "distro_name": "rhel",
"distro_version": "10", "distro_version": "10",
"compiler_name": "gcc", "compiler_name": "gcc",
"compiler_version": "14", "compiler_version": "14",
"image_sha": "10e69b4" "image_sha": "97ba375"
}, },
{ {
"distro_name": "rhel", "distro_name": "rhel",
"distro_version": "10", "distro_version": "10",
"compiler_name": "clang", "compiler_name": "clang",
"compiler_version": "any", "compiler_version": "any",
"image_sha": "10e69b4" "image_sha": "97ba375"
}, },
{ {
"distro_name": "ubuntu", "distro_name": "ubuntu",
"distro_version": "jammy", "distro_version": "jammy",
"compiler_name": "gcc", "compiler_name": "gcc",
"compiler_version": "12", "compiler_version": "12",
"image_sha": "6948666" "image_sha": "97ba375"
}, },
{ {
"distro_name": "ubuntu", "distro_name": "ubuntu",
"distro_version": "noble", "distro_version": "noble",
"compiler_name": "gcc", "compiler_name": "gcc",
"compiler_version": "13", "compiler_version": "13",
"image_sha": "6948666" "image_sha": "97ba375"
}, },
{ {
"distro_name": "ubuntu", "distro_name": "ubuntu",
"distro_version": "noble", "distro_version": "noble",
"compiler_name": "gcc", "compiler_name": "gcc",
"compiler_version": "14", "compiler_version": "14",
"image_sha": "6948666" "image_sha": "97ba375"
}, },
{ {
"distro_name": "ubuntu", "distro_name": "ubuntu",
"distro_version": "noble", "distro_version": "noble",
"compiler_name": "clang", "compiler_name": "clang",
"compiler_version": "16", "compiler_version": "16",
"image_sha": "6948666" "image_sha": "97ba375"
}, },
{ {
"distro_name": "ubuntu", "distro_name": "ubuntu",
"distro_version": "noble", "distro_version": "noble",
"compiler_name": "clang", "compiler_name": "clang",
"compiler_version": "17", "compiler_version": "17",
"image_sha": "6948666" "image_sha": "97ba375"
}, },
{ {
"distro_name": "ubuntu", "distro_name": "ubuntu",
"distro_version": "noble", "distro_version": "noble",
"compiler_name": "clang", "compiler_name": "clang",
"compiler_version": "18", "compiler_version": "18",
"image_sha": "6948666" "image_sha": "97ba375"
}, },
{ {
"distro_name": "ubuntu", "distro_name": "ubuntu",
"distro_version": "noble", "distro_version": "noble",
"compiler_name": "clang", "compiler_name": "clang",
"compiler_version": "19", "compiler_version": "19",
"image_sha": "6948666" "image_sha": "97ba375"
} }
], ],
"build_type": ["Debug", "Release"], "build_type": ["Debug", "Release"],

View File

@@ -50,7 +50,12 @@ on:
workflow_dispatch: workflow_dispatch:
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.ref }} # When a PR is merged into the develop branch it will be assigned a unique
# group identifier, so execution will continue even if another PR is merged
# while it is still running. In all other cases the group identifier is shared
# per branch, so that any in-progress runs are cancelled when a new commit is
# pushed.
group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' && github.sha || github.ref }}
cancel-in-progress: true cancel-in-progress: true
defaults: defaults:

View File

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

View File

@@ -23,6 +23,7 @@ defaults:
env: env:
BUILD_DIR: .build BUILD_DIR: .build
NPROC_SUBTRACT: 2
jobs: jobs:
publish: publish:
@@ -33,6 +34,13 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- name: Get number of processors
uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a
id: nproc
with:
subtract: ${{ env.NPROC_SUBTRACT }}
- name: Check configuration - name: Check configuration
run: | run: |
echo 'Checking path.' echo 'Checking path.'
@@ -46,12 +54,16 @@ jobs:
echo 'Checking Doxygen version.' echo 'Checking Doxygen version.'
doxygen --version doxygen --version
- name: Build documentation - name: Build documentation
env:
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
run: | run: |
mkdir -p "${BUILD_DIR}" mkdir -p "${BUILD_DIR}"
cd "${BUILD_DIR}" cd "${BUILD_DIR}"
cmake -Donly_docs=ON .. cmake -Donly_docs=ON ..
cmake --build . --target docs --parallel $(nproc) cmake --build . --target docs --parallel ${BUILD_NPROC}
- name: Publish documentation - name: Publish documentation
if: ${{ github.ref_type == 'branch' && github.ref_name == github.event.repository.default_branch }} if: ${{ github.ref_type == 'branch' && github.ref_name == github.event.repository.default_branch }}
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0 uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0

View File

@@ -39,6 +39,12 @@ on:
required: true required: true
type: string type: string
nproc_subtract:
description: "The number of processors to subtract when calculating parallelism."
required: false
type: number
default: 2
secrets: secrets:
CODECOV_TOKEN: CODECOV_TOKEN:
description: "The Codecov token to use for uploading coverage reports." description: "The Codecov token to use for uploading coverage reports."
@@ -55,6 +61,7 @@ jobs:
runs_on: ${{ inputs.runs_on }} runs_on: ${{ inputs.runs_on }}
image: ${{ inputs.image }} image: ${{ inputs.image }}
config_name: ${{ inputs.config_name }} config_name: ${{ inputs.config_name }}
nproc_subtract: ${{ inputs.nproc_subtract }}
secrets: secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
@@ -67,3 +74,4 @@ jobs:
runs_on: ${{ inputs.runs_on }} runs_on: ${{ inputs.runs_on }}
image: ${{ inputs.image }} image: ${{ inputs.image }}
config_name: ${{ inputs.config_name }} config_name: ${{ inputs.config_name }}
nproc_subtract: ${{ inputs.nproc_subtract }}

View File

@@ -34,6 +34,11 @@ on:
required: true required: true
type: string type: string
nproc_subtract:
description: "The number of processors to subtract when calculating parallelism."
required: true
type: number
secrets: secrets:
CODECOV_TOKEN: CODECOV_TOKEN:
description: "The Codecov token to use for uploading coverage reports." description: "The Codecov token to use for uploading coverage reports."
@@ -58,13 +63,19 @@ jobs:
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/.github/actions/prepare-runner@638e0dc11ea230f91bd26622fb542116bb5254d5 uses: XRPLF/actions/.github/actions/prepare-runner@99685816bb60a95a66852f212f382580e180df3a
with: with:
disable_ccache: false disable_ccache: false
- name: Print build environment - name: Print build environment
uses: ./.github/actions/print-env uses: ./.github/actions/print-env
- name: Get number of processors
uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a
id: nproc
with:
subtract: ${{ inputs.nproc_subtract }}
- name: Setup Conan - name: Setup Conan
uses: ./.github/actions/setup-conan uses: ./.github/actions/setup-conan
@@ -72,7 +83,11 @@ jobs:
uses: ./.github/actions/build-deps uses: ./.github/actions/build-deps
with: with:
build_dir: ${{ inputs.build_dir }} build_dir: ${{ inputs.build_dir }}
build_nproc: ${{ steps.nproc.outputs.nproc }}
build_type: ${{ inputs.build_type }} build_type: ${{ inputs.build_type }}
# Set the verbosity to "quiet" for Windows to avoid an excessive
# amount of logs. For other OSes, the "verbose" logs are more useful.
log_verbosity: ${{ runner.os == 'Windows' && 'quiet' || 'verbose' }}
- name: Configure CMake - name: Configure CMake
shell: bash shell: bash
@@ -92,25 +107,42 @@ jobs:
shell: bash shell: bash
working-directory: ${{ inputs.build_dir }} working-directory: ${{ inputs.build_dir }}
env: env:
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
BUILD_TYPE: ${{ inputs.build_type }} BUILD_TYPE: ${{ inputs.build_type }}
CMAKE_TARGET: ${{ inputs.cmake_target }} CMAKE_TARGET: ${{ inputs.cmake_target }}
run: | run: |
cmake \ cmake \
--build . \ --build . \
--config "${BUILD_TYPE}" \ --config "${BUILD_TYPE}" \
--parallel $(nproc) \ --parallel ${BUILD_NPROC} \
--target "${CMAKE_TARGET}" --target "${CMAKE_TARGET}"
- name: Put built binaries in one location
shell: bash
working-directory: ${{ inputs.build_dir }}
env:
BUILD_TYPE_DIR: ${{ runner.os == 'Windows' && inputs.build_type || '' }}
CMAKE_TARGET: ${{ inputs.cmake_target }}
run: |
mkdir -p ./binaries/doctest/
cp ./${BUILD_TYPE_DIR}/rippled* ./binaries/
if [ "${CMAKE_TARGET}" != 'coverage' ]; then
cp ./src/tests/libxrpl/${BUILD_TYPE_DIR}/xrpl.test.* ./binaries/doctest/
fi
- name: Upload rippled artifact - name: Upload rippled artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
env:
BUILD_DIR: ${{ inputs.build_dir }}
with: with:
name: rippled-${{ inputs.config_name }} name: rippled-${{ inputs.config_name }}
path: ${{ inputs.build_dir }}/${{ runner.os == 'Windows' && inputs.build_type || '' }}/rippled${{ runner.os == 'Windows' && '.exe' || '' }} path: ${{ env.BUILD_DIR }}/binaries/
retention-days: 3 retention-days: 3
if-no-files-found: error if-no-files-found: error
- name: Upload coverage report - name: Upload coverage report
if: ${{ inputs.cmake_target == 'coverage' }} if: ${{ github.repository_owner == 'XRPLF' && inputs.cmake_target == 'coverage' }}
uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3 uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
with: with:
disable_search: true disable_search: true

View File

@@ -26,6 +26,11 @@ on:
required: true required: true
type: string type: string
nproc_subtract:
description: "The number of processors to subtract when calculating parallelism."
required: true
type: number
jobs: jobs:
test: test:
name: Test ${{ inputs.config_name }} name: Test ${{ inputs.config_name }}
@@ -33,6 +38,16 @@ jobs:
container: ${{ inputs.image != '' && inputs.image || null }} container: ${{ inputs.image != '' && inputs.image || null }}
timeout-minutes: 30 timeout-minutes: 30
steps: steps:
- name: Cleanup workspace
if: ${{ runner.os == 'macOS' }}
uses: XRPLF/actions/.github/actions/cleanup-workspace@3f044c7478548e3c32ff68980eeb36ece02b364e
- name: Get number of processors
uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a
id: nproc
with:
subtract: ${{ inputs.nproc_subtract }}
- name: Download rippled artifact - name: Download rippled artifact
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with: with:
@@ -62,9 +77,35 @@ jobs:
run: | run: |
./rippled --version | grep libvoidstar ./rippled --version | grep libvoidstar
- name: Test the binary - name: Run the embedded tests
if: ${{ inputs.run_tests }} if: ${{ inputs.run_tests }}
shell: bash shell: bash
env:
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
run: | run: |
./rippled --unittest --unittest-jobs $(nproc) ./rippled --unittest --unittest-jobs ${BUILD_NPROC}
ctest -j $(nproc) --output-on-failure
- name: Run the separate tests
if: ${{ inputs.run_tests }}
env:
EXT: ${{ runner.os == 'Windows' && '.exe' || '' }}
shell: bash
run: |
for test_file in ./doctest/*${EXT}; do
echo "Executing $test_file"
chmod +x "$test_file"
if [[ "${{ runner.os }}" == "Windows" && "$test_file" == "./doctest/xrpl.test.net.exe" ]]; then
echo "Skipping $test_file on Windows"
else
"$test_file"
fi
done
- name: Debug failure (Linux)
if: ${{ failure() && runner.os == 'Linux' && inputs.run_tests }}
shell: bash
run: |
echo "IPv4 local port range:"
cat /proc/sys/net/ipv4/ip_local_port_range
echo "Netstat:"
netstat -an

View File

@@ -34,6 +34,7 @@ on:
env: env:
CONAN_REMOTE_NAME: xrplf CONAN_REMOTE_NAME: xrplf
CONAN_REMOTE_URL: https://conan.ripplex.io CONAN_REMOTE_URL: https://conan.ripplex.io
NPROC_SUBTRACT: 2
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
@@ -61,12 +62,23 @@ jobs:
if: ${{ runner.os == 'macOS' }} if: ${{ runner.os == 'macOS' }}
uses: XRPLF/actions/.github/actions/cleanup-workspace@3f044c7478548e3c32ff68980eeb36ece02b364e uses: XRPLF/actions/.github/actions/cleanup-workspace@3f044c7478548e3c32ff68980eeb36ece02b364e
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Checkout repository
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/.github/actions/prepare-runner@638e0dc11ea230f91bd26622fb542116bb5254d5 uses: XRPLF/actions/.github/actions/prepare-runner@99685816bb60a95a66852f212f382580e180df3a
with: with:
disable_ccache: false disable_ccache: false
- name: Print build environment
uses: ./.github/actions/print-env
- name: Get number of processors
uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a
id: nproc
with:
subtract: ${{ env.NPROC_SUBTRACT }}
- name: Setup Conan - name: Setup Conan
uses: ./.github/actions/setup-conan uses: ./.github/actions/setup-conan
with: with:
@@ -77,18 +89,19 @@ jobs:
uses: ./.github/actions/build-deps uses: ./.github/actions/build-deps
with: with:
build_dir: .build build_dir: .build
build_nproc: ${{ steps.nproc.outputs.nproc }}
build_type: ${{ matrix.build_type }} build_type: ${{ matrix.build_type }}
force_build: ${{ github.event_name == 'schedule' || github.event.inputs.force_source_build == 'true' }} force_build: ${{ github.event_name == 'schedule' || github.event.inputs.force_source_build == 'true' }}
# The verbosity is set to "quiet" for Windows to avoid an excessive amount of logs, while it # Set the verbosity to "quiet" for Windows to avoid an excessive
# is set to "verbose" otherwise to provide more information during the build process. # amount of logs. For other OSes, the "verbose" logs are more useful.
verbosity: ${{ runner.os == 'Windows' && 'quiet' || 'verbose' }} log_verbosity: ${{ runner.os == 'Windows' && 'quiet' || 'verbose' }}
- name: Log into Conan remote - name: Log into Conan remote
if: ${{ github.repository_owner == 'XRPLF' && github.event_name != 'pull_request' }} if: ${{ github.repository_owner == 'XRPLF' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
run: conan remote login "${CONAN_REMOTE_NAME}" "${{ secrets.CONAN_REMOTE_USERNAME }}" --password "${{ secrets.CONAN_REMOTE_PASSWORD }}" run: conan remote login "${CONAN_REMOTE_NAME}" "${{ secrets.CONAN_REMOTE_USERNAME }}" --password "${{ secrets.CONAN_REMOTE_PASSWORD }}"
- name: Upload Conan packages - name: Upload Conan packages
if: ${{ github.repository_owner == 'XRPLF' && github.event_name != 'pull_request' && github.event_name != 'schedule' }} if: ${{ github.repository_owner == 'XRPLF' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
env: env:
FORCE_OPTION: ${{ github.event.inputs.force_upload == 'true' && '--force' || '' }} FORCE_OPTION: ${{ github.event.inputs.force_upload == 'true' && '--force' || '' }}
run: conan upload "*" --remote="${CONAN_REMOTE_NAME}" --confirm ${FORCE_OPTION} run: conan upload "*" --remote="${CONAN_REMOTE_NAME}" --confirm ${FORCE_OPTION}

View File

@@ -45,7 +45,7 @@ if (static OR APPLE OR MSVC)
set (OPENSSL_USE_STATIC_LIBS ON) set (OPENSSL_USE_STATIC_LIBS ON)
endif () endif ()
set (OPENSSL_MSVC_STATIC_RT ON) set (OPENSSL_MSVC_STATIC_RT ON)
find_dependency (OpenSSL 1.1.1 REQUIRED) find_dependency (OpenSSL REQUIRED)
find_dependency (ZLIB) find_dependency (ZLIB)
find_dependency (date) find_dependency (date)
if (TARGET ZLIB::ZLIB) if (TARGET ZLIB::ZLIB)

View File

@@ -53,14 +53,15 @@ add_library(xrpl.imports.main INTERFACE)
target_link_libraries(xrpl.imports.main target_link_libraries(xrpl.imports.main
INTERFACE INTERFACE
LibArchive::LibArchive
OpenSSL::Crypto
Ripple::boost
Ripple::opts
Ripple::syslibs
absl::random_random absl::random_random
date::date date::date
ed25519::ed25519 ed25519::ed25519
LibArchive::LibArchive
OpenSSL::Crypto
Ripple::boost
Ripple::libs
Ripple::opts
Ripple::syslibs
secp256k1::secp256k1 secp256k1::secp256k1
xrpl.libpb xrpl.libpb
xxHash::xxhash xxHash::xxhash
@@ -111,6 +112,21 @@ target_link_libraries(xrpl.libxrpl.net PUBLIC
add_module(xrpl server) add_module(xrpl server)
target_link_libraries(xrpl.libxrpl.server PUBLIC xrpl.libxrpl.protocol) target_link_libraries(xrpl.libxrpl.server PUBLIC xrpl.libxrpl.protocol)
add_module(xrpl nodestore)
target_link_libraries(xrpl.libxrpl.nodestore PUBLIC
xrpl.libxrpl.basics
xrpl.libxrpl.json
xrpl.libxrpl.protocol
)
add_module(xrpl shamap)
target_link_libraries(xrpl.libxrpl.shamap PUBLIC
xrpl.libxrpl.basics
xrpl.libxrpl.crypto
xrpl.libxrpl.protocol
xrpl.libxrpl.nodestore
)
add_module(xrpl ledger) add_module(xrpl ledger)
target_link_libraries(xrpl.libxrpl.ledger PUBLIC target_link_libraries(xrpl.libxrpl.ledger PUBLIC
xrpl.libxrpl.basics xrpl.libxrpl.basics
@@ -136,6 +152,8 @@ target_link_modules(xrpl PUBLIC
protocol protocol
resource resource
server server
nodestore
shamap
net net
ledger ledger
) )

View File

@@ -8,20 +8,23 @@ install (
TARGETS TARGETS
common common
opts opts
ripple_syslibs
ripple_boost ripple_boost
ripple_libs
ripple_syslibs
xrpl.imports.main xrpl.imports.main
xrpl.libpb xrpl.libpb
xrpl.libxrpl
xrpl.libxrpl.basics xrpl.libxrpl.basics
xrpl.libxrpl.beast xrpl.libxrpl.beast
xrpl.libxrpl.crypto xrpl.libxrpl.crypto
xrpl.libxrpl.json xrpl.libxrpl.json
xrpl.libxrpl.ledger
xrpl.libxrpl.net
xrpl.libxrpl.nodestore
xrpl.libxrpl.protocol xrpl.libxrpl.protocol
xrpl.libxrpl.resource xrpl.libxrpl.resource
xrpl.libxrpl.ledger
xrpl.libxrpl.server xrpl.libxrpl.server
xrpl.libxrpl.net xrpl.libxrpl.shamap
xrpl.libxrpl
antithesis-sdk-cpp antithesis-sdk-cpp
EXPORT RippleExports EXPORT RippleExports
LIBRARY DESTINATION lib LIBRARY DESTINATION lib

View File

@@ -7,7 +7,7 @@ function(xrpl_add_test name)
"${CMAKE_CURRENT_SOURCE_DIR}/${name}/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/${name}/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp"
) )
add_executable(${target} EXCLUDE_FROM_ALL ${ARGN} ${sources}) add_executable(${target} ${ARGN} ${sources})
isolate_headers( isolate_headers(
${target} ${target}

View File

@@ -1,6 +1,5 @@
# Global configuration for Conan. This is used to set the number of parallel # Global configuration for Conan. This is used to set the number of parallel
# downloads, uploads, and build jobs. # downloads and uploads.
core:non_interactive=True core:non_interactive=True
core.download:parallel={{ os.cpu_count() }} core.download:parallel={{ os.cpu_count() }}
core.upload:parallel={{ os.cpu_count() }} core.upload:parallel={{ os.cpu_count() }}
tools.build:jobs={{ os.cpu_count() - 1 }}

View File

@@ -21,11 +21,11 @@ compiler.libcxx={{detect_api.detect_libcxx(compiler, version, compiler_exe)}}
[conf] [conf]
{% if compiler == "clang" and compiler_version >= 19 %} {% if compiler == "clang" and compiler_version >= 19 %}
tools.build:cxxflags=['-Wno-missing-template-arg-list-after-template-kw'] grpc/1.50.1:tools.build:cxxflags+=['-Wno-missing-template-arg-list-after-template-kw']
{% endif %} {% endif %}
{% if compiler == "apple-clang" and compiler_version >= 17 %} {% if compiler == "apple-clang" and compiler_version >= 17 %}
tools.build:cxxflags=['-Wno-missing-template-arg-list-after-template-kw'] grpc/1.50.1:tools.build:cxxflags+=['-Wno-missing-template-arg-list-after-template-kw']
{% endif %} {% endif %}
{% if compiler == "gcc" and compiler_version < 13 %} {% if compiler == "gcc" and compiler_version < 13 %}
tools.build:cxxflags=['-Wno-restrict'] tools.build:cxxflags+=['-Wno-restrict']
{% endif %} {% endif %}

View File

@@ -20,7 +20,7 @@
#ifndef RIPPLE_NODESTORE_BACKEND_H_INCLUDED #ifndef RIPPLE_NODESTORE_BACKEND_H_INCLUDED
#define RIPPLE_NODESTORE_BACKEND_H_INCLUDED #define RIPPLE_NODESTORE_BACKEND_H_INCLUDED
#include <xrpld/nodestore/Types.h> #include <xrpl/nodestore/Types.h>
#include <cstdint> #include <cstdint>

View File

@@ -20,13 +20,12 @@
#ifndef RIPPLE_NODESTORE_DATABASE_H_INCLUDED #ifndef RIPPLE_NODESTORE_DATABASE_H_INCLUDED
#define RIPPLE_NODESTORE_DATABASE_H_INCLUDED #define RIPPLE_NODESTORE_DATABASE_H_INCLUDED
#include <xrpld/nodestore/Backend.h>
#include <xrpld/nodestore/NodeObject.h>
#include <xrpld/nodestore/Scheduler.h>
#include <xrpl/basics/BasicConfig.h> #include <xrpl/basics/BasicConfig.h>
#include <xrpl/basics/Log.h> #include <xrpl/basics/Log.h>
#include <xrpl/basics/TaggedCache.ipp> #include <xrpl/basics/TaggedCache.ipp>
#include <xrpl/nodestore/Backend.h>
#include <xrpl/nodestore/NodeObject.h>
#include <xrpl/nodestore/Scheduler.h>
#include <xrpl/protocol/SystemParameters.h> #include <xrpl/protocol/SystemParameters.h>
#include <condition_variable> #include <condition_variable>

View File

@@ -20,7 +20,7 @@
#ifndef RIPPLE_NODESTORE_DATABASEROTATING_H_INCLUDED #ifndef RIPPLE_NODESTORE_DATABASEROTATING_H_INCLUDED
#define RIPPLE_NODESTORE_DATABASEROTATING_H_INCLUDED #define RIPPLE_NODESTORE_DATABASEROTATING_H_INCLUDED
#include <xrpld/nodestore/Database.h> #include <xrpl/nodestore/Database.h>
namespace ripple { namespace ripple {
namespace NodeStore { namespace NodeStore {

View File

@@ -20,7 +20,7 @@
#ifndef RIPPLE_NODESTORE_DUMMYSCHEDULER_H_INCLUDED #ifndef RIPPLE_NODESTORE_DUMMYSCHEDULER_H_INCLUDED
#define RIPPLE_NODESTORE_DUMMYSCHEDULER_H_INCLUDED #define RIPPLE_NODESTORE_DUMMYSCHEDULER_H_INCLUDED
#include <xrpld/nodestore/Scheduler.h> #include <xrpl/nodestore/Scheduler.h>
namespace ripple { namespace ripple {
namespace NodeStore { namespace NodeStore {

View File

@@ -20,11 +20,10 @@
#ifndef RIPPLE_NODESTORE_FACTORY_H_INCLUDED #ifndef RIPPLE_NODESTORE_FACTORY_H_INCLUDED
#define RIPPLE_NODESTORE_FACTORY_H_INCLUDED #define RIPPLE_NODESTORE_FACTORY_H_INCLUDED
#include <xrpld/nodestore/Backend.h>
#include <xrpld/nodestore/Scheduler.h>
#include <xrpl/basics/BasicConfig.h> #include <xrpl/basics/BasicConfig.h>
#include <xrpl/beast/utility/Journal.h> #include <xrpl/beast/utility/Journal.h>
#include <xrpl/nodestore/Backend.h>
#include <xrpl/nodestore/Scheduler.h>
#include <nudb/store.hpp> #include <nudb/store.hpp>

View File

@@ -20,8 +20,8 @@
#ifndef RIPPLE_NODESTORE_MANAGER_H_INCLUDED #ifndef RIPPLE_NODESTORE_MANAGER_H_INCLUDED
#define RIPPLE_NODESTORE_MANAGER_H_INCLUDED #define RIPPLE_NODESTORE_MANAGER_H_INCLUDED
#include <xrpld/nodestore/DatabaseRotating.h> #include <xrpl/nodestore/DatabaseRotating.h>
#include <xrpld/nodestore/Factory.h> #include <xrpl/nodestore/Factory.h>
namespace ripple { namespace ripple {

View File

@@ -20,7 +20,7 @@
#ifndef RIPPLE_NODESTORE_SCHEDULER_H_INCLUDED #ifndef RIPPLE_NODESTORE_SCHEDULER_H_INCLUDED
#define RIPPLE_NODESTORE_SCHEDULER_H_INCLUDED #define RIPPLE_NODESTORE_SCHEDULER_H_INCLUDED
#include <xrpld/nodestore/Task.h> #include <xrpl/nodestore/Task.h>
#include <chrono> #include <chrono>

View File

@@ -20,7 +20,7 @@
#ifndef RIPPLE_NODESTORE_TYPES_H_INCLUDED #ifndef RIPPLE_NODESTORE_TYPES_H_INCLUDED
#define RIPPLE_NODESTORE_TYPES_H_INCLUDED #define RIPPLE_NODESTORE_TYPES_H_INCLUDED
#include <xrpld/nodestore/NodeObject.h> #include <xrpl/nodestore/NodeObject.h>
#include <vector> #include <vector>

View File

@@ -20,9 +20,9 @@
#ifndef RIPPLE_NODESTORE_BATCHWRITER_H_INCLUDED #ifndef RIPPLE_NODESTORE_BATCHWRITER_H_INCLUDED
#define RIPPLE_NODESTORE_BATCHWRITER_H_INCLUDED #define RIPPLE_NODESTORE_BATCHWRITER_H_INCLUDED
#include <xrpld/nodestore/Scheduler.h> #include <xrpl/nodestore/Scheduler.h>
#include <xrpld/nodestore/Task.h> #include <xrpl/nodestore/Task.h>
#include <xrpld/nodestore/Types.h> #include <xrpl/nodestore/Types.h>
#include <condition_variable> #include <condition_variable>
#include <mutex> #include <mutex>

View File

@@ -20,10 +20,9 @@
#ifndef RIPPLE_NODESTORE_DATABASENODEIMP_H_INCLUDED #ifndef RIPPLE_NODESTORE_DATABASENODEIMP_H_INCLUDED
#define RIPPLE_NODESTORE_DATABASENODEIMP_H_INCLUDED #define RIPPLE_NODESTORE_DATABASENODEIMP_H_INCLUDED
#include <xrpld/nodestore/Database.h>
#include <xrpl/basics/TaggedCache.h> #include <xrpl/basics/TaggedCache.h>
#include <xrpl/basics/chrono.h> #include <xrpl/basics/chrono.h>
#include <xrpl/nodestore/Database.h>
namespace ripple { namespace ripple {
namespace NodeStore { namespace NodeStore {

View File

@@ -20,7 +20,7 @@
#ifndef RIPPLE_NODESTORE_DATABASEROTATINGIMP_H_INCLUDED #ifndef RIPPLE_NODESTORE_DATABASEROTATINGIMP_H_INCLUDED
#define RIPPLE_NODESTORE_DATABASEROTATINGIMP_H_INCLUDED #define RIPPLE_NODESTORE_DATABASEROTATINGIMP_H_INCLUDED
#include <xrpld/nodestore/DatabaseRotating.h> #include <xrpl/nodestore/DatabaseRotating.h>
#include <mutex> #include <mutex>

View File

@@ -20,7 +20,7 @@
#ifndef RIPPLE_NODESTORE_DECODEDBLOB_H_INCLUDED #ifndef RIPPLE_NODESTORE_DECODEDBLOB_H_INCLUDED
#define RIPPLE_NODESTORE_DECODEDBLOB_H_INCLUDED #define RIPPLE_NODESTORE_DECODEDBLOB_H_INCLUDED
#include <xrpld/nodestore/NodeObject.h> #include <xrpl/nodestore/NodeObject.h>
namespace ripple { namespace ripple {
namespace NodeStore { namespace NodeStore {

View File

@@ -20,9 +20,8 @@
#ifndef RIPPLE_NODESTORE_ENCODEDBLOB_H_INCLUDED #ifndef RIPPLE_NODESTORE_ENCODEDBLOB_H_INCLUDED
#define RIPPLE_NODESTORE_ENCODEDBLOB_H_INCLUDED #define RIPPLE_NODESTORE_ENCODEDBLOB_H_INCLUDED
#include <xrpld/nodestore/NodeObject.h>
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/nodestore/NodeObject.h>
#include <boost/align/align_up.hpp> #include <boost/align/align_up.hpp>

View File

@@ -20,7 +20,7 @@
#ifndef RIPPLE_NODESTORE_MANAGERIMP_H_INCLUDED #ifndef RIPPLE_NODESTORE_MANAGERIMP_H_INCLUDED
#define RIPPLE_NODESTORE_MANAGERIMP_H_INCLUDED #define RIPPLE_NODESTORE_MANAGERIMP_H_INCLUDED
#include <xrpld/nodestore/Manager.h> #include <xrpl/nodestore/Manager.h>
namespace ripple { namespace ripple {
@@ -39,7 +39,7 @@ public:
static void static void
missing_backend(); missing_backend();
ManagerImp() = default; ManagerImp();
~ManagerImp() = default; ~ManagerImp() = default;

View File

@@ -23,11 +23,10 @@
// Disable lz4 deprecation warning due to incompatibility with clang attributes // Disable lz4 deprecation warning due to incompatibility with clang attributes
#define LZ4_DISABLE_DEPRECATE_WARNINGS #define LZ4_DISABLE_DEPRECATE_WARNINGS
#include <xrpld/nodestore/NodeObject.h>
#include <xrpld/nodestore/detail/varint.h>
#include <xrpl/basics/contract.h> #include <xrpl/basics/contract.h>
#include <xrpl/basics/safe_cast.h> #include <xrpl/basics/safe_cast.h>
#include <xrpl/nodestore/NodeObject.h>
#include <xrpl/nodestore/detail/varint.h>
#include <xrpl/protocol/HashPrefix.h> #include <xrpl/protocol/HashPrefix.h>
#include <nudb/detail/field.hpp> #include <nudb/detail/field.hpp>

View File

@@ -55,7 +55,10 @@ std::size_t constexpr oversizeMetaDataCap = 5200;
/** The maximum number of entries per directory page */ /** The maximum number of entries per directory page */
std::size_t constexpr dirNodeMaxEntries = 32; std::size_t constexpr dirNodeMaxEntries = 32;
/** The maximum number of pages allowed in a directory */ /** The maximum number of pages allowed in a directory
Made obsolete by fixDirectoryLimit amendment.
*/
std::uint64_t constexpr dirNodeMaxPages = 262144; std::uint64_t constexpr dirNodeMaxPages = 262144;
/** The maximum number of items in an NFT page */ /** The maximum number of items in an NFT page */

View File

@@ -21,6 +21,7 @@
#define RIPPLE_PROTOCOL_PUBLICKEY_H_INCLUDED #define RIPPLE_PROTOCOL_PUBLICKEY_H_INCLUDED
#include <xrpl/basics/Slice.h> #include <xrpl/basics/Slice.h>
#include <xrpl/beast/net/IPEndpoint.h>
#include <xrpl/protocol/KeyType.h> #include <xrpl/protocol/KeyType.h>
#include <xrpl/protocol/STExchange.h> #include <xrpl/protocol/STExchange.h>
#include <xrpl/protocol/UintTypes.h> #include <xrpl/protocol/UintTypes.h>
@@ -264,6 +265,24 @@ calcNodeID(PublicKey const&);
AccountID AccountID
calcAccountID(PublicKey const& pk); calcAccountID(PublicKey const& pk);
inline std::string
getFingerprint(
beast::IP::Endpoint const& address,
std::optional<PublicKey> const& publicKey = std::nullopt,
std::optional<std::string> const& id = std::nullopt)
{
std::stringstream ss;
ss << "IP Address: " << address;
if (publicKey.has_value())
{
ss << ", Public Key: " << toBase58(TokenType::NodePublic, *publicKey);
}
if (id.has_value())
{
ss << ", Id: " << id.value();
}
return ss.str();
}
} // namespace ripple } // namespace ripple
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@@ -709,37 +709,6 @@ canAdd(STAmount const& amt1, STAmount const& amt2);
bool bool
canSubtract(STAmount const& amt1, STAmount const& amt2); canSubtract(STAmount const& amt1, STAmount const& amt2);
// Since `canonicalize` does not have access to a ledger, this is needed to put
// the low-level routine stAmountCanonicalize on an amendment switch. Only
// transactions need to use this switchover. Outside of a transaction it's safe
// to unconditionally use the new behavior.
bool
getSTAmountCanonicalizeSwitchover();
void
setSTAmountCanonicalizeSwitchover(bool v);
/** RAII class to set and restore the STAmount canonicalize switchover.
*/
class STAmountSO
{
public:
explicit STAmountSO(bool v) : saved_(getSTAmountCanonicalizeSwitchover())
{
setSTAmountCanonicalizeSwitchover(v);
}
~STAmountSO()
{
setSTAmountCanonicalizeSwitchover(saved_);
}
private:
bool saved_;
};
} // namespace ripple } // namespace ripple
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@@ -244,6 +244,9 @@ public:
getFieldPathSet(SField const& field) const; getFieldPathSet(SField const& field) const;
STVector256 const& STVector256 const&
getFieldV256(SField const& field) const; getFieldV256(SField const& field) const;
// If not found, returns an object constructed with the given field
STObject
getFieldObject(SField const& field) const;
STArray const& STArray const&
getFieldArray(SField const& field) const; getFieldArray(SField const& field) const;
STCurrency const& STCurrency const&
@@ -390,6 +393,8 @@ public:
setFieldV256(SField const& field, STVector256 const& v); setFieldV256(SField const& field, STVector256 const& v);
void void
setFieldArray(SField const& field, STArray const& v); setFieldArray(SField const& field, STArray const& v);
void
setFieldObject(SField const& field, STObject const& v);
template <class Tag> template <class Tag>
void void

View File

@@ -87,8 +87,14 @@ public:
getFullText() const override; getFullText() const override;
// Outer transaction functions / signature functions. // Outer transaction functions / signature functions.
static Blob
getSignature(STObject const& sigObject);
Blob Blob
getSignature() const; getSignature() const
{
return getSignature(*this);
}
uint256 uint256
getSigningHash() const; getSigningHash() const;
@@ -119,13 +125,20 @@ public:
getJson(JsonOptions options, bool binary) const; getJson(JsonOptions options, bool binary) const;
void void
sign(PublicKey const& publicKey, SecretKey const& secretKey); sign(
PublicKey const& publicKey,
SecretKey const& secretKey,
std::optional<std::reference_wrapper<SField const>> signatureTarget =
{});
/** Check the signature.
@return `true` if valid signature. If invalid, the error message string.
*/
enum class RequireFullyCanonicalSig : bool { no, yes }; enum class RequireFullyCanonicalSig : bool { no, yes };
/** Check the signature.
@param requireCanonicalSig If `true`, check that the signature is fully
canonical. If `false`, only check that the signature is valid.
@param rules The current ledger rules.
@return `true` if valid signature. If invalid, the error message string.
*/
Expected<void, std::string> Expected<void, std::string>
checkSign(RequireFullyCanonicalSig requireCanonicalSig, Rules const& rules) checkSign(RequireFullyCanonicalSig requireCanonicalSig, Rules const& rules)
const; const;
@@ -150,17 +163,34 @@ public:
char status, char status,
std::string const& escapedMetaData) const; std::string const& escapedMetaData) const;
std::vector<uint256> std::vector<uint256> const&
getBatchTransactionIDs() const; getBatchTransactionIDs() const;
private: private:
/** Check the signature.
@param requireCanonicalSig If `true`, check that the signature is fully
canonical. If `false`, only check that the signature is valid.
@param rules The current ledger rules.
@param sigObject Reference to object that contains the signature fields.
Will be *this more often than not.
@return `true` if valid signature. If invalid, the error message string.
*/
Expected<void, std::string> Expected<void, std::string>
checkSingleSign(RequireFullyCanonicalSig requireCanonicalSig) const; checkSign(
RequireFullyCanonicalSig requireCanonicalSig,
Rules const& rules,
STObject const& sigObject) const;
Expected<void, std::string>
checkSingleSign(
RequireFullyCanonicalSig requireCanonicalSig,
STObject const& sigObject) const;
Expected<void, std::string> Expected<void, std::string>
checkMultiSign( checkMultiSign(
RequireFullyCanonicalSig requireCanonicalSig, RequireFullyCanonicalSig requireCanonicalSig,
Rules const& rules) const; Rules const& rules,
STObject const& sigObject) const;
Expected<void, std::string> Expected<void, std::string>
checkBatchSingleSign( checkBatchSingleSign(
@@ -179,7 +209,7 @@ private:
move(std::size_t n, void* buf) override; move(std::size_t n, void* buf) override;
friend class detail::STVar; friend class detail::STVar;
mutable std::vector<uint256> batch_txn_ids_; mutable std::vector<uint256> batchTxnIds_;
}; };
bool bool

View File

@@ -73,14 +73,8 @@ static constexpr std::uint32_t XRP_LEDGER_EARLIEST_SEQ{32570u};
* used in asserts and tests. */ * used in asserts and tests. */
static constexpr std::uint32_t XRP_LEDGER_EARLIEST_FEES{562177u}; static constexpr std::uint32_t XRP_LEDGER_EARLIEST_FEES{562177u};
/** The minimum amount of support an amendment should have. /** The minimum amount of support an amendment should have. */
constexpr std::ratio<80, 100> amendmentMajorityCalcThreshold;
@note This value is used by legacy code and will become obsolete
once the fixAmendmentMajorityCalc amendment activates.
*/
constexpr std::ratio<204, 256> preFixAmendmentMajorityCalcThreshold;
constexpr std::ratio<80, 100> postFixAmendmentMajorityCalcThreshold;
/** The minimum amount of time an amendment must hold a majority */ /** The minimum amount of time an amendment must hold a majority */
constexpr std::chrono::seconds const defaultAmendmentMajorityTime = weeks{2}; constexpr std::chrono::seconds const defaultAmendmentMajorityTime = weeks{2};

View File

@@ -225,8 +225,9 @@ enum TERcodes : TERUnderlyingType {
terQUEUED, // Transaction is being held in TxQ until fee drops terQUEUED, // Transaction is being held in TxQ until fee drops
terPRE_TICKET, // Ticket is not yet in ledger but might be on its way terPRE_TICKET, // Ticket is not yet in ledger but might be on its way
terNO_AMM, // AMM doesn't exist for the asset pair terNO_AMM, // AMM doesn't exist for the asset pair
terADDRESS_COLLISION, // Failed to allocate AccountID when trying to terADDRESS_COLLISION, // Failed to allocate AccountID when trying to
// create a pseudo-account // create a pseudo-account
terNO_DELEGATE_PERMISSION, // Delegate does not have permission
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -361,6 +362,9 @@ enum TECcodes : TERUnderlyingType {
tecLIMIT_EXCEEDED = 195, tecLIMIT_EXCEEDED = 195,
tecPSEUDO_ACCOUNT = 196, tecPSEUDO_ACCOUNT = 196,
tecPRECISION_LOSS = 197, tecPRECISION_LOSS = 197,
// DEPRECATED: This error code tecNO_DELEGATE_PERMISSION is reserved for
// backward compatibility with historical data on non-prod networks, can be
// reclaimed after those networks reset.
tecNO_DELEGATE_PERMISSION = 198, tecNO_DELEGATE_PERMISSION = 198,
}; };

View File

@@ -33,51 +33,35 @@ namespace ripple {
class TxMeta class TxMeta
{ {
private:
struct CtorHelper
{
explicit CtorHelper() = default;
};
template <class T>
TxMeta(
uint256 const& txID,
std::uint32_t ledger,
T const& data,
CtorHelper);
public: public:
TxMeta( TxMeta(uint256 const& transactionID, std::uint32_t ledger);
uint256 const& transactionID,
std::uint32_t ledger,
std::optional<uint256> parentBatchId = std::nullopt);
TxMeta(uint256 const& txID, std::uint32_t ledger, Blob const&); TxMeta(uint256 const& txID, std::uint32_t ledger, Blob const&);
TxMeta(uint256 const& txID, std::uint32_t ledger, std::string const&);
TxMeta(uint256 const& txID, std::uint32_t ledger, STObject const&); TxMeta(uint256 const& txID, std::uint32_t ledger, STObject const&);
uint256 const& uint256 const&
getTxID() const getTxID() const
{ {
return mTransactionID; return transactionID_;
} }
std::uint32_t std::uint32_t
getLgrSeq() const getLgrSeq() const
{ {
return mLedger; return ledgerSeq_;
} }
int int
getResult() const getResult() const
{ {
return mResult; return result_;
} }
TER TER
getResultTER() const getResultTER() const
{ {
return TER::fromInt(mResult); return TER::fromInt(result_);
} }
std::uint32_t std::uint32_t
getIndex() const getIndex() const
{ {
return mIndex; return index_;
} }
void void
@@ -104,66 +88,52 @@ public:
STArray& STArray&
getNodes() getNodes()
{ {
return (mNodes); return nodes_;
} }
STArray const& STArray const&
getNodes() const getNodes() const
{ {
return (mNodes); return nodes_;
} }
void void
setDeliveredAmount(STAmount const& delivered) setAdditionalFields(STObject const& obj)
{ {
mDelivered = delivered; if (obj.isFieldPresent(sfDeliveredAmount))
deliveredAmount_ = obj.getFieldAmount(sfDeliveredAmount);
if (obj.isFieldPresent(sfParentBatchID))
parentBatchID_ = obj.getFieldH256(sfParentBatchID);
} }
STAmount std::optional<STAmount> const&
getDeliveredAmount() const getDeliveredAmount() const
{ {
XRPL_ASSERT( return deliveredAmount_;
hasDeliveredAmount(),
"ripple::TxMeta::getDeliveredAmount : non-null delivered amount");
return *mDelivered;
}
bool
hasDeliveredAmount() const
{
return static_cast<bool>(mDelivered);
} }
void void
setParentBatchId(uint256 const& parentBatchId) setDeliveredAmount(std::optional<STAmount> const& amount)
{ {
mParentBatchId = parentBatchId; deliveredAmount_ = amount;
} }
uint256 void
getParentBatchId() const setParentBatchID(std::optional<uint256> const& id)
{ {
XRPL_ASSERT( parentBatchID_ = id;
hasParentBatchId(),
"ripple::TxMeta::getParentBatchId : non-null batch id");
return *mParentBatchId;
}
bool
hasParentBatchId() const
{
return static_cast<bool>(mParentBatchId);
} }
private: private:
uint256 mTransactionID; uint256 transactionID_;
std::uint32_t mLedger; std::uint32_t ledgerSeq_;
std::uint32_t mIndex; std::uint32_t index_;
int mResult; int result_;
std::optional<STAmount> mDelivered; std::optional<STAmount> deliveredAmount_;
std::optional<uint256> mParentBatchId; std::optional<uint256> parentBatchID_;
STArray mNodes; STArray nodes_;
}; };
} // namespace ripple } // namespace ripple

View File

@@ -29,15 +29,14 @@
// Add new amendments to the top of this list. // Add new amendments to the top of this list.
// Keep it sorted in reverse chronological order. // Keep it sorted in reverse chronological order.
// If you add an amendment here, then do not forget to increment `numFeatures`
// in include/xrpl/protocol/Feature.h.
XRPL_FEATURE(PermissionDelegationV1_1, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (DirectoryLimit, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (IncludeKeyletFields, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (IncludeKeyletFields, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(DynamicMPT, Supported::no, VoteBehavior::DefaultNo) XRPL_FEATURE(DynamicMPT, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (TokenEscrowV1, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (TokenEscrowV1, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (DelegateV1_1, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (PriceOracleOrder, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (PriceOracleOrder, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (MPTDeliveredAmount, Supported::no, VoteBehavior::DefaultNo) XRPL_FIX (MPTDeliveredAmount, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (AMMClawbackRounding, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (AMMClawbackRounding, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(TokenEscrow, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(TokenEscrow, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (EnforceNFTokenTrustlineV2, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (EnforceNFTokenTrustlineV2, Supported::yes, VoteBehavior::DefaultNo)
@@ -45,7 +44,6 @@ XRPL_FIX (AMMv1_3, Supported::yes, VoteBehavior::DefaultNo
XRPL_FEATURE(PermissionedDEX, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(PermissionedDEX, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(Batch, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(Batch, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(SingleAssetVault, Supported::no, VoteBehavior::DefaultNo) XRPL_FEATURE(SingleAssetVault, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(PermissionDelegation, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (PayChanCancelAfter, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (PayChanCancelAfter, Supported::yes, VoteBehavior::DefaultNo)
// Check flags in Credential transactions // Check flags in Credential transactions
XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultNo)
@@ -79,40 +77,25 @@ XRPL_FIX (DisallowIncomingV1, Supported::yes, VoteBehavior::DefaultNo
XRPL_FEATURE(XChainBridge, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(XChainBridge, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(AMM, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(AMM, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(Clawback, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(Clawback, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (ReducedOffersV1, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (NFTokenRemint, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (NFTokenRemint, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (NonFungibleTokensV1_2, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (NonFungibleTokensV1_2, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (UniversalNumber, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (UniversalNumber, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(XRPFees, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(XRPFees, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(DisallowIncoming, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(DisallowIncoming, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(ImmediateOfferKilled, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (RemoveNFTokenAutoTrustLine, Supported::yes, VoteBehavior::DefaultYes) XRPL_FIX (RemoveNFTokenAutoTrustLine, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (TrustLinesToSelf, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (TrustLinesToSelf, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(NonFungibleTokensV1_1, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(NonFungibleTokensV1_1, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(ExpandedSignerList, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(ExpandedSignerList, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(CheckCashMakesTrustLine, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(CheckCashMakesTrustLine, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (RmSmallIncreasedQOffers, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (STAmountCanonicalize, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(FlowSortStrands, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(FlowSortStrands, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(TicketBatch, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(TicketBatch, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(NegativeUNL, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(NegativeUNL, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (AmendmentMajorityCalc, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(HardenedValidations, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(HardenedValidations, Supported::yes, VoteBehavior::DefaultYes)
// fix1781: XRPEndpointSteps should be included in the circular payment check
XRPL_FIX (1781, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(RequireFullyCanonicalSig, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(RequireFullyCanonicalSig, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (QualityUpperBound, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(DeletableAccounts, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(DeletableAccounts, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (PayChanRecipientOwnerDir, Supported::yes, VoteBehavior::DefaultYes) XRPL_FIX (PayChanRecipientOwnerDir, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (CheckThreading, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (MasterKeyAsRegularKey, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (TakerDryOfferRemoval, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(MultiSignReserve, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(MultiSignReserve, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (1578, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(DepositPreauth, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(DepositPreauth, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (1623, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (1543, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (1571, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(Checks, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(Checks, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(DepositAuth, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(DepositAuth, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(Flow, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(Flow, Supported::yes, VoteBehavior::DefaultYes)
@@ -135,23 +118,39 @@ XRPL_FEATURE(CryptoConditionsSuite, Supported::yes, VoteBehavior::Obsolete)
// The following amendments have been active for at least two years. Their // The following amendments have been active for at least two years. Their
// pre-amendment code has been removed and the identifiers are deprecated. // pre-amendment code has been removed and the identifiers are deprecated.
// All known amendments and amendments that may appear in a validated // All known amendments and amendments that may appear in a validated ledger
// ledger must be registered either here or above with the "active" amendments // must be registered either here or above with the "active" amendments
XRPL_RETIRE(MultiSign) //
XRPL_RETIRE(TrustSetAuth) // Please keep this list sorted alphabetically for convenience.
XRPL_RETIRE(FeeEscalation)
XRPL_RETIRE(PayChan)
XRPL_RETIRE(CryptoConditions)
XRPL_RETIRE(TickSize)
XRPL_RETIRE(fix1368)
XRPL_RETIRE(Escrow)
XRPL_RETIRE(fix1373)
XRPL_RETIRE(EnforceInvariants)
XRPL_RETIRE(SortedDirectories)
XRPL_RETIRE(fix1201) XRPL_RETIRE(fix1201)
XRPL_RETIRE(fix1368)
XRPL_RETIRE(fix1373)
XRPL_RETIRE(fix1512) XRPL_RETIRE(fix1512)
XRPL_RETIRE(fix1523)
XRPL_RETIRE(fix1528)
XRPL_RETIRE(FlowCross)
XRPL_RETIRE(fix1513) XRPL_RETIRE(fix1513)
XRPL_RETIRE(fix1515) XRPL_RETIRE(fix1515)
XRPL_RETIRE(fix1523)
XRPL_RETIRE(fix1528)
XRPL_RETIRE(fix1543)
XRPL_RETIRE(fix1571)
XRPL_RETIRE(fix1578)
XRPL_RETIRE(fix1623)
XRPL_RETIRE(fix1781)
XRPL_RETIRE(fixAmendmentMajorityCalc)
XRPL_RETIRE(fixCheckThreading)
XRPL_RETIRE(fixMasterKeyAsRegularKey)
XRPL_RETIRE(fixQualityUpperBound)
XRPL_RETIRE(fixReducedOffersV1)
XRPL_RETIRE(fixRmSmallIncreasedQOffers)
XRPL_RETIRE(fixSTAmountCanonicalize)
XRPL_RETIRE(fixTakerDryOfferRemoval)
XRPL_RETIRE(CryptoConditions)
XRPL_RETIRE(Escrow)
XRPL_RETIRE(EnforceInvariants)
XRPL_RETIRE(FeeEscalation)
XRPL_RETIRE(FlowCross)
XRPL_RETIRE(ImmediateOfferKilled)
XRPL_RETIRE(MultiSign)
XRPL_RETIRE(PayChan)
XRPL_RETIRE(SortedDirectories)
XRPL_RETIRE(TickSize)
XRPL_RETIRE(TrustSetAuth)

View File

@@ -457,7 +457,7 @@ LEDGER_ENTRY(ltCREDENTIAL, 0x0081, Credential, credential, ({
{sfExpiration, soeOPTIONAL}, {sfExpiration, soeOPTIONAL},
{sfURI, soeOPTIONAL}, {sfURI, soeOPTIONAL},
{sfIssuerNode, soeREQUIRED}, {sfIssuerNode, soeREQUIRED},
{sfSubjectNode, soeREQUIRED}, {sfSubjectNode, soeOPTIONAL},
{sfPreviousTxnID, soeREQUIRED}, {sfPreviousTxnID, soeREQUIRED},
{sfPreviousTxnLgrSeq, soeREQUIRED}, {sfPreviousTxnLgrSeq, soeREQUIRED},
})) }))

View File

@@ -316,7 +316,7 @@ TRANSACTION(ttTRUST_SET, 20, TrustSet,
#endif #endif
TRANSACTION(ttACCOUNT_DELETE, 21, AccountDelete, TRANSACTION(ttACCOUNT_DELETE, 21, AccountDelete,
Delegation::notDelegatable, Delegation::notDelegatable,
uint256{}, featureDeletableAccounts,
mustDeleteAcct, mustDeleteAcct,
({ ({
{sfDestination, soeREQUIRED}, {sfDestination, soeREQUIRED},
@@ -837,7 +837,7 @@ TRANSACTION(ttPERMISSIONED_DOMAIN_DELETE, 63, PermissionedDomainDelete,
#endif #endif
TRANSACTION(ttDELEGATE_SET, 64, DelegateSet, TRANSACTION(ttDELEGATE_SET, 64, DelegateSet,
Delegation::notDelegatable, Delegation::notDelegatable,
featurePermissionDelegation, featurePermissionDelegationV1_1,
noPriv, noPriv,
({ ({
{sfAuthorize, soeREQUIRED}, {sfAuthorize, soeREQUIRED},

View File

@@ -569,6 +569,7 @@ JSS(settle_delay); // out: AccountChannels
JSS(severity); // in: LogLevel JSS(severity); // in: LogLevel
JSS(shares); // out: VaultInfo JSS(shares); // out: VaultInfo
JSS(signature); // out: NetworkOPs, ChannelAuthorize JSS(signature); // out: NetworkOPs, ChannelAuthorize
JSS(signature_target); // in: TransactionSign
JSS(signature_verified); // out: ChannelVerify JSS(signature_verified); // out: ChannelVerify
JSS(signing_key); // out: NetworkOPs JSS(signing_key); // out: NetworkOPs
JSS(signing_keys); // out: ValidatorList JSS(signing_keys); // out: ValidatorList

View File

@@ -21,6 +21,7 @@
#define RIPPLE_RESOURCE_CONSUMER_H_INCLUDED #define RIPPLE_RESOURCE_CONSUMER_H_INCLUDED
#include <xrpl/basics/Log.h> #include <xrpl/basics/Log.h>
#include <xrpl/protocol/PublicKey.h>
#include <xrpl/resource/Charge.h> #include <xrpl/resource/Charge.h>
#include <xrpl/resource/Disposition.h> #include <xrpl/resource/Disposition.h>
@@ -87,6 +88,9 @@ public:
Entry& Entry&
entry(); entry();
void
setPublicKey(PublicKey const& publicKey);
private: private:
Logic* m_logic; Logic* m_logic;
Entry* m_entry; Entry* m_entry;

View File

@@ -53,7 +53,7 @@ struct Entry : public beast::List<Entry>::Node
std::string std::string
to_string() const to_string() const
{ {
return key->address.to_string(); return getFingerprint(key->address, publicKey);
} }
/** /**
@@ -82,6 +82,9 @@ struct Entry : public beast::List<Entry>::Node
return local_balance.add(charge, now) + remote_balance; return local_balance.add(charge, now) + remote_balance;
} }
// The public key of the peer
std::optional<PublicKey> publicKey;
// Back pointer to the map key (bit of a hack here) // Back pointer to the map key (bit of a hack here)
Key const* key; Key const* key;

View File

@@ -20,11 +20,10 @@
#ifndef RIPPLE_SHAMAP_FAMILY_H_INCLUDED #ifndef RIPPLE_SHAMAP_FAMILY_H_INCLUDED
#define RIPPLE_SHAMAP_FAMILY_H_INCLUDED #define RIPPLE_SHAMAP_FAMILY_H_INCLUDED
#include <xrpld/nodestore/Database.h>
#include <xrpld/shamap/FullBelowCache.h>
#include <xrpld/shamap/TreeNodeCache.h>
#include <xrpl/beast/utility/Journal.h> #include <xrpl/beast/utility/Journal.h>
#include <xrpl/nodestore/Database.h>
#include <xrpl/shamap/FullBelowCache.h>
#include <xrpl/shamap/TreeNodeCache.h>
#include <cstdint> #include <cstdint>

View File

@@ -20,21 +20,19 @@
#ifndef RIPPLE_SHAMAP_SHAMAP_H_INCLUDED #ifndef RIPPLE_SHAMAP_SHAMAP_H_INCLUDED
#define RIPPLE_SHAMAP_SHAMAP_H_INCLUDED #define RIPPLE_SHAMAP_SHAMAP_H_INCLUDED
#include <xrpld/nodestore/Database.h>
#include <xrpld/nodestore/NodeObject.h>
#include <xrpld/shamap/Family.h>
#include <xrpld/shamap/SHAMapAddNode.h>
#include <xrpld/shamap/SHAMapInnerNode.h>
#include <xrpld/shamap/SHAMapItem.h>
#include <xrpld/shamap/SHAMapLeafNode.h>
#include <xrpld/shamap/SHAMapMissingNode.h>
#include <xrpld/shamap/SHAMapTreeNode.h>
#include <xrpld/shamap/TreeNodeCache.h>
#include <xrpl/basics/IntrusivePointer.h> #include <xrpl/basics/IntrusivePointer.h>
#include <xrpl/basics/UnorderedContainers.h> #include <xrpl/basics/UnorderedContainers.h>
#include <xrpl/beast/utility/Journal.h> #include <xrpl/beast/utility/Journal.h>
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/nodestore/Database.h>
#include <xrpl/nodestore/NodeObject.h>
#include <xrpl/shamap/Family.h>
#include <xrpl/shamap/SHAMapAddNode.h>
#include <xrpl/shamap/SHAMapInnerNode.h>
#include <xrpl/shamap/SHAMapItem.h>
#include <xrpl/shamap/SHAMapLeafNode.h>
#include <xrpl/shamap/SHAMapMissingNode.h>
#include <xrpl/shamap/SHAMapTreeNode.h>
#include <set> #include <set>
#include <stack> #include <stack>

View File

@@ -20,12 +20,11 @@
#ifndef RIPPLE_SHAMAP_SHAMAPACCOUNTSTATELEAFNODE_H_INCLUDED #ifndef RIPPLE_SHAMAP_SHAMAPACCOUNTSTATELEAFNODE_H_INCLUDED
#define RIPPLE_SHAMAP_SHAMAPACCOUNTSTATELEAFNODE_H_INCLUDED #define RIPPLE_SHAMAP_SHAMAPACCOUNTSTATELEAFNODE_H_INCLUDED
#include <xrpld/shamap/SHAMapItem.h>
#include <xrpld/shamap/SHAMapLeafNode.h>
#include <xrpl/basics/CountedObject.h> #include <xrpl/basics/CountedObject.h>
#include <xrpl/protocol/HashPrefix.h> #include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/digest.h> #include <xrpl/protocol/digest.h>
#include <xrpl/shamap/SHAMapItem.h>
#include <xrpl/shamap/SHAMapLeafNode.h>
namespace ripple { namespace ripple {

View File

@@ -20,10 +20,9 @@
#ifndef RIPPLE_SHAMAP_SHAMAPINNERNODE_H_INCLUDED #ifndef RIPPLE_SHAMAP_SHAMAPINNERNODE_H_INCLUDED
#define RIPPLE_SHAMAP_SHAMAPINNERNODE_H_INCLUDED #define RIPPLE_SHAMAP_SHAMAPINNERNODE_H_INCLUDED
#include <xrpld/shamap/SHAMapNodeID.h>
#include <xrpld/shamap/detail/TaggedPointer.h>
#include <xrpl/basics/IntrusivePointer.h> #include <xrpl/basics/IntrusivePointer.h>
#include <xrpl/shamap/SHAMapNodeID.h>
#include <xrpl/shamap/detail/TaggedPointer.h>
#include <atomic> #include <atomic>
#include <cstdint> #include <cstdint>

View File

@@ -20,8 +20,8 @@
#ifndef RIPPLE_SHAMAP_SHAMAPLEAFNODE_H_INCLUDED #ifndef RIPPLE_SHAMAP_SHAMAPLEAFNODE_H_INCLUDED
#define RIPPLE_SHAMAP_SHAMAPLEAFNODE_H_INCLUDED #define RIPPLE_SHAMAP_SHAMAPLEAFNODE_H_INCLUDED
#include <xrpld/shamap/SHAMapItem.h> #include <xrpl/shamap/SHAMapItem.h>
#include <xrpld/shamap/SHAMapTreeNode.h> #include <xrpl/shamap/SHAMapTreeNode.h>
#include <cstdint> #include <cstdint>

View File

@@ -20,9 +20,8 @@
#ifndef RIPPLE_SHAMAP_SHAMAPMISSINGNODE_H_INCLUDED #ifndef RIPPLE_SHAMAP_SHAMAPMISSINGNODE_H_INCLUDED
#define RIPPLE_SHAMAP_SHAMAPMISSINGNODE_H_INCLUDED #define RIPPLE_SHAMAP_SHAMAPMISSINGNODE_H_INCLUDED
#include <xrpld/shamap/SHAMapTreeNode.h>
#include <xrpl/basics/base_uint.h> #include <xrpl/basics/base_uint.h>
#include <xrpl/shamap/SHAMapTreeNode.h>
#include <iosfwd> #include <iosfwd>
#include <stdexcept> #include <stdexcept>

View File

@@ -20,7 +20,7 @@
#ifndef RIPPLE_SHAMAP_SHAMAPSYNCFILTER_H_INCLUDED #ifndef RIPPLE_SHAMAP_SHAMAPSYNCFILTER_H_INCLUDED
#define RIPPLE_SHAMAP_SHAMAPSYNCFILTER_H_INCLUDED #define RIPPLE_SHAMAP_SHAMAPSYNCFILTER_H_INCLUDED
#include <xrpld/shamap/SHAMapTreeNode.h> #include <xrpl/shamap/SHAMapTreeNode.h>
#include <optional> #include <optional>

View File

@@ -20,13 +20,12 @@
#ifndef RIPPLE_SHAMAP_SHAMAPTREENODE_H_INCLUDED #ifndef RIPPLE_SHAMAP_SHAMAPTREENODE_H_INCLUDED
#define RIPPLE_SHAMAP_SHAMAPTREENODE_H_INCLUDED #define RIPPLE_SHAMAP_SHAMAPTREENODE_H_INCLUDED
#include <xrpld/shamap/SHAMapItem.h>
#include <xrpld/shamap/SHAMapNodeID.h>
#include <xrpl/basics/IntrusivePointer.h> #include <xrpl/basics/IntrusivePointer.h>
#include <xrpl/basics/IntrusiveRefCounts.h> #include <xrpl/basics/IntrusiveRefCounts.h>
#include <xrpl/basics/SHAMapHash.h> #include <xrpl/basics/SHAMapHash.h>
#include <xrpl/protocol/Serializer.h> #include <xrpl/protocol/Serializer.h>
#include <xrpl/shamap/SHAMapItem.h>
#include <xrpl/shamap/SHAMapNodeID.h>
#include <cstdint> #include <cstdint>
#include <string> #include <string>

View File

@@ -20,12 +20,11 @@
#ifndef RIPPLE_SHAMAP_SHAMAPTXLEAFNODE_H_INCLUDED #ifndef RIPPLE_SHAMAP_SHAMAPTXLEAFNODE_H_INCLUDED
#define RIPPLE_SHAMAP_SHAMAPTXLEAFNODE_H_INCLUDED #define RIPPLE_SHAMAP_SHAMAPTXLEAFNODE_H_INCLUDED
#include <xrpld/shamap/SHAMapItem.h>
#include <xrpld/shamap/SHAMapLeafNode.h>
#include <xrpl/basics/CountedObject.h> #include <xrpl/basics/CountedObject.h>
#include <xrpl/protocol/HashPrefix.h> #include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/digest.h> #include <xrpl/protocol/digest.h>
#include <xrpl/shamap/SHAMapItem.h>
#include <xrpl/shamap/SHAMapLeafNode.h>
namespace ripple { namespace ripple {

View File

@@ -20,12 +20,11 @@
#ifndef RIPPLE_SHAMAP_SHAMAPLEAFTXPLUSMETANODE_H_INCLUDED #ifndef RIPPLE_SHAMAP_SHAMAPLEAFTXPLUSMETANODE_H_INCLUDED
#define RIPPLE_SHAMAP_SHAMAPLEAFTXPLUSMETANODE_H_INCLUDED #define RIPPLE_SHAMAP_SHAMAPLEAFTXPLUSMETANODE_H_INCLUDED
#include <xrpld/shamap/SHAMapItem.h>
#include <xrpld/shamap/SHAMapLeafNode.h>
#include <xrpl/basics/CountedObject.h> #include <xrpl/basics/CountedObject.h>
#include <xrpl/protocol/HashPrefix.h> #include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/digest.h> #include <xrpl/protocol/digest.h>
#include <xrpl/shamap/SHAMapItem.h>
#include <xrpl/shamap/SHAMapLeafNode.h>
namespace ripple { namespace ripple {

View File

@@ -20,10 +20,9 @@
#ifndef RIPPLE_SHAMAP_TREENODECACHE_H_INCLUDED #ifndef RIPPLE_SHAMAP_TREENODECACHE_H_INCLUDED
#define RIPPLE_SHAMAP_TREENODECACHE_H_INCLUDED #define RIPPLE_SHAMAP_TREENODECACHE_H_INCLUDED
#include <xrpld/shamap/SHAMapTreeNode.h>
#include <xrpl/basics/IntrusivePointer.h> #include <xrpl/basics/IntrusivePointer.h>
#include <xrpl/basics/TaggedCache.h> #include <xrpl/basics/TaggedCache.h>
#include <xrpl/shamap/SHAMapTreeNode.h>
namespace ripple { namespace ripple {

View File

@@ -20,9 +20,8 @@
#ifndef RIPPLE_SHAMAP_TAGGEDPOINTER_H_INCLUDED #ifndef RIPPLE_SHAMAP_TAGGEDPOINTER_H_INCLUDED
#define RIPPLE_SHAMAP_TAGGEDPOINTER_H_INCLUDED #define RIPPLE_SHAMAP_TAGGEDPOINTER_H_INCLUDED
#include <xrpld/shamap/SHAMapTreeNode.h>
#include <xrpl/basics/IntrusivePointer.h> #include <xrpl/basics/IntrusivePointer.h>
#include <xrpl/shamap/SHAMapTreeNode.h>
#include <array> #include <array>
#include <cstdint> #include <cstdint>

View File

@@ -17,10 +17,9 @@
*/ */
//============================================================================== //==============================================================================
#include <xrpld/shamap/SHAMapInnerNode.h>
#include <xrpld/shamap/detail/TaggedPointer.h>
#include <xrpl/basics/ByteUtilities.h> #include <xrpl/basics/ByteUtilities.h>
#include <xrpl/shamap/SHAMapInnerNode.h>
#include <xrpl/shamap/detail/TaggedPointer.h>
#include <boost/pool/pool_alloc.hpp> #include <boost/pool/pool_alloc.hpp>

View File

@@ -126,10 +126,10 @@ ApplyStateTable::apply(
std::optional<TxMeta> metadata; std::optional<TxMeta> metadata;
if (!to.open() || isDryRun) if (!to.open() || isDryRun)
{ {
TxMeta meta(tx.getTransactionID(), to.seq(), parentBatchId); TxMeta meta(tx.getTransactionID(), to.seq());
if (deliver) meta.setDeliveredAmount(deliver);
meta.setDeliveredAmount(*deliver); meta.setParentBatchID(parentBatchId);
Mods newMod; Mods newMod;
for (auto& item : items_) for (auto& item : items_)
@@ -682,12 +682,6 @@ ApplyStateTable::threadOwners(
if (auto const optSleAcct{(*sle)[~sfAccount]}) if (auto const optSleAcct{(*sle)[~sfAccount]})
threadTx(base, meta, *optSleAcct, mods, j); threadTx(base, meta, *optSleAcct, mods, j);
// Don't thread a check's sfDestination unless the amendment is
// enabled
if (ledgerType == ltCHECK &&
!base.rules().enabled(fixCheckThreading))
break;
// If sfDestination is present, thread to that account // If sfDestination is present, thread to that account
if (auto const optSleDest{(*sle)[~sfDestination]}) if (auto const optSleDest{(*sle)[~sfDestination]})
threadTx(base, meta, *optSleDest, mods, j); threadTx(base, meta, *optSleDest, mods, j);

View File

@@ -22,6 +22,9 @@
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/protocol/Protocol.h> #include <xrpl/protocol/Protocol.h>
#include <limits>
#include <type_traits>
namespace ripple { namespace ripple {
std::optional<std::uint64_t> std::optional<std::uint64_t>
@@ -91,8 +94,21 @@ ApplyView::dirAdd(
return page; return page;
} }
// We rely on modulo arithmetic of unsigned integers (guaranteed in
// [basic.fundamental] paragraph 2) to detect page representation overflow.
// For signed integers this would be UB, hence static_assert here.
static_assert(std::is_unsigned_v<decltype(page)>);
// Defensive check against breaking changes in compiler.
static_assert([]<typename T>(std::type_identity<T>) constexpr -> T {
T tmp = std::numeric_limits<T>::max();
return ++tmp;
}(std::type_identity<decltype(page)>{}) == 0);
++page;
// Check whether we're out of pages. // Check whether we're out of pages.
if (++page >= dirNodeMaxPages) if (page == 0)
return std::nullopt;
if (!rules().enabled(fixDirectoryLimit) &&
page >= dirNodeMaxPages) // Old pages limit
return std::nullopt; return std::nullopt;
// We are about to create a new node; we'll link it to // We are about to create a new node; we'll link it to

View File

@@ -17,7 +17,7 @@
*/ */
//============================================================================== //==============================================================================
#include <xrpld/nodestore/detail/BatchWriter.h> #include <xrpl/nodestore/detail/BatchWriter.h>
namespace ripple { namespace ripple {
namespace NodeStore { namespace NodeStore {

View File

@@ -17,11 +17,10 @@
*/ */
//============================================================================== //==============================================================================
#include <xrpld/nodestore/Database.h>
#include <xrpl/basics/chrono.h> #include <xrpl/basics/chrono.h>
#include <xrpl/beast/core/CurrentThreadName.h> #include <xrpl/beast/core/CurrentThreadName.h>
#include <xrpl/json/json_value.h> #include <xrpl/json/json_value.h>
#include <xrpl/nodestore/Database.h>
#include <xrpl/protocol/HashPrefix.h> #include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/jss.h> #include <xrpl/protocol/jss.h>

View File

@@ -17,7 +17,7 @@
*/ */
//============================================================================== //==============================================================================
#include <xrpld/nodestore/detail/DatabaseNodeImp.h> #include <xrpl/nodestore/detail/DatabaseNodeImp.h>
namespace ripple { namespace ripple {
namespace NodeStore { namespace NodeStore {

View File

@@ -17,7 +17,7 @@
*/ */
//============================================================================== //==============================================================================
#include <xrpld/nodestore/detail/DatabaseRotatingImp.h> #include <xrpl/nodestore/detail/DatabaseRotatingImp.h>
namespace ripple { namespace ripple {
namespace NodeStore { namespace NodeStore {

View File

@@ -17,10 +17,9 @@
*/ */
//============================================================================== //==============================================================================
#include <xrpld/nodestore/detail/DecodedBlob.h>
#include <xrpl/basics/safe_cast.h> #include <xrpl/basics/safe_cast.h>
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/nodestore/detail/DecodedBlob.h>
#include <algorithm> #include <algorithm>

View File

@@ -17,7 +17,7 @@
*/ */
//============================================================================== //==============================================================================
#include <xrpld/nodestore/DummyScheduler.h> #include <xrpl/nodestore/DummyScheduler.h>
namespace ripple { namespace ripple {
namespace NodeStore { namespace NodeStore {

View File

@@ -17,8 +17,8 @@
*/ */
//============================================================================== //==============================================================================
#include <xrpld/nodestore/detail/DatabaseNodeImp.h> #include <xrpl/nodestore/detail/DatabaseNodeImp.h>
#include <xrpld/nodestore/detail/ManagerImp.h> #include <xrpl/nodestore/detail/ManagerImp.h>
#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/predicate.hpp>
@@ -41,6 +41,27 @@ ManagerImp::missing_backend()
"please see the rippled-example.cfg file!"); "please see the rippled-example.cfg file!");
} }
// We shouldn't rely on global variables for lifetime management because their
// lifetime is not well-defined. ManagerImp may get destroyed before the Factory
// classes, and then, calling Manager::instance().erase() in the destructors of
// the Factory classes is an undefined behaviour.
void
registerNuDBFactory(Manager& manager);
void
registerRocksDBFactory(Manager& manager);
void
registerNullFactory(Manager& manager);
void
registerMemoryFactory(Manager& manager);
ManagerImp::ManagerImp()
{
registerNuDBFactory(*this);
registerRocksDBFactory(*this);
registerNullFactory(*this);
registerMemoryFactory(*this);
}
std::unique_ptr<Backend> std::unique_ptr<Backend>
ManagerImp::make_Backend( ManagerImp::make_Backend(
Section const& parameters, Section const& parameters,

View File

@@ -17,7 +17,7 @@
*/ */
//============================================================================== //==============================================================================
#include <xrpld/nodestore/NodeObject.h> #include <xrpl/nodestore/NodeObject.h>
#include <memory> #include <memory>

View File

@@ -17,10 +17,9 @@
*/ */
//============================================================================== //==============================================================================
#include <xrpld/nodestore/Factory.h>
#include <xrpld/nodestore/Manager.h>
#include <xrpl/basics/contract.h> #include <xrpl/basics/contract.h>
#include <xrpl/nodestore/Factory.h>
#include <xrpl/nodestore/Manager.h>
#include <boost/beast/core/string.hpp> #include <boost/beast/core/string.hpp>
#include <boost/core/ignore_unused.hpp> #include <boost/core/ignore_unused.hpp>
@@ -46,10 +45,10 @@ class MemoryFactory : public Factory
private: private:
std::mutex mutex_; std::mutex mutex_;
std::map<std::string, MemoryDB, boost::beast::iless> map_; std::map<std::string, MemoryDB, boost::beast::iless> map_;
Manager& manager_;
public: public:
MemoryFactory(); explicit MemoryFactory(Manager& manager);
~MemoryFactory() override;
std::string std::string
getName() const override; getName() const override;
@@ -75,7 +74,14 @@ public:
} }
}; };
static MemoryFactory memoryFactory; MemoryFactory* memoryFactory = nullptr;
void
registerMemoryFactory(Manager& manager)
{
static MemoryFactory instance{manager};
memoryFactory = &instance;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -112,9 +118,9 @@ public:
} }
void void
open(bool createIfMissing) override open(bool) override
{ {
db_ = &memoryFactory.open(name_); db_ = &memoryFactory->open(name_);
} }
bool bool
@@ -219,14 +225,9 @@ public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
MemoryFactory::MemoryFactory() MemoryFactory::MemoryFactory(Manager& manager) : manager_(manager)
{ {
Manager::instance().insert(*this); manager_.insert(*this);
}
MemoryFactory::~MemoryFactory()
{
Manager::instance().erase(*this);
} }
std::string std::string

View File

@@ -17,15 +17,14 @@
*/ */
//============================================================================== //==============================================================================
#include <xrpld/nodestore/Factory.h>
#include <xrpld/nodestore/Manager.h>
#include <xrpld/nodestore/detail/DecodedBlob.h>
#include <xrpld/nodestore/detail/EncodedBlob.h>
#include <xrpld/nodestore/detail/codec.h>
#include <xrpl/basics/contract.h> #include <xrpl/basics/contract.h>
#include <xrpl/beast/core/LexicalCast.h> #include <xrpl/beast/core/LexicalCast.h>
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/nodestore/Factory.h>
#include <xrpl/nodestore/Manager.h>
#include <xrpl/nodestore/detail/DecodedBlob.h>
#include <xrpl/nodestore/detail/EncodedBlob.h>
#include <xrpl/nodestore/detail/codec.h>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
@@ -427,15 +426,13 @@ private:
class NuDBFactory : public Factory class NuDBFactory : public Factory
{ {
public: private:
NuDBFactory() Manager& manager_;
{
Manager::instance().insert(*this);
}
~NuDBFactory() override public:
explicit NuDBFactory(Manager& manager) : manager_(manager)
{ {
Manager::instance().erase(*this); manager_.insert(*this);
} }
std::string std::string
@@ -470,7 +467,11 @@ public:
} }
}; };
static NuDBFactory nuDBFactory; void
registerNuDBFactory(Manager& manager)
{
static NuDBFactory instance{manager};
}
} // namespace NodeStore } // namespace NodeStore
} // namespace ripple } // namespace ripple

View File

@@ -17,8 +17,8 @@
*/ */
//============================================================================== //==============================================================================
#include <xrpld/nodestore/Factory.h> #include <xrpl/nodestore/Factory.h>
#include <xrpld/nodestore/Manager.h> #include <xrpl/nodestore/Manager.h>
#include <memory> #include <memory>
@@ -111,15 +111,13 @@ private:
class NullFactory : public Factory class NullFactory : public Factory
{ {
public: private:
NullFactory() Manager& manager_;
{
Manager::instance().insert(*this);
}
~NullFactory() override public:
explicit NullFactory(Manager& manager) : manager_(manager)
{ {
Manager::instance().erase(*this); manager_.insert(*this);
} }
std::string std::string
@@ -140,7 +138,11 @@ public:
} }
}; };
static NullFactory nullFactory; void
registerNullFactory(Manager& manager)
{
static NullFactory instance{manager};
}
} // namespace NodeStore } // namespace NodeStore
} // namespace ripple } // namespace ripple

View File

@@ -17,20 +17,18 @@
*/ */
//============================================================================== //==============================================================================
#include <xrpld/unity/rocksdb.h> #include <xrpl/basics/rocksdb.h>
#if RIPPLE_ROCKSDB_AVAILABLE #if RIPPLE_ROCKSDB_AVAILABLE
#include <xrpld/core/Config.h> // VFALCO Bad dependency
#include <xrpld/nodestore/Factory.h>
#include <xrpld/nodestore/Manager.h>
#include <xrpld/nodestore/detail/BatchWriter.h>
#include <xrpld/nodestore/detail/DecodedBlob.h>
#include <xrpld/nodestore/detail/EncodedBlob.h>
#include <xrpl/basics/ByteUtilities.h> #include <xrpl/basics/ByteUtilities.h>
#include <xrpl/basics/contract.h> #include <xrpl/basics/contract.h>
#include <xrpl/basics/safe_cast.h> #include <xrpl/basics/safe_cast.h>
#include <xrpl/beast/core/CurrentThreadName.h> #include <xrpl/beast/core/CurrentThreadName.h>
#include <xrpl/nodestore/Factory.h>
#include <xrpl/nodestore/Manager.h>
#include <xrpl/nodestore/detail/BatchWriter.h>
#include <xrpl/nodestore/detail/DecodedBlob.h>
#include <xrpl/nodestore/detail/EncodedBlob.h>
#include <atomic> #include <atomic>
#include <memory> #include <memory>
@@ -461,17 +459,15 @@ public:
class RocksDBFactory : public Factory class RocksDBFactory : public Factory
{ {
private:
Manager& manager_;
public: public:
RocksDBEnv m_env; RocksDBEnv m_env;
RocksDBFactory() RocksDBFactory(Manager& manager) : manager_(manager)
{ {
Manager::instance().insert(*this); manager_.insert(*this);
}
~RocksDBFactory() override
{
Manager::instance().erase(*this);
} }
std::string std::string
@@ -493,7 +489,11 @@ public:
} }
}; };
static RocksDBFactory rocksDBFactory; void
registerRocksDBFactory(Manager& manager)
{
static RocksDBFactory instance{manager};
}
} // namespace NodeStore } // namespace NodeStore
} // namespace ripple } // namespace ripple

View File

@@ -174,21 +174,22 @@ Permission::isDelegatable(
auto const txType = permissionToTxType(permissionValue); auto const txType = permissionToTxType(permissionValue);
auto const it = delegatableTx_.find(txType); auto const it = delegatableTx_.find(txType);
if (rules.enabled(fixDelegateV1_1)) if (it == delegatableTx_.end())
{ return false;
if (it == delegatableTx_.end())
return false;
auto const feature = getTxFeature(txType); auto const txFeaturesIt = txFeatureMap_.find(txType);
XRPL_ASSERT(
txFeaturesIt != txFeatureMap_.end(),
"ripple::Permissions::isDelegatable : tx exists in txFeatureMap_");
// fixDelegateV1_1: Delegation is only allowed if the required amendment // Delegation is only allowed if the required amendment for the transaction
// for the transaction is enabled. For transactions that do not require // is enabled. For transactions that do not require an amendment, delegation
// an amendment, delegation is always allowed. // is always allowed.
if (feature && !rules.enabled(*feature)) if (txFeaturesIt->second != uint256{} &&
return false; !rules.enabled(txFeaturesIt->second))
} return false;
if (it != delegatableTx_.end() && it->second == Delegation::notDelegatable) if (it->second == Delegation::notDelegatable)
return false; return false;
return true; return true;

View File

@@ -68,29 +68,6 @@
namespace ripple { namespace ripple {
namespace {
// Use a static inside a function to help prevent order-of-initialzation issues
LocalValue<bool>&
getStaticSTAmountCanonicalizeSwitchover()
{
static LocalValue<bool> r{true};
return r;
}
} // namespace
bool
getSTAmountCanonicalizeSwitchover()
{
return *getStaticSTAmountCanonicalizeSwitchover();
}
void
setSTAmountCanonicalizeSwitchover(bool v)
{
*getStaticSTAmountCanonicalizeSwitchover() = v;
}
static std::uint64_t const tenTo14 = 100000000000000ull; static std::uint64_t const tenTo14 = 100000000000000ull;
static std::uint64_t const tenTo14m1 = tenTo14 - 1; static std::uint64_t const tenTo14m1 = tenTo14 - 1;
static std::uint64_t const tenTo17 = tenTo14 * 1000; static std::uint64_t const tenTo17 = tenTo14 * 1000;
@@ -884,18 +861,14 @@ STAmount::canonicalize()
return; return;
} }
if (getSTAmountCanonicalizeSwitchover()) // log(cMaxNativeN, 10) == 17
{ if (native() && mOffset > 17)
// log(cMaxNativeN, 10) == 17 Throw<std::runtime_error>("Native currency amount out of range");
if (native() && mOffset > 17) // log(maxMPTokenAmount, 10) ~ 18.96
Throw<std::runtime_error>( if (mAsset.holds<MPTIssue>() && mOffset > 18)
"Native currency amount out of range"); Throw<std::runtime_error>("MPT amount out of range");
// log(maxMPTokenAmount, 10) ~ 18.96
if (mAsset.holds<MPTIssue>() && mOffset > 18)
Throw<std::runtime_error>("MPT amount out of range");
}
if (getSTNumberSwitchover() && getSTAmountCanonicalizeSwitchover()) if (getSTNumberSwitchover())
{ {
Number num( Number num(
mIsNegative ? -mValue : mValue, mOffset, Number::unchecked{}); mIsNegative ? -mValue : mValue, mOffset, Number::unchecked{});
@@ -919,16 +892,14 @@ STAmount::canonicalize()
while (mOffset > 0) while (mOffset > 0)
{ {
if (getSTAmountCanonicalizeSwitchover()) // N.B. do not move the overflow check to after the
{ // multiplication
// N.B. do not move the overflow check to after the if (native() && mValue > cMaxNativeN)
// multiplication Throw<std::runtime_error>(
if (native() && mValue > cMaxNativeN) "Native currency amount out of range");
Throw<std::runtime_error>( else if (!native() && mValue > maxMPTokenAmount)
"Native currency amount out of range"); Throw<std::runtime_error>("MPT amount out of range");
else if (!native() && mValue > maxMPTokenAmount)
Throw<std::runtime_error>("MPT amount out of range");
}
mValue *= 10; mValue *= 10;
--mOffset; --mOffset;
} }

View File

@@ -688,6 +688,16 @@ STObject::getFieldV256(SField const& field) const
return getFieldByConstRef<STVector256>(field, empty); return getFieldByConstRef<STVector256>(field, empty);
} }
STObject
STObject::getFieldObject(SField const& field) const
{
STObject const empty{field};
auto ret = getFieldByConstRef<STObject>(field, empty);
if (ret != empty)
ret.applyTemplateFromSField(field);
return ret;
}
STArray const& STArray const&
STObject::getFieldArray(SField const& field) const STObject::getFieldArray(SField const& field) const
{ {
@@ -833,6 +843,12 @@ STObject::setFieldArray(SField const& field, STArray const& v)
setFieldUsingAssignment(field, v); setFieldUsingAssignment(field, v);
} }
void
STObject::setFieldObject(SField const& field, STObject const& v)
{
setFieldUsingAssignment(field, v);
}
Json::Value Json::Value
STObject::getJson(JsonOptions options) const STObject::getJson(JsonOptions options) const
{ {

View File

@@ -200,11 +200,11 @@ STTx::getSigningHash() const
} }
Blob Blob
STTx::getSignature() const STTx::getSignature(STObject const& sigObject)
{ {
try try
{ {
return getFieldVL(sfTxnSignature); return sigObject.getFieldVL(sfTxnSignature);
} }
catch (std::exception const&) catch (std::exception const&)
{ {
@@ -234,35 +234,68 @@ STTx::getSeqValue() const
} }
void void
STTx::sign(PublicKey const& publicKey, SecretKey const& secretKey) STTx::sign(
PublicKey const& publicKey,
SecretKey const& secretKey,
std::optional<std::reference_wrapper<SField const>> signatureTarget)
{ {
auto const data = getSigningData(*this); auto const data = getSigningData(*this);
auto const sig = ripple::sign(publicKey, secretKey, makeSlice(data)); auto const sig = ripple::sign(publicKey, secretKey, makeSlice(data));
setFieldVL(sfTxnSignature, sig); if (signatureTarget)
{
auto& target = peekFieldObject(*signatureTarget);
target.setFieldVL(sfTxnSignature, sig);
}
else
{
setFieldVL(sfTxnSignature, sig);
}
tid_ = getHash(HashPrefix::transactionID); tid_ = getHash(HashPrefix::transactionID);
} }
Expected<void, std::string>
STTx::checkSign(
RequireFullyCanonicalSig requireCanonicalSig,
Rules const& rules,
STObject const& sigObject) const
{
try
{
// Determine whether we're single- or multi-signing by looking
// at the SigningPubKey. If it's empty we must be
// multi-signing. Otherwise we're single-signing.
Blob const& signingPubKey = sigObject.getFieldVL(sfSigningPubKey);
return signingPubKey.empty()
? checkMultiSign(requireCanonicalSig, rules, sigObject)
: checkSingleSign(requireCanonicalSig, sigObject);
}
catch (std::exception const&)
{
}
return Unexpected("Internal signature check failure.");
}
Expected<void, std::string> Expected<void, std::string>
STTx::checkSign( STTx::checkSign(
RequireFullyCanonicalSig requireCanonicalSig, RequireFullyCanonicalSig requireCanonicalSig,
Rules const& rules) const Rules const& rules) const
{ {
try if (auto const ret = checkSign(requireCanonicalSig, rules, *this); !ret)
return ret;
/* Placeholder for field that will be added by Lending Protocol
if (isFieldPresent(sfCounterpartySignature))
{ {
// Determine whether we're single- or multi-signing by looking auto const counterSig = getFieldObject(sfCounterpartySignature);
// at the SigningPubKey. If it's empty we must be if (auto const ret = checkSign(requireCanonicalSig, rules, counterSig);
// multi-signing. Otherwise we're single-signing. !ret)
Blob const& signingPubKey = getFieldVL(sfSigningPubKey); return Unexpected("Counterparty: " + ret.error());
return signingPubKey.empty()
? checkMultiSign(requireCanonicalSig, rules)
: checkSingleSign(requireCanonicalSig);
} }
catch (std::exception const&) */
{ return {};
}
return Unexpected("Internal signature check failure.");
} }
Expected<void, std::string> Expected<void, std::string>
@@ -382,23 +415,23 @@ STTx::getMetaSQL(
static Expected<void, std::string> static Expected<void, std::string>
singleSignHelper( singleSignHelper(
STObject const& signer, STObject const& sigObject,
Slice const& data, Slice const& data,
bool const fullyCanonical) bool const fullyCanonical)
{ {
// We don't allow both a non-empty sfSigningPubKey and an sfSigners. // We don't allow both a non-empty sfSigningPubKey and an sfSigners.
// That would allow the transaction to be signed two ways. So if both // That would allow the transaction to be signed two ways. So if both
// fields are present the signature is invalid. // fields are present the signature is invalid.
if (signer.isFieldPresent(sfSigners)) if (sigObject.isFieldPresent(sfSigners))
return Unexpected("Cannot both single- and multi-sign."); return Unexpected("Cannot both single- and multi-sign.");
bool validSig = false; bool validSig = false;
try try
{ {
auto const spk = signer.getFieldVL(sfSigningPubKey); auto const spk = sigObject.getFieldVL(sfSigningPubKey);
if (publicKeyType(makeSlice(spk))) if (publicKeyType(makeSlice(spk)))
{ {
Blob const signature = signer.getFieldVL(sfTxnSignature); Blob const signature = sigObject.getFieldVL(sfTxnSignature);
validSig = verify( validSig = verify(
PublicKey(makeSlice(spk)), PublicKey(makeSlice(spk)),
data, data,
@@ -418,12 +451,14 @@ singleSignHelper(
} }
Expected<void, std::string> Expected<void, std::string>
STTx::checkSingleSign(RequireFullyCanonicalSig requireCanonicalSig) const STTx::checkSingleSign(
RequireFullyCanonicalSig requireCanonicalSig,
STObject const& sigObject) const
{ {
auto const data = getSigningData(*this); auto const data = getSigningData(*this);
bool const fullyCanonical = (getFlags() & tfFullyCanonicalSig) || bool const fullyCanonical = (getFlags() & tfFullyCanonicalSig) ||
(requireCanonicalSig == STTx::RequireFullyCanonicalSig::yes); (requireCanonicalSig == STTx::RequireFullyCanonicalSig::yes);
return singleSignHelper(*this, makeSlice(data), fullyCanonical); return singleSignHelper(sigObject, makeSlice(data), fullyCanonical);
} }
Expected<void, std::string> Expected<void, std::string>
@@ -440,31 +475,29 @@ STTx::checkBatchSingleSign(
Expected<void, std::string> Expected<void, std::string>
multiSignHelper( multiSignHelper(
STObject const& signerObj, STObject const& sigObject,
std::optional<AccountID> txnAccountID,
bool const fullyCanonical, bool const fullyCanonical,
std::function<Serializer(AccountID const&)> makeMsg, std::function<Serializer(AccountID const&)> makeMsg,
Rules const& rules) Rules const& rules)
{ {
// Make sure the MultiSigners are present. Otherwise they are not // Make sure the MultiSigners are present. Otherwise they are not
// attempting multi-signing and we just have a bad SigningPubKey. // attempting multi-signing and we just have a bad SigningPubKey.
if (!signerObj.isFieldPresent(sfSigners)) if (!sigObject.isFieldPresent(sfSigners))
return Unexpected("Empty SigningPubKey."); return Unexpected("Empty SigningPubKey.");
// We don't allow both an sfSigners and an sfTxnSignature. Both fields // We don't allow both an sfSigners and an sfTxnSignature. Both fields
// being present would indicate that the transaction is signed both ways. // being present would indicate that the transaction is signed both ways.
if (signerObj.isFieldPresent(sfTxnSignature)) if (sigObject.isFieldPresent(sfTxnSignature))
return Unexpected("Cannot both single- and multi-sign."); return Unexpected("Cannot both single- and multi-sign.");
STArray const& signers{signerObj.getFieldArray(sfSigners)}; STArray const& signers{sigObject.getFieldArray(sfSigners)};
// There are well known bounds that the number of signers must be within. // There are well known bounds that the number of signers must be within.
if (signers.size() < STTx::minMultiSigners || if (signers.size() < STTx::minMultiSigners ||
signers.size() > STTx::maxMultiSigners(&rules)) signers.size() > STTx::maxMultiSigners(&rules))
return Unexpected("Invalid Signers array size."); return Unexpected("Invalid Signers array size.");
// We also use the sfAccount field inside the loop. Get it once.
auto const txnAccountID = signerObj.getAccountID(sfAccount);
// Signers must be in sorted order by AccountID. // Signers must be in sorted order by AccountID.
AccountID lastAccountID(beast::zero); AccountID lastAccountID(beast::zero);
@@ -472,8 +505,10 @@ multiSignHelper(
{ {
auto const accountID = signer.getAccountID(sfAccount); auto const accountID = signer.getAccountID(sfAccount);
// The account owner may not multisign for themselves. // The account owner may not usually multisign for themselves.
if (accountID == txnAccountID) // If they can, txnAccountID will be unseated, which is not equal to any
// value.
if (txnAccountID == accountID)
return Unexpected("Invalid multisigner."); return Unexpected("Invalid multisigner.");
// No duplicate signers allowed. // No duplicate signers allowed.
@@ -489,6 +524,7 @@ multiSignHelper(
// Verify the signature. // Verify the signature.
bool validSig = false; bool validSig = false;
std::optional<std::string> errorWhat;
try try
{ {
auto spk = signer.getFieldVL(sfSigningPubKey); auto spk = signer.getFieldVL(sfSigningPubKey);
@@ -502,15 +538,16 @@ multiSignHelper(
fullyCanonical); fullyCanonical);
} }
} }
catch (std::exception const&) catch (std::exception const& e)
{ {
// We assume any problem lies with the signature. // We assume any problem lies with the signature.
validSig = false; validSig = false;
errorWhat = e.what();
} }
if (!validSig) if (!validSig)
return Unexpected( return Unexpected(
std::string("Invalid signature on account ") + std::string("Invalid signature on account ") +
toBase58(accountID) + "."); toBase58(accountID) + errorWhat.value_or("") + ".");
} }
// All signatures verified. // All signatures verified.
return {}; return {};
@@ -532,8 +569,9 @@ STTx::checkBatchMultiSign(
serializeBatch(dataStart, getFlags(), getBatchTransactionIDs()); serializeBatch(dataStart, getFlags(), getBatchTransactionIDs());
return multiSignHelper( return multiSignHelper(
batchSigner, batchSigner,
std::nullopt,
fullyCanonical, fullyCanonical,
[&dataStart](AccountID const& accountID) mutable -> Serializer { [&dataStart](AccountID const& accountID) -> Serializer {
Serializer s = dataStart; Serializer s = dataStart;
finishMultiSigningData(accountID, s); finishMultiSigningData(accountID, s);
return s; return s;
@@ -544,19 +582,27 @@ STTx::checkBatchMultiSign(
Expected<void, std::string> Expected<void, std::string>
STTx::checkMultiSign( STTx::checkMultiSign(
RequireFullyCanonicalSig requireCanonicalSig, RequireFullyCanonicalSig requireCanonicalSig,
Rules const& rules) const Rules const& rules,
STObject const& sigObject) const
{ {
bool const fullyCanonical = (getFlags() & tfFullyCanonicalSig) || bool const fullyCanonical = (getFlags() & tfFullyCanonicalSig) ||
(requireCanonicalSig == RequireFullyCanonicalSig::yes); (requireCanonicalSig == RequireFullyCanonicalSig::yes);
// Used inside the loop in multiSignHelper to enforce that
// the account owner may not multisign for themselves.
auto const txnAccountID = &sigObject != this
? std::nullopt
: std::optional<AccountID>(getAccountID(sfAccount));
// We can ease the computational load inside the loop a bit by // We can ease the computational load inside the loop a bit by
// pre-constructing part of the data that we hash. Fill a Serializer // pre-constructing part of the data that we hash. Fill a Serializer
// with the stuff that stays constant from signature to signature. // with the stuff that stays constant from signature to signature.
Serializer dataStart = startMultiSigningData(*this); Serializer dataStart = startMultiSigningData(*this);
return multiSignHelper( return multiSignHelper(
*this, sigObject,
txnAccountID,
fullyCanonical, fullyCanonical,
[&dataStart](AccountID const& accountID) mutable -> Serializer { [&dataStart](AccountID const& accountID) -> Serializer {
Serializer s = dataStart; Serializer s = dataStart;
finishMultiSigningData(accountID, s); finishMultiSigningData(accountID, s);
return s; return s;
@@ -569,7 +615,7 @@ STTx::checkMultiSign(
* *
* This function returns a vector of transaction IDs by extracting them from * This function returns a vector of transaction IDs by extracting them from
* the field array `sfRawTransactions` within the STTx. If the batch * the field array `sfRawTransactions` within the STTx. If the batch
* transaction IDs have already been computed and cached in `batch_txn_ids_`, * transaction IDs have already been computed and cached in `batchTxnIds_`,
* it returns the cached vector. Otherwise, it computes the transaction IDs, * it returns the cached vector. Otherwise, it computes the transaction IDs,
* caches them, and then returns the vector. * caches them, and then returns the vector.
* *
@@ -579,7 +625,7 @@ STTx::checkMultiSign(
* empty and that the size of the computed batch transaction IDs matches the * empty and that the size of the computed batch transaction IDs matches the
* size of the `sfRawTransactions` field array. * size of the `sfRawTransactions` field array.
*/ */
std::vector<uint256> std::vector<uint256> const&
STTx::getBatchTransactionIDs() const STTx::getBatchTransactionIDs() const
{ {
XRPL_ASSERT( XRPL_ASSERT(
@@ -588,16 +634,20 @@ STTx::getBatchTransactionIDs() const
XRPL_ASSERT( XRPL_ASSERT(
getFieldArray(sfRawTransactions).size() != 0, getFieldArray(sfRawTransactions).size() != 0,
"STTx::getBatchTransactionIDs : empty raw transactions"); "STTx::getBatchTransactionIDs : empty raw transactions");
if (batch_txn_ids_.size() != 0)
return batch_txn_ids_;
for (STObject const& rb : getFieldArray(sfRawTransactions)) // The list of inner ids is built once, then reused on subsequent calls.
batch_txn_ids_.push_back(rb.getHash(HashPrefix::transactionID)); // After the list is built, it must always have the same size as the array
// `sfRawTransactions`. The assert below verifies that.
if (batchTxnIds_.size() == 0)
{
for (STObject const& rb : getFieldArray(sfRawTransactions))
batchTxnIds_.push_back(rb.getHash(HashPrefix::transactionID));
}
XRPL_ASSERT( XRPL_ASSERT(
batch_txn_ids_.size() == getFieldArray(sfRawTransactions).size(), batchTxnIds_.size() == getFieldArray(sfRawTransactions).size(),
"STTx::getBatchTransactionIDs : batch transaction IDs size mismatch"); "STTx::getBatchTransactionIDs : batch transaction IDs size mismatch");
return batch_txn_ids_; return batchTxnIds_;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@@ -127,7 +127,6 @@ transResults()
MAKE_ERROR(tecLIMIT_EXCEEDED, "Limit exceeded."), MAKE_ERROR(tecLIMIT_EXCEEDED, "Limit exceeded."),
MAKE_ERROR(tecPSEUDO_ACCOUNT, "This operation is not allowed against a pseudo-account."), MAKE_ERROR(tecPSEUDO_ACCOUNT, "This operation is not allowed against a pseudo-account."),
MAKE_ERROR(tecPRECISION_LOSS, "The amounts used by the transaction cannot interact."), MAKE_ERROR(tecPRECISION_LOSS, "The amounts used by the transaction cannot interact."),
MAKE_ERROR(tecNO_DELEGATE_PERMISSION, "Delegated account lacks permission to perform this transaction."),
MAKE_ERROR(tefALREADY, "The exact transaction was already in this ledger."), MAKE_ERROR(tefALREADY, "The exact transaction was already in this ledger."),
MAKE_ERROR(tefBAD_ADD_AUTH, "Not authorized to add account."), MAKE_ERROR(tefBAD_ADD_AUTH, "Not authorized to add account."),
@@ -235,6 +234,7 @@ transResults()
MAKE_ERROR(terPRE_TICKET, "Ticket is not yet in ledger."), MAKE_ERROR(terPRE_TICKET, "Ticket is not yet in ledger."),
MAKE_ERROR(terNO_AMM, "AMM doesn't exist for the asset pair."), MAKE_ERROR(terNO_AMM, "AMM doesn't exist for the asset pair."),
MAKE_ERROR(terADDRESS_COLLISION, "Failed to allocate an unique account address."), MAKE_ERROR(terADDRESS_COLLISION, "Failed to allocate an unique account address."),
MAKE_ERROR(terNO_DELEGATE_PERMISSION, "Delegated account lacks permission to perform this transaction."),
MAKE_ERROR(tesSUCCESS, "The transaction was applied. Only final in a validated ledger."), MAKE_ERROR(tesSUCCESS, "The transaction was applied. Only final in a validated ledger."),
}; };

View File

@@ -39,35 +39,13 @@
namespace ripple { namespace ripple {
template <class T>
TxMeta::TxMeta(
uint256 const& txid,
std::uint32_t ledger,
T const& data,
CtorHelper)
: mTransactionID(txid), mLedger(ledger), mNodes(sfAffectedNodes, 32)
{
SerialIter sit(makeSlice(data));
STObject obj(sit, sfMetadata);
mResult = obj.getFieldU8(sfTransactionResult);
mIndex = obj.getFieldU32(sfTransactionIndex);
mNodes = *dynamic_cast<STArray*>(&obj.getField(sfAffectedNodes));
if (obj.isFieldPresent(sfDeliveredAmount))
setDeliveredAmount(obj.getFieldAmount(sfDeliveredAmount));
if (obj.isFieldPresent(sfParentBatchID))
setParentBatchId(obj.getFieldH256(sfParentBatchID));
}
TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj) TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj)
: mTransactionID(txid) : transactionID_(txid)
, mLedger(ledger) , ledgerSeq_(ledger)
, mNodes(obj.getFieldArray(sfAffectedNodes)) , nodes_(obj.getFieldArray(sfAffectedNodes))
{ {
mResult = obj.getFieldU8(sfTransactionResult); result_ = obj.getFieldU8(sfTransactionResult);
mIndex = obj.getFieldU32(sfTransactionIndex); index_ = obj.getFieldU32(sfTransactionIndex);
auto affectedNodes = auto affectedNodes =
dynamic_cast<STArray const*>(obj.peekAtPField(sfAffectedNodes)); dynamic_cast<STArray const*>(obj.peekAtPField(sfAffectedNodes));
@@ -75,40 +53,32 @@ TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj)
affectedNodes, affectedNodes,
"ripple::TxMeta::TxMeta(STObject) : type cast succeeded"); "ripple::TxMeta::TxMeta(STObject) : type cast succeeded");
if (affectedNodes) if (affectedNodes)
mNodes = *affectedNodes; nodes_ = *affectedNodes;
if (obj.isFieldPresent(sfDeliveredAmount)) setAdditionalFields(obj);
setDeliveredAmount(obj.getFieldAmount(sfDeliveredAmount));
if (obj.isFieldPresent(sfParentBatchID))
setParentBatchId(obj.getFieldH256(sfParentBatchID));
} }
TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, Blob const& vec) TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, Blob const& vec)
: TxMeta(txid, ledger, vec, CtorHelper()) : transactionID_(txid), ledgerSeq_(ledger), nodes_(sfAffectedNodes, 32)
{ {
SerialIter sit(makeSlice(vec));
STObject obj(sit, sfMetadata);
result_ = obj.getFieldU8(sfTransactionResult);
index_ = obj.getFieldU32(sfTransactionIndex);
nodes_ = obj.getFieldArray(sfAffectedNodes);
setAdditionalFields(obj);
} }
TxMeta::TxMeta( TxMeta::TxMeta(uint256 const& transactionID, std::uint32_t ledger)
uint256 const& txid, : transactionID_(transactionID)
std::uint32_t ledger, , ledgerSeq_(ledger)
std::string const& data) , index_(std::numeric_limits<std::uint32_t>::max())
: TxMeta(txid, ledger, data, CtorHelper()) , result_(255)
, nodes_(sfAffectedNodes)
{ {
} nodes_.reserve(32);
TxMeta::TxMeta(
uint256 const& transactionID,
std::uint32_t ledger,
std::optional<uint256> parentBatchId)
: mTransactionID(transactionID)
, mLedger(ledger)
, mIndex(static_cast<std::uint32_t>(-1))
, mResult(255)
, mParentBatchId(parentBatchId)
, mNodes(sfAffectedNodes)
{
mNodes.reserve(32);
} }
void void
@@ -118,7 +88,7 @@ TxMeta::setAffectedNode(
std::uint16_t nodeType) std::uint16_t nodeType)
{ {
// make sure the node exists and force its type // make sure the node exists and force its type
for (auto& n : mNodes) for (auto& n : nodes_)
{ {
if (n.getFieldH256(sfLedgerIndex) == node) if (n.getFieldH256(sfLedgerIndex) == node)
{ {
@@ -128,8 +98,8 @@ TxMeta::setAffectedNode(
} }
} }
mNodes.push_back(STObject(type)); nodes_.push_back(STObject(type));
STObject& obj = mNodes.back(); STObject& obj = nodes_.back();
XRPL_ASSERT( XRPL_ASSERT(
obj.getFName() == type, obj.getFName() == type,
@@ -146,14 +116,15 @@ TxMeta::getAffectedAccounts() const
// This code should match the behavior of the JS method: // This code should match the behavior of the JS method:
// Meta#getAffectedAccounts // Meta#getAffectedAccounts
for (auto const& it : mNodes) for (auto const& node : nodes_)
{ {
int index = it.getFieldIndex( int index = node.getFieldIndex(
(it.getFName() == sfCreatedNode) ? sfNewFields : sfFinalFields); (node.getFName() == sfCreatedNode) ? sfNewFields : sfFinalFields);
if (index != -1) if (index != -1)
{ {
auto inner = dynamic_cast<STObject const*>(&it.peekAtIndex(index)); auto const* inner =
dynamic_cast<STObject const*>(&node.peekAtIndex(index));
XRPL_ASSERT( XRPL_ASSERT(
inner, inner,
"ripple::getAffectedAccounts : STObject type cast succeeded"); "ripple::getAffectedAccounts : STObject type cast succeeded");
@@ -213,13 +184,13 @@ STObject&
TxMeta::getAffectedNode(SLE::ref node, SField const& type) TxMeta::getAffectedNode(SLE::ref node, SField const& type)
{ {
uint256 index = node->key(); uint256 index = node->key();
for (auto& n : mNodes) for (auto& n : nodes_)
{ {
if (n.getFieldH256(sfLedgerIndex) == index) if (n.getFieldH256(sfLedgerIndex) == index)
return n; return n;
} }
mNodes.push_back(STObject(type)); nodes_.push_back(STObject(type));
STObject& obj = mNodes.back(); STObject& obj = nodes_.back();
XRPL_ASSERT( XRPL_ASSERT(
obj.getFName() == type, obj.getFName() == type,
@@ -233,7 +204,7 @@ TxMeta::getAffectedNode(SLE::ref node, SField const& type)
STObject& STObject&
TxMeta::getAffectedNode(uint256 const& node) TxMeta::getAffectedNode(uint256 const& node)
{ {
for (auto& n : mNodes) for (auto& n : nodes_)
{ {
if (n.getFieldH256(sfLedgerIndex) == node) if (n.getFieldH256(sfLedgerIndex) == node)
return n; return n;
@@ -241,7 +212,7 @@ TxMeta::getAffectedNode(uint256 const& node)
// LCOV_EXCL_START // LCOV_EXCL_START
UNREACHABLE("ripple::TxMeta::getAffectedNode(uint256) : node not found"); UNREACHABLE("ripple::TxMeta::getAffectedNode(uint256) : node not found");
Throw<std::runtime_error>("Affected node not found"); Throw<std::runtime_error>("Affected node not found");
return *(mNodes.begin()); // Silence compiler warning. return *(nodes_.begin()); // Silence compiler warning.
// LCOV_EXCL_STOP // LCOV_EXCL_STOP
} }
@@ -249,15 +220,15 @@ STObject
TxMeta::getAsObject() const TxMeta::getAsObject() const
{ {
STObject metaData(sfTransactionMetaData); STObject metaData(sfTransactionMetaData);
XRPL_ASSERT(mResult != 255, "ripple::TxMeta::getAsObject : result is set"); XRPL_ASSERT(result_ != 255, "ripple::TxMeta::getAsObject : result_ is set");
metaData.setFieldU8(sfTransactionResult, mResult); metaData.setFieldU8(sfTransactionResult, result_);
metaData.setFieldU32(sfTransactionIndex, mIndex); metaData.setFieldU32(sfTransactionIndex, index_);
metaData.emplace_back(mNodes); metaData.emplace_back(nodes_);
if (hasDeliveredAmount()) if (deliveredAmount_.has_value())
metaData.setFieldAmount(sfDeliveredAmount, getDeliveredAmount()); metaData.setFieldAmount(sfDeliveredAmount, *deliveredAmount_);
if (hasParentBatchId()) if (parentBatchID_.has_value())
metaData.setFieldH256(sfParentBatchID, getParentBatchId()); metaData.setFieldH256(sfParentBatchID, *parentBatchID_);
return metaData; return metaData;
} }
@@ -265,13 +236,13 @@ TxMeta::getAsObject() const
void void
TxMeta::addRaw(Serializer& s, TER result, std::uint32_t index) TxMeta::addRaw(Serializer& s, TER result, std::uint32_t index)
{ {
mResult = TERtoInt(result); result_ = TERtoInt(result);
mIndex = index; index_ = index;
XRPL_ASSERT( XRPL_ASSERT(
(mResult == 0) || ((mResult > 100) && (mResult <= 255)), (result_ == 0) || ((result_ > 100) && (result_ <= 255)),
"ripple::TxMeta::addRaw : valid TER input"); "ripple::TxMeta::addRaw : valid TER input");
mNodes.sort([](STObject const& o1, STObject const& o2) { nodes_.sort([](STObject const& o1, STObject const& o2) {
return o1.getFieldH256(sfLedgerIndex) < o2.getFieldH256(sfLedgerIndex); return o1.getFieldH256(sfLedgerIndex) < o2.getFieldH256(sfLedgerIndex);
}); });

View File

@@ -148,6 +148,12 @@ Consumer::entry()
return *m_entry; return *m_entry;
} }
void
Consumer::setPublicKey(PublicKey const& publicKey)
{
m_entry->publicKey = publicKey;
}
std::ostream& std::ostream&
operator<<(std::ostream& os, Consumer const& v) operator<<(std::ostream& os, Consumer const& v)
{ {

View File

@@ -17,15 +17,14 @@
*/ */
//============================================================================== //==============================================================================
#include <xrpld/shamap/SHAMap.h>
#include <xrpld/shamap/SHAMapAccountStateLeafNode.h>
#include <xrpld/shamap/SHAMapNodeID.h>
#include <xrpld/shamap/SHAMapSyncFilter.h>
#include <xrpld/shamap/SHAMapTxLeafNode.h>
#include <xrpld/shamap/SHAMapTxPlusMetaLeafNode.h>
#include <xrpl/basics/TaggedCache.ipp> #include <xrpl/basics/TaggedCache.ipp>
#include <xrpl/basics/contract.h> #include <xrpl/basics/contract.h>
#include <xrpl/shamap/SHAMap.h>
#include <xrpl/shamap/SHAMapAccountStateLeafNode.h>
#include <xrpl/shamap/SHAMapNodeID.h>
#include <xrpl/shamap/SHAMapSyncFilter.h>
#include <xrpl/shamap/SHAMapTxLeafNode.h>
#include <xrpl/shamap/SHAMapTxPlusMetaLeafNode.h>
namespace ripple { namespace ripple {

View File

@@ -17,10 +17,9 @@
*/ */
//============================================================================== //==============================================================================
#include <xrpld/shamap/SHAMap.h>
#include <xrpl/basics/IntrusivePointer.ipp> #include <xrpl/basics/IntrusivePointer.ipp>
#include <xrpl/basics/contract.h> #include <xrpl/basics/contract.h>
#include <xrpl/shamap/SHAMap.h>
#include <array> #include <array>
#include <stack> #include <stack>

View File

@@ -17,16 +17,15 @@
*/ */
//============================================================================== //==============================================================================
#include <xrpld/shamap/SHAMapInnerNode.h>
#include <xrpld/shamap/SHAMapTreeNode.h>
#include <xrpld/shamap/detail/TaggedPointer.ipp>
#include <xrpl/basics/IntrusivePointer.ipp> #include <xrpl/basics/IntrusivePointer.ipp>
#include <xrpl/basics/Slice.h> #include <xrpl/basics/Slice.h>
#include <xrpl/basics/contract.h> #include <xrpl/basics/contract.h>
#include <xrpl/basics/spinlock.h> #include <xrpl/basics/spinlock.h>
#include <xrpl/protocol/HashPrefix.h> #include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/digest.h> #include <xrpl/protocol/digest.h>
#include <xrpl/shamap/SHAMapInnerNode.h>
#include <xrpl/shamap/SHAMapTreeNode.h>
#include <xrpl/shamap/detail/TaggedPointer.ipp>
namespace ripple { namespace ripple {

View File

@@ -17,7 +17,7 @@
*/ */
//============================================================================== //==============================================================================
#include <xrpld/shamap/SHAMapLeafNode.h> #include <xrpl/shamap/SHAMapLeafNode.h>
namespace ripple { namespace ripple {

View File

@@ -17,12 +17,11 @@
*/ */
//============================================================================== //==============================================================================
#include <xrpld/shamap/SHAMap.h>
#include <xrpld/shamap/SHAMapNodeID.h>
#include <xrpl/beast/core/LexicalCast.h> #include <xrpl/beast/core/LexicalCast.h>
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/protocol/Serializer.h> #include <xrpl/protocol/Serializer.h>
#include <xrpl/shamap/SHAMap.h>
#include <xrpl/shamap/SHAMapNodeID.h>
namespace ripple { namespace ripple {

View File

@@ -17,10 +17,10 @@
*/ */
//============================================================================== //==============================================================================
#include <xrpld/shamap/SHAMap.h>
#include <xrpld/shamap/SHAMapSyncFilter.h>
#include <xrpl/basics/random.h> #include <xrpl/basics/random.h>
#include <xrpl/shamap/SHAMap.h>
#include <xrpl/shamap/SHAMapLeafNode.h>
#include <xrpl/shamap/SHAMapSyncFilter.h>
namespace ripple { namespace ripple {
@@ -591,16 +591,16 @@ SHAMap::addKnownNode(
} }
auto const generation = f_.getFullBelowCache()->getGeneration(); auto const generation = f_.getFullBelowCache()->getGeneration();
SHAMapNodeID iNodeID; SHAMapNodeID currNodeID;
auto iNode = root_.get(); auto currNode = root_.get();
while (iNode->isInner() && while (currNode->isInner() &&
!static_cast<SHAMapInnerNode*>(iNode)->isFullBelow(generation) && !static_cast<SHAMapInnerNode*>(currNode)->isFullBelow(generation) &&
(iNodeID.getDepth() < node.getDepth())) (currNodeID.getDepth() < node.getDepth()))
{ {
int branch = selectBranch(iNodeID, node.getNodeID()); int const branch = selectBranch(currNodeID, node.getNodeID());
XRPL_ASSERT(branch >= 0, "ripple::SHAMap::addKnownNode : valid branch"); XRPL_ASSERT(branch >= 0, "ripple::SHAMap::addKnownNode : valid branch");
auto inner = static_cast<SHAMapInnerNode*>(iNode); auto inner = static_cast<SHAMapInnerNode*>(currNode);
if (inner->isEmptyBranch(branch)) if (inner->isEmptyBranch(branch))
{ {
JLOG(journal_.warn()) << "Add known node for empty branch" << node; JLOG(journal_.warn()) << "Add known node for empty branch" << node;
@@ -614,58 +614,84 @@ SHAMap::addKnownNode(
} }
auto prevNode = inner; auto prevNode = inner;
std::tie(iNode, iNodeID) = descend(inner, iNodeID, branch, filter); std::tie(currNode, currNodeID) =
descend(inner, currNodeID, branch, filter);
if (iNode == nullptr) if (currNode != nullptr)
continue;
auto newNode = SHAMapTreeNode::makeFromWire(rawNode);
if (!newNode || childHash != newNode->getHash())
{ {
auto newNode = SHAMapTreeNode::makeFromWire(rawNode); JLOG(journal_.warn()) << "Corrupt node received";
return SHAMapAddNode::invalid();
}
if (!newNode || childHash != newNode->getHash()) // In rare cases, a node can still be corrupt even after hash
// validation. For leaf nodes, we perform an additional check to
// ensure the node's position in the tree is consistent with its
// content to prevent inconsistencies that could
// propagate further down the line.
if (newNode->isLeaf())
{
auto const& actualKey =
static_cast<SHAMapLeafNode const*>(newNode.get())
->peekItem()
->key();
// Validate that this leaf belongs at the target position
auto const expectedNodeID =
SHAMapNodeID::createID(node.getDepth(), actualKey);
if (expectedNodeID.getNodeID() != node.getNodeID())
{ {
JLOG(journal_.warn()) << "Corrupt node received"; JLOG(journal_.debug())
<< "Leaf node position mismatch: "
<< "expected=" << expectedNodeID.getNodeID()
<< ", actual=" << node.getNodeID();
return SHAMapAddNode::invalid(); return SHAMapAddNode::invalid();
} }
}
// Inner nodes must be at a level strictly less than 64 // Inner nodes must be at a level strictly less than 64
// but leaf nodes (while notionally at level 64) can be // but leaf nodes (while notionally at level 64) can be
// at any depth up to and including 64: // at any depth up to and including 64:
if ((iNodeID.getDepth() > leafDepth) || if ((currNodeID.getDepth() > leafDepth) ||
(newNode->isInner() && iNodeID.getDepth() == leafDepth)) (newNode->isInner() && currNodeID.getDepth() == leafDepth))
{ {
// Map is provably invalid // Map is provably invalid
state_ = SHAMapState::Invalid; state_ = SHAMapState::Invalid;
return SHAMapAddNode::useful();
}
if (iNodeID != node)
{
// Either this node is broken or we didn't request it (yet)
JLOG(journal_.warn()) << "unable to hook node " << node;
JLOG(journal_.info()) << " stuck at " << iNodeID;
JLOG(journal_.info()) << "got depth=" << node.getDepth()
<< ", walked to= " << iNodeID.getDepth();
return SHAMapAddNode::useful();
}
if (backed_)
canonicalize(childHash, newNode);
newNode = prevNode->canonicalizeChild(branch, std::move(newNode));
if (filter)
{
Serializer s;
newNode->serializeWithPrefix(s);
filter->gotNode(
false,
childHash,
ledgerSeq_,
std::move(s.modData()),
newNode->getType());
}
return SHAMapAddNode::useful(); return SHAMapAddNode::useful();
} }
if (currNodeID != node)
{
// Either this node is broken or we didn't request it (yet)
JLOG(journal_.warn()) << "unable to hook node " << node;
JLOG(journal_.info()) << " stuck at " << currNodeID;
JLOG(journal_.info()) << "got depth=" << node.getDepth()
<< ", walked to= " << currNodeID.getDepth();
return SHAMapAddNode::useful();
}
if (backed_)
canonicalize(childHash, newNode);
newNode = prevNode->canonicalizeChild(branch, std::move(newNode));
if (filter)
{
Serializer s;
newNode->serializeWithPrefix(s);
filter->gotNode(
false,
childHash,
ledgerSeq_,
std::move(s.modData()),
newNode->getType());
}
return SHAMapAddNode::useful();
} }
JLOG(journal_.trace()) << "got node, already had it (late)"; JLOG(journal_.trace()) << "got node, already had it (late)";

View File

@@ -17,18 +17,17 @@
*/ */
//============================================================================== //==============================================================================
#include <xrpld/shamap/SHAMapAccountStateLeafNode.h>
#include <xrpld/shamap/SHAMapInnerNode.h>
#include <xrpld/shamap/SHAMapTreeNode.h>
#include <xrpld/shamap/SHAMapTxLeafNode.h>
#include <xrpld/shamap/SHAMapTxPlusMetaLeafNode.h>
#include <xrpl/basics/IntrusivePointer.ipp> #include <xrpl/basics/IntrusivePointer.ipp>
#include <xrpl/basics/Slice.h> #include <xrpl/basics/Slice.h>
#include <xrpl/basics/contract.h> #include <xrpl/basics/contract.h>
#include <xrpl/basics/safe_cast.h> #include <xrpl/basics/safe_cast.h>
#include <xrpl/protocol/HashPrefix.h> #include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/digest.h> #include <xrpl/protocol/digest.h>
#include <xrpl/shamap/SHAMapAccountStateLeafNode.h>
#include <xrpl/shamap/SHAMapInnerNode.h>
#include <xrpl/shamap/SHAMapTreeNode.h>
#include <xrpl/shamap/SHAMapTxLeafNode.h>
#include <xrpl/shamap/SHAMapTxPlusMetaLeafNode.h>
namespace ripple { namespace ripple {

View File

@@ -198,109 +198,100 @@ private:
// Fill or Kill - unless we fully cross, just charge a fee and don't // Fill or Kill - unless we fully cross, just charge a fee and don't
// place the offer on the books. But also clean up expired offers // place the offer on the books. But also clean up expired offers
// that are discovered along the way. // that are discovered along the way.
// testAMM(
// fix1578 changes the return code. Verify expected behavior [&](AMM& ammAlice, Env& env) {
// without and with fix1578. // Order that can't be filled
for (auto const& tweakedFeatures : TER const killedCode{TER{tecKILLED}};
{features - fix1578, features | fix1578}) env(offer(carol, USD(100), XRP(100)),
{ txflags(tfFillOrKill),
testAMM( ter(killedCode));
[&](AMM& ammAlice, Env& env) { env.close();
// Order that can't be filled BEAST_EXPECT(ammAlice.expectBalances(
TER const killedCode{ XRP(10'100), USD(10'000), ammAlice.tokens()));
tweakedFeatures[fix1578] ? TER{tecKILLED} // fee = AMM
: TER{tesSUCCESS}}; BEAST_EXPECT(expectLedgerEntryRoot(
env(offer(carol, USD(100), XRP(100)), env, carol, XRP(30'000) - (txfee(env, 1))));
txflags(tfFillOrKill), BEAST_EXPECT(expectOffers(env, carol, 0));
ter(killedCode)); BEAST_EXPECT(expectHolding(env, carol, USD(30'000)));
env.close();
BEAST_EXPECT(ammAlice.expectBalances(
XRP(10'100), USD(10'000), ammAlice.tokens()));
// fee = AMM
BEAST_EXPECT(expectLedgerEntryRoot(
env, carol, XRP(30'000) - (txfee(env, 1))));
BEAST_EXPECT(expectOffers(env, carol, 0));
BEAST_EXPECT(expectHolding(env, carol, USD(30'000)));
// Order that can be filled // Order that can be filled
env(offer(carol, XRP(100), USD(100)), env(offer(carol, XRP(100), USD(100)),
txflags(tfFillOrKill), txflags(tfFillOrKill),
ter(tesSUCCESS)); ter(tesSUCCESS));
BEAST_EXPECT(ammAlice.expectBalances( BEAST_EXPECT(ammAlice.expectBalances(
XRP(10'000), USD(10'100), ammAlice.tokens())); XRP(10'000), USD(10'100), ammAlice.tokens()));
BEAST_EXPECT(expectLedgerEntryRoot( BEAST_EXPECT(expectLedgerEntryRoot(
env, carol, XRP(30'000) + XRP(100) - txfee(env, 2))); env, carol, XRP(30'000) + XRP(100) - txfee(env, 2)));
BEAST_EXPECT(expectHolding(env, carol, USD(29'900))); BEAST_EXPECT(expectHolding(env, carol, USD(29'900)));
BEAST_EXPECT(expectOffers(env, carol, 0)); BEAST_EXPECT(expectOffers(env, carol, 0));
}, },
{{XRP(10'100), USD(10'000)}}, {{XRP(10'100), USD(10'000)}},
0, 0,
std::nullopt, std::nullopt,
{tweakedFeatures}); {features});
// Immediate or Cancel - cross as much as possible // Immediate or Cancel - cross as much as possible
// and add nothing on the books. // and add nothing on the books.
testAMM( testAMM(
[&](AMM& ammAlice, Env& env) { [&](AMM& ammAlice, Env& env) {
env(offer(carol, XRP(200), USD(200)), env(offer(carol, XRP(200), USD(200)),
txflags(tfImmediateOrCancel), txflags(tfImmediateOrCancel),
ter(tesSUCCESS)); ter(tesSUCCESS));
// AMM generates a synthetic offer of 100USD/100XRP // AMM generates a synthetic offer of 100USD/100XRP
// to match the CLOB offer quality. // to match the CLOB offer quality.
BEAST_EXPECT(ammAlice.expectBalances( BEAST_EXPECT(ammAlice.expectBalances(
XRP(10'000), USD(10'100), ammAlice.tokens())); XRP(10'000), USD(10'100), ammAlice.tokens()));
// +AMM - offer * fee // +AMM - offer * fee
BEAST_EXPECT(expectLedgerEntryRoot( BEAST_EXPECT(expectLedgerEntryRoot(
env, carol, XRP(30'000) + XRP(100) - txfee(env, 1))); env, carol, XRP(30'000) + XRP(100) - txfee(env, 1)));
// AMM // AMM
BEAST_EXPECT(expectHolding(env, carol, USD(29'900))); BEAST_EXPECT(expectHolding(env, carol, USD(29'900)));
BEAST_EXPECT(expectOffers(env, carol, 0)); BEAST_EXPECT(expectOffers(env, carol, 0));
}, },
{{XRP(10'100), USD(10'000)}}, {{XRP(10'100), USD(10'000)}},
0, 0,
std::nullopt, std::nullopt,
{tweakedFeatures}); {features});
// tfPassive -- place the offer without crossing it. // tfPassive -- place the offer without crossing it.
testAMM( testAMM(
[&](AMM& ammAlice, Env& env) { [&](AMM& ammAlice, Env& env) {
// Carol creates a passive offer that could cross AMM. // Carol creates a passive offer that could cross AMM.
// Carol's offer should stay in the ledger. // Carol's offer should stay in the ledger.
env(offer(carol, XRP(100), USD(100), tfPassive)); env(offer(carol, XRP(100), USD(100), tfPassive));
env.close(); env.close();
BEAST_EXPECT(ammAlice.expectBalances( BEAST_EXPECT(ammAlice.expectBalances(
XRP(10'100), STAmount{USD, 10'000}, ammAlice.tokens())); XRP(10'100), STAmount{USD, 10'000}, ammAlice.tokens()));
BEAST_EXPECT(expectOffers( BEAST_EXPECT(expectOffers(
env, carol, 1, {{{XRP(100), STAmount{USD, 100}}}})); env, carol, 1, {{{XRP(100), STAmount{USD, 100}}}}));
}, },
{{XRP(10'100), USD(10'000)}}, {{XRP(10'100), USD(10'000)}},
0, 0,
std::nullopt, std::nullopt,
{tweakedFeatures}); {features});
// tfPassive -- cross only offers of better quality. // tfPassive -- cross only offers of better quality.
testAMM( testAMM(
[&](AMM& ammAlice, Env& env) { [&](AMM& ammAlice, Env& env) {
env(offer(alice, USD(110), XRP(100))); env(offer(alice, USD(110), XRP(100)));
env.close(); env.close();
// Carol creates a passive offer. That offer should cross // Carol creates a passive offer. That offer should cross
// AMM and leave Alice's offer untouched. // AMM and leave Alice's offer untouched.
env(offer(carol, XRP(100), USD(100), tfPassive)); env(offer(carol, XRP(100), USD(100), tfPassive));
env.close(); env.close();
BEAST_EXPECT(ammAlice.expectBalances( BEAST_EXPECT(ammAlice.expectBalances(
XRP(10'900), XRP(10'900),
STAmount{USD, UINT64_C(9'082'56880733945), -11}, STAmount{USD, UINT64_C(9'082'56880733945), -11},
ammAlice.tokens())); ammAlice.tokens()));
BEAST_EXPECT(expectOffers(env, carol, 0)); BEAST_EXPECT(expectOffers(env, carol, 0));
BEAST_EXPECT(expectOffers(env, alice, 1)); BEAST_EXPECT(expectOffers(env, alice, 1));
}, },
{{XRP(11'000), USD(9'000)}}, {{XRP(11'000), USD(9'000)}},
0, 0,
std::nullopt, std::nullopt,
{tweakedFeatures}); {features});
}
} }
void void
@@ -867,8 +858,7 @@ private:
using namespace jtx; using namespace jtx;
// Code returned if an offer is killed. // Code returned if an offer is killed.
TER const killedCode{ TER const killedCode{TER{tecKILLED}};
features[fix1578] ? TER{tecKILLED} : TER{tesSUCCESS}};
{ {
Env env{*this, features}; Env env{*this, features};
@@ -2819,15 +2809,9 @@ private:
testcase("Circular XRP"); testcase("Circular XRP");
using namespace jtx; using namespace jtx;
for (auto const withFix : {true, false})
{ {
auto const feats = withFix
? testable_amendments()
: testable_amendments() - FeatureBitset{fix1781};
// Payment path starting with XRP // Payment path starting with XRP
Env env(*this, feats); Env env(*this, testable_amendments());
// Note, if alice doesn't have default ripple, then pay // Note, if alice doesn't have default ripple, then pay
// fails with tecPATH_DRY. // fails with tecPATH_DRY.
fund( fund(
@@ -2842,8 +2826,7 @@ private:
AMM ammAliceXRP_EUR(env, alice, XRP(100), EUR(101)); AMM ammAliceXRP_EUR(env, alice, XRP(100), EUR(101));
env.close(); env.close();
TER const expectedTer = TER const expectedTer = TER{temBAD_PATH_LOOP};
withFix ? TER{temBAD_PATH_LOOP} : TER{tesSUCCESS};
env(pay(alice, bob, EUR(1)), env(pay(alice, bob, EUR(1)),
path(~USD, ~XRP, ~EUR), path(~USD, ~XRP, ~EUR),
sendmax(XRP(1)), sendmax(XRP(1)),

View File

@@ -545,8 +545,7 @@ public:
for (auto const& [hash, nVotes] : votes) for (auto const& [hash, nVotes] : votes)
{ {
if (rules.enabled(fixAmendmentMajorityCalc) ? nVotes >= i if (nVotes >= i)
: nVotes > i)
{ {
// We vote yes on this amendment // We vote yes on this amendment
field.push_back(hash); field.push_back(hash);
@@ -982,10 +981,6 @@ public:
void void
testChangedUNL(FeatureBitset const& feat) testChangedUNL(FeatureBitset const& feat)
{ {
// This test doesn't work without fixAmendmentMajorityCalc enabled.
if (!feat[fixAmendmentMajorityCalc])
return;
testcase("changedUNL"); testcase("changedUNL");
auto const testAmendment = amendmentId("changedUNL"); auto const testAmendment = amendmentId("changedUNL");
@@ -1143,10 +1138,6 @@ public:
void void
testValidatorFlapping(FeatureBitset const& feat) testValidatorFlapping(FeatureBitset const& feat)
{ {
// This test doesn't work without fixAmendmentMajorityCalc enabled.
if (!feat[fixAmendmentMajorityCalc])
return;
testcase("validatorFlapping"); testcase("validatorFlapping");
// We run a test where a validator flaps on and off every 23 hours // We run a test where a validator flaps on and off every 23 hours
@@ -1289,14 +1280,12 @@ public:
run() override run() override
{ {
FeatureBitset const all{test::jtx::testable_amendments()}; FeatureBitset const all{test::jtx::testable_amendments()};
FeatureBitset const fixMajorityCalc{fixAmendmentMajorityCalc};
testConstruct(); testConstruct();
testGet(); testGet();
testBadConfig(); testBadConfig();
testEnableVeto(); testEnableVeto();
testHasUnsupported(); testHasUnsupported();
testFeature(all - fixMajorityCalc);
testFeature(all); testFeature(all);
} }
}; };

View File

@@ -3946,14 +3946,13 @@ class Batch_test : public beast::unit_test::suite
tesSUCCESS, tesSUCCESS,
batch::outer(gw, seq, batchFee, tfIndependent), batch::outer(gw, seq, batchFee, tfIndependent),
batch::inner(jv1, seq + 1), batch::inner(jv1, seq + 1),
// tecNO_DELEGATE_PERMISSION: not authorized to clear freeze // terNO_DELEGATE_PERMISSION: not authorized to clear freeze
batch::inner(jv2, seq + 2)); batch::inner(jv2, seq + 2));
env.close(); env.close();
std::vector<TestLedgerData> testCases = { std::vector<TestLedgerData> testCases = {
{0, "Batch", "tesSUCCESS", batchID, std::nullopt}, {0, "Batch", "tesSUCCESS", batchID, std::nullopt},
{1, "TrustSet", "tesSUCCESS", txIDs[0], batchID}, {1, "TrustSet", "tesSUCCESS", txIDs[0], batchID},
{2, "TrustSet", "tecNO_DELEGATE_PERMISSION", txIDs[1], batchID},
}; };
validateClosedLedger(env, testCases); validateClosedLedger(env, testCases);
} }

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