Compare commits

..

300 Commits

Author SHA1 Message Date
Ed Hennis
9f626b052f Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-05-19 16:54:09 -04:00
Ed Hennis
ee49e76a16 Merge branch 'develop' into ximinez/online-delete-gaps 2026-05-19 16:53:27 -04:00
Ed Hennis
9fcee2f8b5 Merge remote-tracking branch 'XRPLF/ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated
* XRPLF/ximinez/online-delete-gaps:
  ci: Only run reusable package in public repos (7293)
  fix: Set default peering port to 2459 (6848)
  fix: Use account ledger entry when canceling token escrows (6171)
  refactor: Rename `account_` to `accountID_` (7284)
  ci: Add Linux package builds (DEB + RPM) to CI (6639)
  refactor: Clean up comments post-clang-tidy changes (7283)
  release: Set version to 3.3.0-b0 (7280)
  refactor: Rename static constants (7120)
  refactor: Use `isFlag` where possible instead of bitwise math (7278)
  ci: Update XRPLF/actions (7281)
2026-05-19 21:51:45 +01:00
Ed Hennis
c1318990f3 Merge branch 'develop' into ximinez/online-delete-gaps 2026-05-19 10:15:02 -04:00
Ed Hennis
69128294f8 Merge branch 'develop' into ximinez/online-delete-gaps 2026-05-19 05:15:40 -04:00
Ed Hennis
149e884ebc Merge branch 'develop' into ximinez/online-delete-gaps 2026-05-15 21:32:03 -04:00
Ed Hennis
d27353225c Merge remote-tracking branch 'XRPLF/develop' into ximinez/online-delete-gaps
* XRPLF/develop:
  release: Set version to 3.3.0-b0 (7280)
  refactor: Rename static constants (7120)
  refactor: Use `isFlag` where possible instead of bitwise math (7278)
  ci: Update XRPLF/actions (7281)
2026-05-15 15:47:01 -04:00
Ed Hennis
8cda06948a Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-05-14 20:39:37 -04:00
Ed Hennis
13a0f77eb5 Merge branch 'develop' into ximinez/online-delete-gaps 2026-05-14 20:39:04 -04:00
Ed Hennis
8fef7ce705 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-05-14 10:48:54 -04:00
Ed Hennis
549c093398 Merge branch 'develop' into ximinez/online-delete-gaps 2026-05-13 20:16:12 -04:00
Ed Hennis
5ab4dd3845 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-05-13 12:04:14 -04:00
Ed Hennis
fb66ca7a2e Merge branch 'develop' into ximinez/online-delete-gaps 2026-05-13 12:03:27 -04:00
Ed Hennis
5d29d31755 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-05-12 20:11:43 -04:00
Ed Hennis
e2af73b0a0 Merge branch 'develop' into ximinez/online-delete-gaps 2026-05-12 19:18:39 -04:00
Ed Hennis
14c3c9a256 Merge branch 'develop' into ximinez/online-delete-gaps 2026-05-12 16:26:02 -04:00
Ed Hennis
4b6851a287 Merge branch 'develop' into ximinez/online-delete-gaps 2026-05-12 15:59:13 -04:00
Ed Hennis
d182673d24 Merge branch 'develop' into ximinez/online-delete-gaps 2026-05-11 13:33:56 -04:00
Ed Hennis
dded5549d5 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-05-07 18:10:35 -04:00
Ed Hennis
bea609d805 Merge branch 'develop' into ximinez/online-delete-gaps 2026-05-07 18:09:54 -04:00
Ed Hennis
eb9d0c7006 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-05-07 14:19:42 -04:00
Ed Hennis
56eeb20bc8 Merge branch 'develop' into ximinez/online-delete-gaps 2026-05-07 14:18:14 -04:00
Ed Hennis
ce7e9af875 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-05-07 13:29:03 -04:00
Ed Hennis
e293a3d918 Merge branch 'develop' into ximinez/online-delete-gaps 2026-05-07 13:28:18 -04:00
Ed Hennis
a1fdd3b1ba Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-05-06 22:34:54 -04:00
Ed Hennis
3dff580d39 Merge branch 'develop' into ximinez/online-delete-gaps 2026-05-06 22:34:11 -04:00
Ed Hennis
2d797acca1 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-05-06 18:48:50 -04:00
Ed Hennis
487f5a0fd3 clang-tidy fix: lock_guard -> scoped_lock 2026-05-06 18:44:16 -04:00
Ed Hennis
d530f269ca Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-05-06 14:18:33 -04:00
Ed Hennis
d8134f98e9 Merge branch 'develop' into ximinez/online-delete-gaps 2026-05-06 14:17:47 -04:00
Ed Hennis
743c9b9ede Merge remote-tracking branch 'XRPLF/ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated
* XRPLF/ximinez/online-delete-gaps:
  fix: Fix regressions in `server_definitions` (7008)
  chore: Do not duplicate sanitizer flags (7058)
  ci: Run pre-commit on diff in clang-tidy workflow (7078)
  ci: Use XRPLF/create-issue (7076)
  ci: Rewrite clang-tidy workflow(s) in a reusable manner (7062)
  chore: Ignore identifier-naming update in git blame (7066)
  refactor: Enable clang-tidy `readability-identifier-naming` check (6571)
2026-05-05 19:25:10 -04:00
Ed Hennis
a22732fb66 Fix build errors caused by divergence from base branch 2026-05-05 19:17:54 -04:00
Ed Hennis
450a623d4b Merge branch 'develop' into ximinez/online-delete-gaps 2026-05-05 16:46:26 -04:00
Ed Hennis
9e517be4ce Merge branch 'develop' into ximinez/online-delete-gaps 2026-05-05 10:50:18 -04:00
Ed Hennis
b8370438fb Merge remote-tracking branch 'XRPLF/develop' into ximinez/online-delete-gaps
* XRPLF/develop:
  ci: Rewrite clang-tidy workflow(s) in a reusable manner (7062)
  chore: Ignore identifier-naming update in git blame (7066)
  refactor: Enable clang-tidy `readability-identifier-naming` check (6571)
2026-05-04 21:36:05 -04:00
Ed Hennis
2b948835e9 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-05-01 14:01:13 -04:00
Ed Hennis
ecb5604d3b Merge branch 'develop' into ximinez/online-delete-gaps 2026-05-01 12:54:31 -04:00
Ed Hennis
c4527e7b0f Merge remote-tracking branch 'XRPLF/develop' into ximinez/online-delete-gaps
* XRPLF/develop:
  fix: Gate -mcmodel flags to x86_64 in sanitizer builds (7049)
  fix: Prevents overwriting a bool value in an invariant (6609)
  fix: Address code review comments regarding `boost::coroutine2` (6977)
  refactor: Apply various minor improvements and corrections (7045)
  fix: Store `Delegate` object in delegating and authorized account directories for proper deletion (6681)
  ci: Use print-env from XRPLF/actions (7052)
  fix: Make assorted RPC fixes (6529)
  chore: Enable clang-tidy v21 new checks (7031)
2026-04-30 14:30:36 -04:00
Ed Hennis
778e2b3ce8 Fix clang-tidy: missing include 2026-04-28 15:44:14 -05:00
Ed Hennis
23146d684b Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-04-28 16:31:50 -04:00
Ed Hennis
295d03aec8 Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-28 16:23:08 -04:00
Ed Hennis
e45be2411f Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-04-25 14:46:13 -04:00
Ed Hennis
9262c2e624 Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-25 14:41:57 -04:00
Ed Hennis
dbcc37548e Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-04-23 15:56:35 -04:00
Ed Hennis
b385a41aa5 Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-23 15:55:43 -04:00
Ed Hennis
488ce12a13 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-04-22 23:53:00 -04:00
Ed Hennis
4eb9726097 Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-22 23:39:00 -04:00
Ed Hennis
d961f3d88a Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-04-22 14:49:34 -04:00
Ed Hennis
28a38ef1cc Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-22 14:48:51 -04:00
Ed Hennis
52c14b533d Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-04-22 13:11:06 -04:00
Ed Hennis
39f9380b2b Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-22 11:36:03 -04:00
Ed Hennis
e135f43430 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-04-21 19:35:08 -04:00
Ed Hennis
239fcaceb4 clang-tidy fix: Use std::to_string for std::uint32_t 2026-04-21 19:30:05 -04:00
Ed Hennis
8ab86f009e Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-21 18:47:53 -04:00
Ed Hennis
d4b58a74f4 Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-21 14:37:52 -04:00
Ed Hennis
ff900591ae Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-21 10:40:45 -04:00
Ed Hennis
87f2a7fc40 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-04-20 17:50:07 -04:00
Ed Hennis
a5b7471af6 Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-20 17:49:20 -04:00
Ed Hennis
6d022e8710 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-04-20 15:45:25 -04:00
Ed Hennis
e0734986dd Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-20 15:44:37 -04:00
Ed Hennis
bf8ccd0065 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-04-20 11:39:31 -04:00
Ed Hennis
8440f479e5 Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-20 11:37:54 -04:00
Ed Hennis
2da44b43d6 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-04-17 18:21:06 -04:00
Ed Hennis
ac390622e0 Fix clang-tidy issues 2026-04-17 17:54:37 -04:00
Ed Hennis
5d807f0d6d Merge remote-tracking branch 'XRPLF/develop' into ximinez/online-delete-gaps
* XRPLF/develop:
  chore: Enable clang-tidy include cleaner (6947)
  fix: Change AMMClawback return code to tecNO_PERMISSION (6946)
  ci: [DEPENDABOT] bump actions/upload-pages-artifact from 4.0.0 to 5.0.0 (6927)
  ci: [DEPENDABOT] bump actions/upload-artifact from 7.0.0 to 7.0.1 (6928)
  chore: Enable clang-tidy readability checks (6930)
2026-04-17 15:23:33 -04:00
Ed Hennis
e40135eb41 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-04-16 13:44:56 -04:00
Ed Hennis
b93294f26b Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-16 13:44:23 -04:00
Ed Hennis
09ba4138db Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-04-15 19:09:41 -04:00
Ed Hennis
ef95ace0f9 Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-15 19:06:15 -04:00
Ed Hennis
490fb6e15a Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-04-15 14:29:17 -04:00
Ed Hennis
fc58bf6edf Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-15 14:28:41 -04:00
Ed Hennis
05644b52e1 Merge remote-tracking branch 'XRPLF/ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated
* XRPLF/ximinez/online-delete-gaps:
  Fix clang-tidy issues
  refactor: Remove unused notTooManyOffers function from NFTokenUtils (6737)
2026-04-13 20:39:46 -04:00
Ed Hennis
348555d5ba Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-13 20:28:29 -04:00
Ed Hennis
302802e42d Fix clang-tidy issues 2026-04-13 20:23:23 -04:00
Ed Hennis
1fcde8ac28 fix formatting 2026-04-13 20:11:32 -04:00
Ed Hennis
eebff3ece2 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-04-10 12:13:11 -04:00
Ed Hennis
5d881f87a3 Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-10 12:12:27 -04:00
Ed Hennis
be6b84d4be Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-04-10 09:13:35 -04:00
Ed Hennis
a8a8035b32 Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-10 09:10:39 -04:00
Ed Hennis
0b981528b9 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-04-09 11:51:02 -04:00
Ed Hennis
45af14231f Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-09 11:39:55 -04:00
Ed Hennis
2576f16f96 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-04-08 17:00:25 -04:00
Ed Hennis
380bf274d0 Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-08 16:56:56 -04:00
Ed Hennis
460ec5eeea Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-08 15:12:46 -04:00
Ed Hennis
df47e892a3 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-04-07 17:11:17 -04:00
Ed Hennis
14be8ca4ea Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-07 16:47:32 -04:00
Ed Hennis
948264d44c Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-06 19:06:51 -04:00
Ed Hennis
9c816b2043 Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-06 18:33:20 -04:00
Ed Hennis
f68402acd1 Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-06 16:52:50 -04:00
Ed Hennis
5358e25eaa Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-06 13:24:22 -04:00
Ed Hennis
a34d1e5537 Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-01 17:26:14 -04:00
Ed Hennis
78a122943d Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-01 13:39:05 -04:00
Ed Hennis
06135e7203 Merge branch 'develop' into ximinez/online-delete-gaps 2026-04-01 11:45:32 -04:00
Ed Hennis
f20425fa4f Merge branch 'develop' into ximinez/online-delete-gaps 2026-03-30 21:29:37 -04:00
Ed Hennis
3e94546acc Merge branch 'develop' into ximinez/online-delete-gaps 2026-03-12 15:05:04 -04:00
Ed Hennis
e2d9e436ba Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-03-10 13:39:16 -04:00
Ed Hennis
3b088ed0dc Merge branch 'develop' into ximinez/online-delete-gaps 2026-03-10 12:46:18 -04:00
Ed Hennis
5088b0f7f6 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-03-06 13:32:10 -04:00
Ed Hennis
26182ed52e Merge branch 'develop' into ximinez/online-delete-gaps 2026-03-06 13:04:00 -04:00
Ed Hennis
de2a3e10f5 Merge branch 'develop' into ximinez/online-delete-gaps 2026-03-05 21:34:29 -04:00
Ed Hennis
bfaa50d001 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-03-04 17:12:07 -04:00
Ed Hennis
e17f8554fc Merge branch 'develop' into ximinez/online-delete-gaps 2026-03-04 17:11:27 -04:00
Ed Hennis
5a559fa0d5 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-03-03 21:49:28 -04:00
Ed Hennis
386a7192ba Merge branch 'develop' into ximinez/online-delete-gaps 2026-03-03 20:46:41 -04:00
Ed Hennis
5447a0a20b Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-03-03 18:38:39 -04:00
Ed Hennis
12cc6e424d Merge branch 'develop' into ximinez/online-delete-gaps 2026-03-03 15:54:32 -04:00
Ed Hennis
a4e3004229 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-02-24 17:43:37 -04:00
Ed Hennis
c9deecf1b7 Merge branch 'develop' into ximinez/online-delete-gaps 2026-02-24 17:34:32 -04:00
Ed Hennis
ddd1b49f38 Merge branch 'develop' into ximinez/online-delete-gaps 2026-02-24 16:45:55 -04:00
Ed Hennis
889d88d644 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-02-20 18:51:03 -04:00
Ed Hennis
c1b2a24005 Merge branch 'develop' into ximinez/online-delete-gaps 2026-02-20 18:49:39 -04:00
Ed Hennis
89076a9560 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-02-20 18:27:58 -04:00
Ed Hennis
86d88eca31 Merge branch 'develop' into ximinez/online-delete-gaps 2026-02-20 18:25:58 -04:00
Ed Hennis
ef09eaea00 Merge branch 'develop' into ximinez/online-delete-gaps 2026-02-20 17:31:41 -04:00
Ed Hennis
c504cfb291 Merge branch 'develop' into ximinez/online-delete-gaps 2026-02-20 17:21:03 -04:00
Ed Hennis
0c217dfa2b Merge branch 'develop' into ximinez/online-delete-gaps 2026-02-20 15:14:23 -04:00
Ed Hennis
b0198d2566 Merge remote-tracking branch 'upstream/develop' into ximinez/online-delete-gaps
* upstream/develop:
  ci: Add dependabot config (6379)
  Fix tautological assertion (6393)
  chore: Apply clang-format width 100 (6387)
2026-02-20 12:20:07 -05:00
Ed Hennis
7eee8ca802 Update formatting 2026-02-20 12:15:30 -05:00
Ed Hennis
2a079a0154 Merge commit '25cca465538a56cce501477f9e5e2c1c7ea2d84c' into ximinez/online-delete-gaps
* commit '25cca465538a56cce501477f9e5e2c1c7ea2d84c':
  chore: Set clang-format width to 100 in config file (6387)
2026-02-20 12:12:56 -05:00
Ed Hennis
3911bde4d5 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-02-19 16:25:17 -05:00
Ed Hennis
40989c1178 Merge branch 'develop' into ximinez/online-delete-gaps 2026-02-19 16:21:11 -05:00
Ed Hennis
4c79a39428 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-02-18 21:13:25 -04:00
Ed Hennis
addc831eb3 Merge branch 'develop' into ximinez/online-delete-gaps 2026-02-18 18:06:20 -04:00
Ed Hennis
5bbe9f5ad8 Merge remote-tracking branch 'XRPLF/ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated
* XRPLF/ximinez/online-delete-gaps:
  chore: Update secp256k1 and openssl (6327)
  chore: Remove unnecessary script (6326)
  refactor: Replace include guards by '#pragma once' (6322)
  chore: Remove unity builds (6300)
  refactor: Add ServiceRegistry to help modularization (6222)
  fix: Deletes expired NFToken offers from ledger (5707)
  chore: Add .zed editor config directory to .gitignore (6317)
  docs: Update API changelog, add APIv2+APIv3 version documentation (6308)
  fix: Restore config changes that broke standalone mode (6301)
  chore: Add upper-case match for ARM64 in CompilationEnv (6315)
  ci: Update hashes of XRPLF/actions (6316)
  chore: Format all cmake files without comments (6294)
  chore: Add cmake-format pre-commit hook (6279)
  Fix formatting
2026-02-04 16:16:09 -05:00
Ed Hennis
b4efc6d116 Merge branch 'develop' into ximinez/online-delete-gaps 2026-02-04 16:29:49 -04:00
Ed Hennis
125d075d6e Merge branch 'develop' into ximinez/online-delete-gaps 2026-02-04 14:16:24 -04:00
Ed Hennis
370a775479 Merge branch 'develop' into ximinez/online-delete-gaps 2026-02-03 16:07:47 -04:00
Ed Hennis
8cad1455af Fix formatting 2026-01-28 19:44:21 -05:00
Ed Hennis
1a2ee706eb Fix formatting 2026-01-28 19:43:23 -05:00
Ed Hennis
78c79c000c Fix formatting 2026-01-28 19:29:25 -05:00
Ed Hennis
16640d611a Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-01-28 19:16:42 -04:00
Ed Hennis
eeee7a36c8 Merge commit '1ae475e724' into ximinez/online-delete-lastrotated
* commit '1ae475e724':
  chore: Set ColumnLimit to 120 in clang-format (6288)
2026-01-28 18:15:30 -05:00
Ed Hennis
8249b30dc9 Merge commit 'a3e9401fbc' into ximinez/online-delete-lastrotated
* commit 'a3e9401fbc':
  test: Fix the `xrpl.net` unit test using async read (6241)
  ci: Upload Conan recipes for develop, release candidates, and releases (6286)
  fix: Stop embedded tests from hanging on ARM by using `atomic_flag` (6248)
  fix:  Remove DEFAULT fields that change to the default in associateAsset (6259) (6273)
  refactor: Update Boost to 1.90 (6280)
  refactor: clean up uses of `std::source_location` (6272)
  ci: Pass missing sanitizers input to actions (6266)
  ci: Properly propagate Conan credentials (6265)
  ci: Explicitly set version when exporting the Conan recipe (6264)
  ci: Use plus instead of hyphen for Conan recipe version suffix (6261)
  chore: Detect uninitialized variables in CMake files (6247)
  ci: Run on-trigger and on-pr when generate-version is modified (6257)
  refactor: Enforce 15-char limit and simplify labels for thread naming (6212)
  docs: Update Ripple Bug Bounty public key (6258)
  ci: Add missing commit hash to Conan recipe version (6256)
  fix: Include `<functional>` header in `Number.h` (6254)
  ci: Upload Conan recipe for merges into develop and commits to release (6235)
  Limit reply size on `TMGetObjectByHash` queries (6110)
  ci: remove 'master' branch as a trigger (6234)
  Improve ledger_entry lookups for fee, amendments, NUNL, and hashes (5644)
2026-01-28 18:15:11 -05:00
Ed Hennis
2a981357ba Merge branch 'develop' into ximinez/online-delete-gaps 2026-01-28 18:40:24 -04:00
Ed Hennis
1ae475e724 Merge commit '5f638f55536def0d88b970d1018a465a238e55f4' into ximinez/online-delete-gaps
* commit '5f638f55536def0d88b970d1018a465a238e55f4':
  chore: Set ColumnLimit to 120 in clang-format (6288)
2026-01-28 17:38:29 -05:00
Ed Hennis
a3e9401fbc Merge commit '92046785d1fea5f9efe5a770d636792ea6cab78b' into ximinez/online-delete-gaps
* commit '92046785d1fea5f9efe5a770d636792ea6cab78b':
  test: Fix the `xrpl.net` unit test using async read (6241)
  ci: Upload Conan recipes for develop, release candidates, and releases (6286)
  fix: Stop embedded tests from hanging on ARM by using `atomic_flag` (6248)
  fix:  Remove DEFAULT fields that change to the default in associateAsset (6259) (6273)
  refactor: Update Boost to 1.90 (6280)
  refactor: clean up uses of `std::source_location` (6272)
  ci: Pass missing sanitizers input to actions (6266)
  ci: Properly propagate Conan credentials (6265)
  ci: Explicitly set version when exporting the Conan recipe (6264)
  ci: Use plus instead of hyphen for Conan recipe version suffix (6261)
  chore: Detect uninitialized variables in CMake files (6247)
  ci: Run on-trigger and on-pr when generate-version is modified (6257)
  refactor: Enforce 15-char limit and simplify labels for thread naming (6212)
  docs: Update Ripple Bug Bounty public key (6258)
  ci: Add missing commit hash to Conan recipe version (6256)
  fix: Include `<functional>` header in `Number.h` (6254)
  ci: Upload Conan recipe for merges into develop and commits to release (6235)
  Limit reply size on `TMGetObjectByHash` queries (6110)
  ci: remove 'master' branch as a trigger (6234)
  Improve ledger_entry lookups for fee, amendments, NUNL, and hashes (5644)
2026-01-28 17:38:13 -05:00
Ed Hennis
268953c386 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-01-15 13:16:33 -04:00
Ed Hennis
9091469f9e Merge branch 'develop' into ximinez/online-delete-gaps 2026-01-15 13:03:03 -04:00
Ed Hennis
bd340fd0b6 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-01-15 12:06:24 -04:00
Ed Hennis
17fa54f1f9 Merge branch 'develop' into ximinez/online-delete-gaps 2026-01-15 12:05:41 -04:00
Ed Hennis
8fb5347c2d Merge branch 'develop' into ximinez/online-delete-gaps 2026-01-14 19:20:11 -04:00
Ed Hennis
72899948b8 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-01-13 18:19:31 -04:00
Ed Hennis
6739bf998f Merge branch 'develop' into ximinez/online-delete-gaps 2026-01-13 18:04:18 -04:00
Ed Hennis
6eea38ba67 Merge branch 'develop' into ximinez/online-delete-gaps 2026-01-13 16:15:44 -04:00
Ed Hennis
c662169770 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-01-13 15:35:24 -04:00
Ed Hennis
e9cf88b359 Merge branch 'develop' into ximinez/online-delete-gaps 2026-01-13 15:01:56 -04:00
Ed Hennis
645b203476 Merge branch 'develop' into ximinez/online-delete-gaps 2026-01-12 21:07:23 -04:00
Ed Hennis
6cf8f4e33c Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-01-12 14:52:38 -04:00
Ed Hennis
be2aff1f4c Merge branch 'develop' into ximinez/online-delete-gaps 2026-01-12 14:51:34 -04:00
Ed Hennis
39279f7d6d Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-01-11 00:55:37 -04:00
Ed Hennis
56ed237e82 Merge branch 'develop' into ximinez/online-delete-gaps 2026-01-11 00:48:27 -04:00
Ed Hennis
0f0b606f8a Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-01-08 17:07:09 -04:00
Ed Hennis
fd7b0fd135 Merge branch 'develop' into ximinez/online-delete-gaps 2026-01-08 17:05:28 -04:00
Ed Hennis
6189b772f7 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-01-08 13:05:35 -04:00
Ed Hennis
e700994891 Merge branch 'develop' into ximinez/online-delete-gaps 2026-01-08 13:03:41 -04:00
Ed Hennis
467b5f26aa Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2026-01-06 14:02:38 -05:00
Ed Hennis
c76f7029ac Merge remote-tracking branch 'XRPLF/develop' into ximinez/online-delete-gaps
* XRPLF/develop:
  test: add more tests for `ledger_entry` RPC (5858)
  refactor: Rename `rippled.cfg` to `xrpld.cfg` (6098)
  Revert "chore: Pin ruamel.yaml<0.19 in pre-commit-hooks (6166)" (6167)
  chore: Pin ruamel.yaml<0.19 in pre-commit-hooks (6166)
  fix: Remove cryptographic libs from libxrpl Conan package (6163)
2026-01-06 11:27:23 -05:00
Ed Hennis
94fe83e196 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2025-12-22 17:51:25 -05:00
Ed Hennis
d535c5fb2a Merge branch 'develop' into ximinez/online-delete-gaps 2025-12-22 17:39:25 -05:00
Ed Hennis
3c7714ea61 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2025-12-18 20:00:12 -05:00
Ed Hennis
54f860463e Merge branch 'develop' into ximinez/online-delete-gaps 2025-12-18 18:15:15 -05:00
Ed Hennis
950434b8ff Merge branch 'develop' into ximinez/online-delete-gaps 2025-12-17 12:12:39 -05:00
Ed Hennis
63a47840dd Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2025-12-12 20:39:32 -05:00
Ed Hennis
ee365e876d Merge branch 'develop' into ximinez/online-delete-gaps 2025-12-12 20:34:29 -05:00
Ed Hennis
c6c59834b9 Update View info() to header() 2025-12-12 15:35:07 -05:00
Ed Hennis
84cffe39e8 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2025-12-11 16:14:37 -05:00
Ed Hennis
63b47914b8 Merge remote-tracking branch 'XRPLF/develop' into ximinez/online-delete-gaps
* XRPLF/develop:
  refactor: Rename `ripple` namespace to `xrpl` (5982)
  refactor: Move JobQueue and related classes into xrpl.core module (6121)
  refactor: Rename `rippled` binary to `xrpld` (5983)
2025-12-11 15:25:43 -05:00
Ed Hennis
9e02e5be2e Merge branch 'develop' into ximinez/online-delete-gaps 2025-12-10 18:55:14 -05:00
Ed Hennis
56b5b896a1 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2025-12-05 21:13:29 -05:00
Ed Hennis
093cd70fa1 Merge branch 'develop' into ximinez/online-delete-gaps 2025-12-05 21:12:43 -05:00
Ed Hennis
034b387eb9 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2025-12-02 19:06:46 -05:00
Ed Hennis
376d65a483 Merge branch 'develop' into ximinez/online-delete-gaps 2025-12-02 17:21:39 -05:00
Ed Hennis
838d340faf Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2025-12-01 14:41:06 -05:00
Ed Hennis
a0d9a2458e Merge branch 'develop' into ximinez/online-delete-gaps 2025-12-01 14:40:15 -05:00
Ed Hennis
aa6d53849f Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2025-11-28 15:52:49 -05:00
Ed Hennis
456f639cf7 Merge branch 'develop' into ximinez/online-delete-gaps 2025-11-28 15:46:19 -05:00
Ed Hennis
2c559ec2f3 Merge branch 'develop' into ximinez/online-delete-gaps 2025-11-27 01:48:33 -05:00
Ed Hennis
457b80d882 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2025-11-26 00:25:38 -05:00
Ed Hennis
619c81f463 Merge branch 'develop' into ximinez/online-delete-gaps 2025-11-26 00:24:50 -05:00
Ed Hennis
b2b079b546 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2025-11-25 14:55:28 -05:00
Ed Hennis
f1490df960 Merge branch 'develop' into ximinez/online-delete-gaps 2025-11-25 14:54:38 -05:00
Ed Hennis
5926b4bf57 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2025-11-24 21:49:30 -05:00
Ed Hennis
7bdf74de98 Merge branch 'develop' into ximinez/online-delete-gaps 2025-11-24 21:48:42 -05:00
Ed Hennis
81300afd19 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2025-11-24 21:30:42 -05:00
Ed Hennis
1743d6fb98 Merge branch 'develop' into ximinez/online-delete-gaps 2025-11-24 21:29:52 -05:00
Ed Hennis
879d054eed Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2025-11-21 14:34:53 -05:00
Ed Hennis
ca7a5bb926 Merge branch 'develop' into ximinez/online-delete-gaps 2025-11-21 12:47:28 -05:00
Ed Hennis
f2ee3b9f49 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2025-11-18 22:51:25 -05:00
Ed Hennis
ce8b1a3f1e Merge branch 'develop' into ximinez/online-delete-gaps 2025-11-18 22:39:06 -05:00
Ed Hennis
b72cf3d7d9 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2025-11-15 03:09:00 -05:00
Ed Hennis
486fa75a10 Merge branch 'develop' into ximinez/online-delete-gaps 2025-11-15 03:08:18 -05:00
Ed Hennis
2017304c71 Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2025-11-13 12:20:18 -05:00
Ed Hennis
f8d68cd3d3 Merge branch 'develop' into ximinez/online-delete-gaps 2025-11-13 12:18:08 -05:00
Ed Hennis
bb71c62fca Merge branch 'ximinez/online-delete-gaps' into ximinez/online-delete-lastrotated 2025-11-12 14:17:06 -05:00
Ed Hennis
ef7a3f5606 Merge branch 'develop' into ximinez/online-delete-gaps 2025-11-12 13:59:45 -05:00
Ed Hennis
ab740d94e6 fix: Update lastRotated to the current validated seq + 2
- First approximation. Good enough and consistent enough for unit tests.
  Not sure about real world, but it'll be an improvement either way.
2025-11-10 19:53:53 -05:00
Ed Hennis
ae3e4aa56b Create a unit test demonstrating "lost" ledgers
- It is possible for changed ledger objects to be written to the
  ArchiveDB during the online delete rotation process before the
  writable DB is created. When the rotation finishes, `lastRotated` is
  updated to the ledger sequence from when the process started, on the
  assumption that all ledgers after that will be written to the new
  writable DB, but some of them are in the old DB. Next time rotation
  runs, the data for those old ledgers is not brought over, and thus is
  deleted from the Archive DB.
2025-11-10 19:53:53 -05:00
Ed Hennis
e92437b083 Revert "Fix build errors"
This reverts commit e13baa58a5.
2025-11-10 19:53:52 -05:00
Ed Hennis
4f84ed7490 Merge branch 'develop' into ximinez/online-delete-gaps 2025-11-10 19:52:42 -05:00
Ed Hennis
d534103131 Merge branch 'develop' into ximinez/online-delete-gaps 2025-11-10 15:34:55 -05:00
Ed Hennis
82dff3c2ce Merge branch 'develop' into ximinez/online-delete-gaps 2025-11-08 22:49:26 -05:00
Ed Hennis
30d73eb5ba Merge branch 'develop' into ximinez/online-delete-gaps 2025-11-06 23:50:23 -05:00
Ed Hennis
1b2754bac2 Merge branch 'develop' into ximinez/online-delete-gaps 2025-11-05 22:23:07 -05:00
Ed Hennis
cf80cafc75 Merge branch 'develop' into ximinez/online-delete-gaps 2025-11-04 18:02:30 -05:00
Ed Hennis
b8897d51de Merge branch 'develop' into ximinez/online-delete-gaps 2025-11-03 18:03:56 -05:00
Ed Hennis
3ff25eeb65 Merge branch 'develop' into ximinez/online-delete-gaps 2025-11-03 12:41:48 -05:00
Ed Hennis
2bbfc4e786 Merge branch 'develop' into ximinez/online-delete-gaps 2025-10-31 13:51:15 -04:00
Ed Hennis
2b1eb052e6 Merge branch 'develop' into ximinez/online-delete-gaps 2025-10-31 12:51:24 -04:00
Ed Hennis
360e214e54 Merge branch 'develop' into ximinez/online-delete-gaps 2025-10-29 14:23:10 -04:00
Ed Hennis
2618afed94 Merge branch 'develop' into ximinez/online-delete-gaps 2025-10-29 13:42:21 -04:00
Ed Hennis
698ba2c788 Merge branch 'develop' into ximinez/online-delete-gaps 2025-10-29 12:54:16 -04:00
Ed Hennis
b614e99588 Merge branch 'develop' into ximinez/online-delete-gaps 2025-10-28 17:38:21 -04:00
Ed Hennis
fe8e4af2fa Merge branch 'develop' into ximinez/online-delete-gaps 2025-10-26 19:12:33 -04:00
Ed Hennis
0a897f1528 Merge branch 'develop' into ximinez/online-delete-gaps 2025-10-23 13:24:25 -04:00
Ed Hennis
cf8a3f5779 Merge branch 'develop' into ximinez/online-delete-gaps 2025-10-22 11:38:49 -04:00
Ed Hennis
db39a39868 Merge branch 'develop' into ximinez/online-delete-gaps 2025-10-21 22:20:04 -04:00
Ed Hennis
37a03d28c2 Merge branch 'develop' into ximinez/online-delete-gaps 2025-10-17 18:21:36 -04:00
Ed Hennis
19d275425a Merge branch 'develop' into ximinez/online-delete-gaps 2025-10-16 13:12:08 -04:00
Ed Hennis
88e9045602 Merge branch 'develop' into ximinez/online-delete-gaps 2025-10-16 10:48:43 -04:00
Ed Hennis
5adbc536b6 Merge branch 'develop' into ximinez/online-delete-gaps 2025-10-10 13:01:32 -04:00
Ed Hennis
e27af94ba9 Merge branch 'develop' into ximinez/online-delete-gaps 2025-10-09 15:14:47 -04:00
Ed Hennis
43fe1e7e9c Merge branch 'develop' into ximinez/online-delete-gaps 2025-10-08 14:21:34 -04:00
Ed Hennis
f456a858c8 Merge branch 'develop' into ximinez/online-delete-gaps 2025-10-02 11:03:07 -04:00
Ed Hennis
084c3aa88e Merge branch 'develop' into ximinez/online-delete-gaps 2025-10-01 18:10:57 -04:00
Ed Hennis
34f9b63921 Merge branch 'develop' into ximinez/online-delete-gaps 2025-10-01 13:14:22 -04:00
Ed Hennis
bd3de79817 Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-30 22:28:53 -04:00
Ed Hennis
304eee2259 Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-29 18:34:43 -04:00
Ed Hennis
9e729b7f59 Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-29 17:37:16 -04:00
Ed Hennis
dd141468c4 Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-29 13:32:03 -04:00
Ed Hennis
933147c21f Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-26 19:25:58 -04:00
Ed Hennis
9201a4f591 Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-26 13:41:27 -04:00
Ed Hennis
5adb1e9b8b Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-26 12:09:09 -04:00
Ed Hennis
4df84d7988 Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-25 13:27:09 -04:00
Bart
cd87c0968b Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-24 09:35:19 +02:00
Ed Hennis
8a8e7c90bf Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-20 15:44:32 -04:00
Ed Hennis
e806069065 Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-18 14:08:23 -04:00
Ed Hennis
ce948cbec0 Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-18 12:26:34 -04:00
Ed Hennis
6ed34b3294 Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-18 11:54:30 -04:00
Ed Hennis
7161a235ca Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-17 10:49:03 -04:00
Ed Hennis
71463810de Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-16 10:46:37 -04:00
Ed Hennis
e997219a85 Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-15 11:13:28 -04:00
Ed Hennis
895cc13fa6 Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-11 10:33:14 -04:00
Ed Hennis
8d3c3ca29a Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-10 18:53:24 -04:00
Ed Hennis
9829553807 Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-09 17:14:20 -04:00
Ed Hennis
e551f9731a Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-08 11:41:46 -04:00
Ed Hennis
fd827bf58b Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-05 17:44:06 -04:00
Ed Hennis
5a3baba34d Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-04 20:24:55 -04:00
Ed Hennis
c78f5b160f Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-04 16:43:48 -04:00
Ed Hennis
485f78761a Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-04 12:26:55 -04:00
Ed Hennis
23cd2f7b21 Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-04 10:14:10 -04:00
Ed Hennis
5753266c43 Merge branch 'develop' into ximinez/online-delete-gaps 2025-09-03 14:04:01 -04:00
Ed Hennis
4722d2607d Merge branch 'develop' into ximinez/online-delete-gaps 2025-08-29 15:52:53 -04:00
Ed Hennis
85b5b4f855 Merge branch 'develop' into ximinez/online-delete-gaps 2025-08-29 10:42:50 -04:00
Ed Hennis
a16f492f0f Merge branch 'develop' into ximinez/online-delete-gaps 2025-08-28 18:17:26 -04:00
Ed Hennis
3633dc632c Merge branch 'develop' into ximinez/online-delete-gaps 2025-08-27 11:14:59 -04:00
Ed Hennis
b3b30c3a86 Merge branch 'develop' into ximinez/online-delete-gaps 2025-08-25 14:10:52 -04:00
Ed Hennis
c78a7684f4 Remove trailing space 2025-08-25 14:09:57 -04:00
Ed Hennis
cf83d92630 Merge remote-tracking branch 'upstream/develop' into ximinez/online-delete-gaps
* upstream/develop:
  chore: Remove codecov token check to support tokenless uploads on forks (5722)
  Set version to 2.6.0-rc3
  Revert "perf: Move mutex to the partition level (5486)"
  chore: Update clang-format and prettier with pre-commit (5709)
  fix(test): handle null metadata for unvalidated tx in Env::meta (5715)
  chore: Workaround for CI build errors on arm64 (5717)
  chore: Fix file formatting (5718)
  fix: Skip notify-clio when running in a fork, reorder config fields (5712)
  chore: Reverts formatting changes to external files, adds formatting changes to proto files (5711)
2025-08-25 14:05:49 -04:00
Ed Hennis
a56b1274d8 Merge branch 'develop' into ximinez/online-delete-gaps 2025-08-21 11:38:54 -04:00
Ed Hennis
ae4bdd0492 Merge branch 'develop' into ximinez/online-delete-gaps 2025-08-19 16:05:17 -04:00
Ed Hennis
e90102dd3b Merge branch 'develop' into ximinez/online-delete-gaps 2025-08-18 12:15:38 -04:00
Ed Hennis
71f0e8db3d Merge branch 'develop' into ximinez/online-delete-gaps 2025-08-08 18:23:24 -04:00
Ed Hennis
638929373a Merge branch 'develop' into ximinez/online-delete-gaps 2025-08-08 11:10:20 -04:00
Ed Hennis
8440654377 Merge branch 'develop' into ximinez/online-delete-gaps 2025-08-06 21:03:00 -04:00
Ed Hennis
9fa66c4741 Merge branch 'develop' into ximinez/online-delete-gaps 2025-08-05 21:16:44 -04:00
Ed Hennis
38a9235145 Merge branch 'develop' into ximinez/online-delete-gaps 2025-08-04 13:04:52 -04:00
Ed Hennis
c7a3cc9108 Merge branch 'develop' into ximinez/online-delete-gaps 2025-07-29 20:33:29 -04:00
Ed Hennis
248337908d Merge branch 'develop' into ximinez/online-delete-gaps 2025-07-29 11:54:16 -04:00
Ed Hennis
3d003619fd Merge branch 'develop' into ximinez/online-delete-gaps 2025-07-28 20:57:13 -04:00
Ed Hennis
f163dca12c Merge branch 'develop' into ximinez/online-delete-gaps 2025-07-24 15:50:09 -04:00
Ed Hennis
6e0ce458e5 Revert "TEMP: Change some logging to fatal to diagnose CI failures"
This reverts commit 69cf18158b.
2025-07-22 19:41:02 -04:00
Ed Hennis
5fae8480f1 Revert "TEMP: Add logging to SHAMapStore test"
This reverts commit fe7d0798a7.
2025-07-22 19:40:58 -04:00
Ed Hennis
e6587d374a fixup! Tweak SHAMapStore test timing more 2025-07-22 19:39:58 -04:00
Ed Hennis
376cc404e0 Tweak SHAMapStore test timing more 2025-07-22 18:44:07 -04:00
Ed Hennis
9898ca638f Merge branch 'develop' into ximinez/online-delete-gaps 2025-07-22 14:09:33 -04:00
Ed Hennis
34b46d8f7c Merge branch 'develop' into ximinez/online-delete-gaps 2025-07-21 18:20:41 -04:00
Ed Hennis
fe7d0798a7 TEMP: Add logging to SHAMapStore test 2025-07-21 18:19:53 -04:00
Ed Hennis
0cecc09d71 Tweak timing of SHAMapStore test 2025-07-21 18:19:28 -04:00
Ed Hennis
e091d55561 Try to fix timing of LedgerMaster test 2025-07-21 15:14:42 -04:00
Ed Hennis
69cf18158b TEMP: Change some logging to fatal to diagnose CI failures 2025-07-21 14:32:08 -04:00
Ed Hennis
6513c53817 Improve logging
- There's still a race condition in there
2025-07-21 14:30:49 -04:00
Ed Hennis
e13baa58a5 Fix build errors 2025-07-21 13:31:09 -04:00
Ed Hennis
951056fe9b Merge branch 'develop' into ximinez/online-delete-gaps 2025-07-18 18:33:10 -04:00
Ed Hennis
67700ea6bd Merge branch 'develop' into ximinez/online-delete-gaps 2025-07-16 12:54:23 -04:00
Ed Hennis
e5442cf3f1 Merge branch 'develop' into ximinez/online-delete-gaps 2025-07-15 19:36:25 -04:00
Ed Hennis
da68076f04 Change default recovery wait time to 1s
See https://github.com/XRPLF/rippled/pull/5531#issuecomment-3058218837
2025-07-14 14:13:32 -04:00
Ed Hennis
b24116a118 Improve locking, logging, and test output
- Add more info to the error message on some failed tests.
- Add logging details to SHAMapStoreImp
2025-07-14 14:13:27 -04:00
Ed Hennis
f67398c6bf Merge branch 'develop' into ximinez/online-delete-gaps 2025-07-11 19:27:31 -04:00
Ed Hennis
43d3eb1a24 Merge branch 'develop' into ximinez/online-delete-gaps 2025-07-10 21:25:22 -04:00
Ed Hennis
0993315ed5 Merge branch 'develop' into ximinez/online-delete-gaps 2025-07-10 12:30:18 -04:00
Ed Hennis
0bc383ada9 Fix build errors 2025-07-08 20:15:05 -04:00
Ed Hennis
1841ceca43 Add more logging to SHAMapStore rotation 2025-07-08 16:05:03 -04:00
Ed Hennis
2714cebabd Revert "TEMP: Change logging to show progress during unit test"
This reverts commit e184db4ce2.
2025-07-08 16:02:45 -04:00
Ed Hennis
e184db4ce2 TEMP: Change logging to show progress during unit test 2025-07-08 16:02:19 -04:00
Ed Hennis
ac6dc6943c Tweak when the starting range of ledger gap detection is set
- Add a test to exercise online delete ledger gap detection
2025-07-08 16:01:23 -04:00
Ed Hennis
ddd53806df Add a test to exercise LedgerMaster::missingFromCompleteLedgerRange 2025-07-08 13:22:47 -04:00
Ed Hennis
e629a1f70e Merge branch 'develop' into ximinez/online-delete-gaps 2025-07-03 15:51:23 -04:00
Ed Hennis
68076d969c fixup! fixup! Pause online delete if there any any gaps in recent ledger history 2025-07-02 19:05:06 -04:00
Ed Hennis
d3009d3e1c fixup! Pause online delete if there any any gaps in recent ledger history 2025-07-02 18:51:42 -04:00
Ed Hennis
54f7f3c894 Pause online delete if there any any gaps in recent ledger history 2025-07-02 18:45:48 -04:00
354 changed files with 4909 additions and 15192 deletions

View File

@@ -191,14 +191,11 @@ CheckOptions:
readability-identifier-naming.ParameterCase: camelBack
readability-identifier-naming.FunctionCase: camelBack
readability-identifier-naming.MemberCase: camelBack
readability-identifier-naming.PrivateMemberCase: camelBack
readability-identifier-naming.PrivateMemberSuffix: _
readability-identifier-naming.ProtectedMemberCase: camelBack
readability-identifier-naming.ProtectedMemberSuffix: _
readability-identifier-naming.PublicMemberCase: camelBack
readability-identifier-naming.PublicMemberSuffix: ""
readability-identifier-naming.GlobalFunctionIgnoredRegexp: "^(to_string|hash_append|tuple_hash)$"
HeaderFilterRegex: '^.*/(tests?|xrpl|xrpld)/.*\.(h|hpp|ipp)$'
HeaderFilterRegex: '^.*/(test|xrpl|xrpld)/.*\.(h|hpp|ipp)$'
ExcludeHeaderFilterRegex: '^.*/protocol_autogen/.*\.(h|hpp)$'
WarningsAsErrors: "*"

View File

@@ -37,12 +37,12 @@ runs:
run: |
echo 'Installing dependencies.'
conan install \
--profile ci \
--build="${BUILD_OPTION}" \
--options:host='&:tests=True' \
--options:host='&:xrpld=True' \
--settings:all build_type="${BUILD_TYPE}" \
--conf:all tools.build:jobs=${BUILD_NPROC} \
--conf:all tools.build:verbosity="${LOG_VERBOSITY}" \
--conf:all tools.compilation:verbosity="${LOG_VERBOSITY}" \
.
--profile ci \
--build="${BUILD_OPTION}" \
--options:host='&:tests=True' \
--options:host='&:xrpld=True' \
--settings:all build_type="${BUILD_TYPE}" \
--conf:all tools.build:jobs=${BUILD_NPROC} \
--conf:all tools.build:verbosity="${LOG_VERBOSITY}" \
--conf:all tools.compilation:verbosity="${LOG_VERBOSITY}" \
.

View File

@@ -15,7 +15,7 @@ runs:
shell: bash
env:
VERSION: ${{ github.ref_name }}
run: echo "VERSION=${VERSION}" >>"${GITHUB_ENV}"
run: echo "VERSION=${VERSION}" >> "${GITHUB_ENV}"
# When a tag is not pushed, then the version (e.g. 1.2.3-b0) is extracted
# from the BuildInfo.cpp file and the shortened commit hash appended to it.
@@ -28,17 +28,17 @@ runs:
echo 'Extracting version from BuildInfo.cpp.'
VERSION="$(cat src/libxrpl/protocol/BuildInfo.cpp | grep "versionString =" | awk -F '"' '{print $2}')"
if [[ -z "${VERSION}" ]]; then
echo 'Unable to extract version from BuildInfo.cpp.'
exit 1
echo 'Unable to extract version from BuildInfo.cpp.'
exit 1
fi
echo 'Appending shortened commit hash to version.'
SHA='${{ github.sha }}'
VERSION="${VERSION}+${SHA:0:7}"
echo "VERSION=${VERSION}" >>"${GITHUB_ENV}"
echo "VERSION=${VERSION}" >> "${GITHUB_ENV}"
- name: Output version
id: version
shell: bash
run: echo "version=${VERSION}" >>"${GITHUB_OUTPUT}"
run: echo "version=${VERSION}" >> "${GITHUB_OUTPUT}"

View File

@@ -1,403 +0,0 @@
#!/usr/bin/env python3
"""
Format embedded shell snippets using the shfmt hook configured in
.pre-commit-config.yaml.
Two shapes are recognised:
* YAML workflow/action files: literal block-scalar runs (`run: |`) and
single-line runs (`run: some command`). A single-line run is upgraded to
a `run: |` block scalar if shfmt's output spans multiple lines.
* Markdown files: ``` ```bash ``` fenced code blocks.
Any block that shfmt cannot parse is skipped with a warning on stderr, so
the file is left untouched and surrounding blocks still get formatted.
For each occurrence the body is dedented, written to a temp .sh file,
formatted via `pre-commit run shfmt --files <temp>` (falling back to
`prek`), then re-indented and written back in place.
When invoked without arguments, every .yml/.yaml under .github/ plus every
.md file in the repo is scanned. When invoked with file arguments (the
pre-commit case), only those files are processed.
"""
from __future__ import annotations
import re
import shutil
import subprocess
import sys
import tempfile
from dataclasses import dataclass
from pathlib import Path
from typing import Union
REPO = Path(__file__).resolve().parents[2]
_HOOK_RUNNER = next((cmd for cmd in ("pre-commit", "prek") if shutil.which(cmd)), None)
if _HOOK_RUNNER is None:
sys.exit("error: neither `pre-commit` nor `prek` found on PATH")
RUN_BLOCK_RE = re.compile(r"^(?P<prefix>[ \t]*(?:- )?)run:[ \t]*\|[+-]?[ \t]*$")
RUN_INLINE_RE = re.compile(
r"^(?P<prefix>[ \t]*(?:- )?)run:[ \t]+" r"(?P<value>(?!\|[+-]?[ \t]*$)\S.*?)[ \t]*$"
)
MD_BASH_OPEN_RE = re.compile(r"^(?P<indent>[ ]{0,3})`{3}bash[ \t]*$")
MD_FENCE_CLOSE_RE = re.compile(r"^[ ]{0,3}`{3,}[ \t]*$")
@dataclass(frozen=True)
class BlockRun:
"""A `run: |` block scalar; `body_start:body_end` slices into `lines`."""
body_start: int
body_end: int
body_indent: int
@dataclass(frozen=True)
class InlineRun:
"""A single-line `run: value` at `line_idx`."""
line_idx: int
prefix: str
value: str
@dataclass(frozen=True)
class MdBashBlock:
"""A markdown ``` ```bash ``` fenced code block.
`body_start:body_end` slices into the file's lines; `open_line_idx`
points at the opening fence line.
"""
open_line_idx: int
body_start: int
body_end: int
body_indent: int
RunItem = Union[BlockRun, InlineRun]
def _scan_block_body(
lines: list[str], body_start: int, run_col: int
) -> tuple[int | None, int]:
"""Locate the body of a `run: |` block scalar starting at `body_start`.
Returns `(body_indent, scan_end)`. `scan_end` is the line index where the
outer scanner should resume. `body_indent` is `None` when no body is
present (the scalar is empty, or the next non-blank line has indent
`<= run_col`).
"""
body_indent: int | None = None
scan_end = len(lines)
for idx in range(body_start, len(lines)):
line = lines[idx]
if line.strip() == "":
continue
indent = len(line) - len(line.lstrip(" "))
if body_indent is None:
if indent > run_col:
body_indent = indent
else:
scan_end = idx
break
elif indent < body_indent:
scan_end = idx
break
if body_indent is not None:
while scan_end > body_start and lines[scan_end - 1].strip() == "":
scan_end -= 1
if scan_end <= body_start:
body_indent = None
return body_indent, scan_end
def find_run_blocks(lines: list[str]) -> list[RunItem]:
"""Return run items in document order."""
items: list[RunItem] = []
line_idx = 0
while line_idx < len(lines):
line = lines[line_idx]
if block_match := RUN_BLOCK_RE.match(line):
run_col = len(block_match.group("prefix"))
body_start = line_idx + 1
body_indent, scan_end = _scan_block_body(lines, body_start, run_col)
if body_indent is not None:
items.append(
BlockRun(
body_start=body_start,
body_end=scan_end,
body_indent=body_indent,
)
)
line_idx = scan_end
continue
if inline_match := RUN_INLINE_RE.match(line):
items.append(
InlineRun(
line_idx=line_idx,
prefix=inline_match.group("prefix"),
value=inline_match.group("value"),
)
)
line_idx += 1
return items
def find_md_bash_blocks(lines: list[str]) -> list[MdBashBlock]:
"""Return ``` ```bash ``` fenced code blocks in document order."""
blocks: list[MdBashBlock] = []
line_idx = 0
while line_idx < len(lines):
open_match = MD_BASH_OPEN_RE.match(lines[line_idx])
if not open_match:
line_idx += 1
continue
body_start = line_idx + 1
close_idx = next(
(
j
for j in range(body_start, len(lines))
if MD_FENCE_CLOSE_RE.match(lines[j])
),
None,
)
if close_idx is None:
line_idx = body_start
continue
body = lines[body_start:close_idx]
non_blank = [b for b in body if b.strip()]
body_indent = (
min(len(b) - len(b.lstrip(" ")) for b in non_blank)
if non_blank
else len(open_match.group("indent"))
)
blocks.append(
MdBashBlock(
open_line_idx=line_idx,
body_start=body_start,
body_end=close_idx,
body_indent=body_indent,
)
)
line_idx = close_idx + 1
return blocks
def dedent(lines: list[str], n: int) -> list[str]:
pad = " " * n
return [
(
""
if line.strip() == ""
else (line[n:] if line.startswith(pad) else line.lstrip(" "))
)
for line in lines
]
def reindent(lines: list[str], n: int) -> list[str]:
pad = " " * n
return [pad + line if line else "" for line in lines]
_SHFMT_ERR_RE = re.compile(r"\.sh:\d+:\d+:\s")
_GHA_EXPR_RE = re.compile(r"\$\{\{.*?\}\}", re.DOTALL)
_GHA_PLACEHOLDER_RE = re.compile(r"__GHA_EXPR_(\d+)__")
def _encode_gha_exprs(text: str) -> tuple[str, list[str]]:
"""Replace `${{ ... }}` expressions with bash-safe placeholder identifiers."""
exprs: list[str] = []
def repl(match: re.Match[str]) -> str:
exprs.append(match.group(0))
return f"__GHA_EXPR_{len(exprs) - 1}__"
return _GHA_EXPR_RE.sub(repl, text), exprs
def _decode_gha_exprs(text: str, exprs: list[str]) -> str:
"""Restore `${{ ... }}` expressions from placeholder identifiers."""
return _GHA_PLACEHOLDER_RE.sub(lambda m: exprs[int(m.group(1))], text)
def shfmt_via_hook(tmp_path: Path) -> tuple[bool, str]:
# `${{ ... }}` is not valid shell, so swap it for a placeholder identifier
# that shfmt can parse, then restore it after formatting.
encoded, exprs = _encode_gha_exprs(tmp_path.read_text())
if exprs:
tmp_path.write_text(encoded)
res = subprocess.run(
[_HOOK_RUNNER, "run", "shfmt", "--files", str(tmp_path)],
cwd=REPO,
capture_output=True,
text=True,
)
output = res.stdout + res.stderr
# shfmt emits parse errors as "<path>:<line>:<col>: <message>".
parse_err = bool(_SHFMT_ERR_RE.search(output))
# A non-zero exit that is neither a parse error nor pre-commit's "I had
# to modify files" signal means the hook itself failed to run (missing
# binary, install failure, bad config, ...). Surface that loudly rather
# than silently treating it as a no-op.
if (
res.returncode != 0
and not parse_err
and "files were modified by this hook" not in output
):
sys.exit(
f"error: `{_HOOK_RUNNER} run shfmt` failed with exit {res.returncode}:\n{output}"
)
if exprs and not parse_err:
tmp_path.write_text(_decode_gha_exprs(tmp_path.read_text(), exprs))
return not parse_err, output
def _skip(path: Path, where: int, kind: str, output: str) -> None:
print(
f" shfmt could not parse {kind} at {path}:{where + 1} — skipped",
file=sys.stderr,
)
print(f" {output.strip()}", file=sys.stderr)
def process_yaml_file(path: Path, tmp_path: Path) -> int:
text = path.read_text()
had_nl = text.endswith("\n")
lines = text.split("\n")
if had_nl:
lines = lines[:-1]
items = find_run_blocks(lines)
if not items:
return 0
changed = 0
# Process in reverse so earlier indices remain valid as we splice.
for item in reversed(items):
if isinstance(item, BlockRun):
body = lines[item.body_start : item.body_end]
tmp_path.write_text("\n".join(dedent(body, item.body_indent)) + "\n")
ok, output = shfmt_via_hook(tmp_path)
if not ok:
_skip(path, item.body_start, "block", output)
continue
formatted = tmp_path.read_text().rstrip("\n")
new_body = reindent(formatted.split("\n"), item.body_indent)
if new_body != body:
lines[item.body_start : item.body_end] = new_body
changed += 1
else:
tmp_path.write_text(item.value + "\n")
ok, output = shfmt_via_hook(tmp_path)
if not ok:
_skip(path, item.line_idx, "inline run", output)
continue
formatted = tmp_path.read_text().rstrip("\n")
if formatted == item.value:
continue
formatted_lines = formatted.split("\n")
if len(formatted_lines) == 1:
lines[item.line_idx] = f"{item.prefix}run: {formatted}"
else:
body_indent = len(item.prefix) + 2
lines[item.line_idx : item.line_idx + 1] = [
f"{item.prefix}run: |",
*reindent(formatted_lines, body_indent),
]
changed += 1
new_text = "\n".join(lines) + ("\n" if had_nl else "")
if new_text != text:
path.write_text(new_text)
return changed
def process_md_file(path: Path, tmp_path: Path) -> int:
text = path.read_text()
had_nl = text.endswith("\n")
lines = text.split("\n")
if had_nl:
lines = lines[:-1]
blocks = find_md_bash_blocks(lines)
if not blocks:
return 0
changed = 0
for block in reversed(blocks):
body = lines[block.body_start : block.body_end]
tmp_path.write_text("\n".join(dedent(body, block.body_indent)) + "\n")
ok, output = shfmt_via_hook(tmp_path)
if not ok:
_skip(path, block.open_line_idx, "```bash block", output)
continue
formatted = tmp_path.read_text().rstrip("\n")
formatted_lines = formatted.split("\n") if formatted else []
new_body = reindent(formatted_lines, block.body_indent)
if new_body != body:
lines[block.body_start : block.body_end] = new_body
changed += 1
new_text = "\n".join(lines) + ("\n" if had_nl else "")
if new_text != text:
path.write_text(new_text)
return changed
def process_file(path: Path, tmp_path: Path) -> int:
if path.suffix in (".yml", ".yaml"):
return process_yaml_file(path, tmp_path)
if path.suffix == ".md":
return process_md_file(path, tmp_path)
return 0
def gather_files(argv: list[str]) -> list[Path]:
"""Return YAML workflow/action files and markdown files that we should
process — either the paths in `argv` or, when `argv` is empty, every
such file in the repo (skipping `external/`)."""
if argv:
candidates: list[Path] = [
(REPO / a).resolve() if not Path(a).is_absolute() else Path(a) for a in argv
]
else:
gh = REPO / ".github"
candidates = [
*gh.rglob("*.yml"),
*gh.rglob("*.yaml"),
*(
p
for p in REPO.rglob("*.md")
if "external" not in p.relative_to(REPO).parts
),
]
return sorted(
p
for p in candidates
if p.exists()
and (
(p.suffix in (".yml", ".yaml") and ".github" in p.parts)
or p.suffix == ".md"
)
)
def main(argv: list[str]) -> int:
files = gather_files(argv)
if not files:
return 0
with tempfile.TemporaryDirectory(prefix="format-inline-bash-") as tmpdir:
tmp_path = Path(tmpdir) / "shfmt.sh"
total = 0
for f in files:
n = process_file(f, tmp_path)
if n:
print(f"{f.relative_to(REPO)}: reformatted {n} block(s)")
total += n
return 1 if total else 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))

0
.github/scripts/levelization/generate.py vendored Executable file → Normal file
View File

View File

@@ -6,7 +6,7 @@ set -e
# On MacOS, ensure that GNU sed is installed and available as `gsed`.
SED_COMMAND=sed
if [[ "${OSTYPE}" == 'darwin'* ]]; then
if ! command -v gsed &>/dev/null; then
if ! command -v gsed &> /dev/null; then
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
exit 1
fi

View File

@@ -8,12 +8,12 @@ set -e
SED_COMMAND=sed
HEAD_COMMAND=head
if [[ "${OSTYPE}" == 'darwin'* ]]; then
if ! command -v gsed &>/dev/null; then
if ! command -v gsed &> /dev/null; then
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
exit 1
fi
SED_COMMAND=gsed
if ! command -v ghead &>/dev/null; then
if ! command -v ghead &> /dev/null; then
echo "Error: ghead is not installed. Please install it using 'brew install coreutils'."
exit 1
fi
@@ -74,10 +74,10 @@ if grep -q '"xrpld"' cmake/XrplCore.cmake; then
# The script has been rerun, so just restore the name of the binary.
${SED_COMMAND} -i 's/"xrpld"/"rippled"/' cmake/XrplCore.cmake
elif ! grep -q '"rippled"' cmake/XrplCore.cmake; then
${HEAD_COMMAND} -n -1 cmake/XrplCore.cmake >cmake.tmp
echo ' # For the time being, we will keep the name of the binary as it was.' >>cmake.tmp
echo ' set_target_properties(xrpld PROPERTIES OUTPUT_NAME "rippled")' >>cmake.tmp
tail -1 cmake/XrplCore.cmake >>cmake.tmp
${HEAD_COMMAND} -n -1 cmake/XrplCore.cmake > cmake.tmp
echo ' # For the time being, we will keep the name of the binary as it was.' >> cmake.tmp
echo ' set_target_properties(xrpld PROPERTIES OUTPUT_NAME "rippled")' >> cmake.tmp
tail -1 cmake/XrplCore.cmake >> cmake.tmp
mv cmake.tmp cmake/XrplCore.cmake
fi

View File

@@ -6,7 +6,7 @@ set -e
# On MacOS, ensure that GNU sed is installed and available as `gsed`.
SED_COMMAND=sed
if [[ "${OSTYPE}" == 'darwin'* ]]; then
if ! command -v gsed &>/dev/null; then
if ! command -v gsed &> /dev/null; then
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
exit 1
fi

View File

@@ -6,7 +6,7 @@ set -e
# On MacOS, ensure that GNU sed is installed and available as `gsed`.
SED_COMMAND=sed
if [[ "${OSTYPE}" == 'darwin'* ]]; then
if ! command -v gsed &>/dev/null; then
if ! command -v gsed &> /dev/null; then
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
exit 1
fi
@@ -62,37 +62,37 @@ done
# restoring the verbiage that is already present in LICENSE.md. Ensure that if
# the script is run multiple times, duplicate notices are not added.
if ! grep -q 'Raw Material Software' include/xrpl/beast/core/CurrentThreadName.h; then
echo -e "// Portions of this file are from JUCE (http://www.juce.com).\n// Copyright (c) 2013 - Raw Material Software Ltd.\n// Please visit http://www.juce.com\n\n$(cat include/xrpl/beast/core/CurrentThreadName.h)" >include/xrpl/beast/core/CurrentThreadName.h
echo -e "// Portions of this file are from JUCE (http://www.juce.com).\n// Copyright (c) 2013 - Raw Material Software Ltd.\n// Please visit http://www.juce.com\n\n$(cat include/xrpl/beast/core/CurrentThreadName.h)" > include/xrpl/beast/core/CurrentThreadName.h
fi
if ! grep -q 'Dev Null' src/test/app/NetworkID_test.cpp; then
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/app/NetworkID_test.cpp)" >src/test/app/NetworkID_test.cpp
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/app/NetworkID_test.cpp)" > src/test/app/NetworkID_test.cpp
fi
if ! grep -q 'Dev Null' src/test/app/tx/apply_test.cpp; then
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/app/tx/apply_test.cpp)" >src/test/app/tx/apply_test.cpp
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/app/tx/apply_test.cpp)" > src/test/app/tx/apply_test.cpp
fi
if ! grep -q 'Dev Null' src/test/rpc/ManifestRPC_test.cpp; then
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/rpc/ManifestRPC_test.cpp)" >src/test/rpc/ManifestRPC_test.cpp
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/rpc/ManifestRPC_test.cpp)" > src/test/rpc/ManifestRPC_test.cpp
fi
if ! grep -q 'Dev Null' src/test/rpc/ValidatorInfo_test.cpp; then
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/rpc/ValidatorInfo_test.cpp)" >src/test/rpc/ValidatorInfo_test.cpp
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/rpc/ValidatorInfo_test.cpp)" > src/test/rpc/ValidatorInfo_test.cpp
fi
if ! grep -q 'Dev Null' src/xrpld/rpc/handlers/server_info/Manifest.cpp; then
echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/server_info/Manifest.cpp)" >src/xrpld/rpc/handlers/server_info/Manifest.cpp
echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/server_info/Manifest.cpp)" > src/xrpld/rpc/handlers/server_info/Manifest.cpp
fi
if ! grep -q 'Dev Null' src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp; then
echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp)" >src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp
echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp)" > src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp
fi
if ! grep -q 'Bougalis' include/xrpl/basics/SlabAllocator.h; then
echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/SlabAllocator.h)" >include/xrpl/basics/SlabAllocator.h # cspell: ignore Nikolaos Bougalis nikb
echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/SlabAllocator.h)" > include/xrpl/basics/SlabAllocator.h # cspell: ignore Nikolaos Bougalis nikb
fi
if ! grep -q 'Bougalis' include/xrpl/basics/spinlock.h; then
echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/spinlock.h)" >include/xrpl/basics/spinlock.h # cspell: ignore Nikolaos Bougalis nikb
echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/spinlock.h)" > include/xrpl/basics/spinlock.h # cspell: ignore Nikolaos Bougalis nikb
fi
if ! grep -q 'Bougalis' include/xrpl/basics/tagged_integer.h; then
echo -e "// Copyright (c) 2014, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/tagged_integer.h)" >include/xrpl/basics/tagged_integer.h # cspell: ignore Nikolaos Bougalis nikb
echo -e "// Copyright (c) 2014, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/tagged_integer.h)" > include/xrpl/basics/tagged_integer.h # cspell: ignore Nikolaos Bougalis nikb
fi
if ! grep -q 'Ritchford' include/xrpl/beast/utility/Zero.h; then
echo -e "// Copyright (c) 2014, Tom Ritchford <tom@swirly.com>\n\n$(cat include/xrpl/beast/utility/Zero.h)" >include/xrpl/beast/utility/Zero.h # cspell: ignore Ritchford
echo -e "// Copyright (c) 2014, Tom Ritchford <tom@swirly.com>\n\n$(cat include/xrpl/beast/utility/Zero.h)" > include/xrpl/beast/utility/Zero.h # cspell: ignore Ritchford
fi
# Restore newlines and tabs in string literals in the affected file.

View File

@@ -6,7 +6,7 @@ set -e
# On MacOS, ensure that GNU sed is installed and available as `gsed`.
SED_COMMAND=sed
if [[ "${OSTYPE}" == 'darwin'* ]]; then
if ! command -v gsed &>/dev/null; then
if ! command -v gsed &> /dev/null; then
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
exit 1
fi

View File

@@ -6,7 +6,7 @@ set -e
# On MacOS, ensure that GNU sed is installed and available as `gsed`.
SED_COMMAND=sed
if [[ "${OSTYPE}" == 'darwin'* ]]; then
if ! command -v gsed &>/dev/null; then
if ! command -v gsed &> /dev/null; then
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
exit 1
fi

View File

@@ -6,7 +6,7 @@ set -e
# On MacOS, ensure that GNU sed is installed and available as `gsed`.
SED_COMMAND=sed
if [[ "${OSTYPE}" == 'darwin'* ]]; then
if ! command -v gsed &>/dev/null; then
if ! command -v gsed &> /dev/null; then
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
exit 1
fi

View File

@@ -6,16 +6,14 @@ on:
- develop
paths:
- ".github/workflows/build-nix-image.yml"
- ".github/workflows/reusable-build-docker-image.yml"
- "docker/**"
- "docker/nix.Dockerfile"
- "flake.nix"
- "flake.lock"
- "nix/**"
pull_request:
paths:
- ".github/workflows/build-nix-image.yml"
- ".github/workflows/reusable-build-docker-image.yml"
- "docker/**"
- "docker/nix.Dockerfile"
- "flake.nix"
- "flake.lock"
- "nix/**"
@@ -29,81 +27,75 @@ defaults:
run:
shell: bash
env:
UBUNTU_VERSION: "20.04"
RHEL_VERSION: "9"
DEBIAN_VERSION: "bookworm"
jobs:
build:
name: Build ${{ matrix.distro.name }} (${{ matrix.target.platform }})
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
# The base images are the oldest supported version of each distro
# that we want to build images for.
distro:
- name: nixos
base_image: nixos/nix:latest
- name: ubuntu
base_image: ubuntu:20.04
- name: rhel
base_image: registry.access.redhat.com/ubi9/ubi:latest
- name: debian
base_image: debian:bookworm
target:
- platform: linux/amd64
runner: ubuntu-latest
- platform: linux/arm64
runner: ubuntu-24.04-arm
uses: ./.github/workflows/reusable-build-docker-image.yml
with:
image_name: ghcr.io/xrplf/xrpld/nix-${{ matrix.distro.name }}
dockerfile: docker/nix.Dockerfile
base_image: ${{ matrix.distro.base_image }}
platform: ${{ matrix.target.platform }}
runner: ${{ matrix.target.runner }}
push: ${{ github.repository == 'XRPLF/rippled' && github.event_name == 'push' }}
merge:
name: Merge ${{ matrix.distro }} manifest
needs: build
if: ${{ github.repository == 'XRPLF/rippled' && github.event_name == 'push' }}
name: Build and push Nix image (${{ matrix.distro }})
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
distro: [nixos, ubuntu, rhel, debian]
env:
IMAGE_NAME: ghcr.io/xrplf/xrpld/nix-${{ matrix.distro }}
include:
- distro: nixos
- distro: ubuntu
- distro: rhel
- distro: debian
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Docker metadata
id: meta
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
with:
images: ${{ env.IMAGE_NAME }}
tags: |
type=sha,prefix=sha-,format=short
type=raw,value=latest
- name: Determine base image
id: vars
run: |
case "${{ matrix.distro }}" in
nixos)
echo "base_image=nixos/nix:latest" >> $GITHUB_OUTPUT
;;
ubuntu)
echo "base_image=ubuntu:${UBUNTU_VERSION}" >> $GITHUB_OUTPUT
;;
rhel)
echo "base_image=registry.access.redhat.com/ubi${RHEL_VERSION}/ubi:latest" >> $GITHUB_OUTPUT
;;
debian)
echo "base_image=debian:${DEBIAN_VERSION}" >> $GITHUB_OUTPUT
;;
esac
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Login to GitHub Container Registry
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
if: github.event_name == 'push'
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create multi-arch manifests
run: |
for tag in $(jq -cr '.tags[]' <<<"$DOCKER_METADATA_OUTPUT_JSON"); do
docker buildx imagetools create -t "$tag" "${tag}-amd64" "${tag}-arm64"
done
- name: Docker metadata
id: meta
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
with:
images: ghcr.io/xrplf/ci/nix-${{ matrix.distro }}
tags: |
type=sha,prefix=sha-,format=short
type=raw,value=latest
- name: Inspect image
run: |
docker buildx imagetools inspect "${IMAGE_NAME}:${{ steps.meta.outputs.version }}"
- name: Build and push
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
with:
context: .
file: docker/nix.Dockerfile
platforms: linux/amd64
push: ${{ github.event_name == 'push' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: BASE_IMAGE=${{ steps.vars.outputs.base_image }}

View File

@@ -5,17 +5,8 @@ on:
types:
- checks_requested
pull_request:
types:
- opened
- edited
- reopened
- synchronize
- ready_for_review
branches:
- develop
- "release-*"
- "release/*"
- "staging/*"
types: [opened, edited, reopened, synchronize, ready_for_review]
branches: [develop]
jobs:
check_description:
@@ -29,11 +20,11 @@ jobs:
env:
PR_BODY: ${{ github.event.pull_request.body }}
if: ${{ github.event_name == 'pull_request' }}
run: printenv PR_BODY >pr_body.md
run: printenv PR_BODY > pr_body.md
- name: Check PR description differs from template
if: ${{ github.event_name == 'pull_request' }}
run: |
python .github/scripts/check-pr-description.py \
--template-file .github/pull_request_template.md \
--pr-body-file pr_body.md
run: >
python .github/scripts/check-pr-description.py
--template-file .github/pull_request_template.md
--pr-body-file pr_body.md

View File

@@ -5,19 +5,10 @@ on:
types:
- checks_requested
pull_request:
types:
- opened
- edited
- reopened
- synchronize
- ready_for_review
branches:
- develop
- "release-*"
- "release/*"
- "staging/*"
types: [opened, edited, reopened, synchronize, ready_for_review]
branches: [develop]
jobs:
check_title:
if: ${{ github.event.pull_request.draft != true }}
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@cba1f0891650baf1a9c88624dc2d72573be2eb81
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@291206777251b4d493641b5afbdf7c23009d2988

View File

@@ -98,7 +98,7 @@ jobs:
READY: ${{ contains(github.event.pull_request.labels.*.name, 'Ready to merge') }}
MERGE: ${{ github.event_name == 'merge_group' }}
run: |
echo "go=${{ (env.DRAFT != 'true' && env.READY == 'true') || env.FILES == 'true' || env.MERGE == 'true' }}" >>"${GITHUB_OUTPUT}"
echo "go=${{ (env.DRAFT != 'true' && env.READY == 'true') || env.FILES == 'true' || env.MERGE == 'true' }}" >> "${GITHUB_OUTPUT}"
cat "${GITHUB_OUTPUT}"
outputs:
go: ${{ steps.go.outputs.go == 'true' }}
@@ -168,9 +168,9 @@ jobs:
PR_URL: ${{ github.event.pull_request.html_url }}
run: |
gh api --method POST -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" \
/repos/xrplf/clio/dispatches -f "event_type=check_libxrpl" \
-F "client_payload[ref]=${{ needs.upload-recipe.outputs.recipe_ref }}" \
-F "client_payload[pr_url]=${PR_URL}"
/repos/xrplf/clio/dispatches -f "event_type=check_libxrpl" \
-F "client_payload[ref]=${{ needs.upload-recipe.outputs.recipe_ref }}" \
-F "client_payload[pr_url]=${PR_URL}"
passed:
if: failure() || cancelled()

View File

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

View File

@@ -1,89 +0,0 @@
# Build a single-platform Docker image. On push, the image is pushed to
# GHCR with arch-suffixed tags (e.g. `:latest-amd64`, `:sha-abc-amd64`)
# so the calling workflow can stitch per-arch builds into a multi-arch
# manifest without needing to pass digests around.
name: Reusable build Docker image (single platform)
on:
workflow_call:
inputs:
image_name:
description: "Full image name without tag (e.g. 'ghcr.io/xrplf/xrpld/nix-ubuntu')"
required: true
type: string
dockerfile:
description: "Path to the Dockerfile, relative to the repository root"
required: true
type: string
base_image:
description: "Value passed to the Dockerfile as the BASE_IMAGE build arg"
required: true
type: string
platform:
description: "Docker platform string, e.g. linux/amd64"
required: true
type: string
runner:
description: "GitHub Actions runner label to build on"
required: true
type: string
push:
description: "Whether to push the image to GHCR"
required: true
type: boolean
defaults:
run:
shell: bash
jobs:
build:
name: Build (${{ inputs.platform }})
runs-on: ${{ inputs.runner }}
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Determine arch
id: vars
env:
PLATFORM: ${{ inputs.platform }}
run: |
echo "arch=${PLATFORM##*/}" >>$GITHUB_OUTPUT
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Login to GitHub Container Registry
if: inputs.push
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker metadata
id: meta
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
with:
images: ${{ inputs.image_name }}
tags: |
type=sha,prefix=sha-,format=short
type=raw,value=latest
flavor: |
suffix=-${{ steps.vars.outputs.arch }},onlatest=true
- name: Build and push
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
file: ${{ inputs.dockerfile }}
platforms: ${{ inputs.platform }}
push: ${{ inputs.push }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: BASE_IMAGE=${{ inputs.base_image }}

View File

@@ -113,7 +113,7 @@ jobs:
- name: Set ccache log file
if: ${{ inputs.ccache_enabled && runner.debug == '1' }}
run: echo "CCACHE_LOGFILE=${{ runner.temp }}/ccache.log" >>"${GITHUB_ENV}"
run: echo "CCACHE_LOGFILE=${{ runner.temp }}/ccache.log" >> "${GITHUB_ENV}"
- name: Print build environment
uses: XRPLF/actions/print-build-env@59dec886e4afb05a1724443af08baccbc045b574
@@ -146,11 +146,11 @@ jobs:
CMAKE_ARGS: ${{ inputs.cmake_args }}
run: |
cmake \
-G '${{ runner.os == 'Windows' && 'Visual Studio 17 2022' || 'Ninja' }}' \
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
${CMAKE_ARGS} \
..
-G '${{ runner.os == 'Windows' && 'Visual Studio 17 2022' || 'Ninja' }}' \
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
${CMAKE_ARGS} \
..
- name: Check protocol autogen files are up-to-date
working-directory: ${{ env.BUILD_DIR }}
@@ -172,32 +172,32 @@ jobs:
cmake --build . --target code_gen
DIFF=$(git -C .. status --porcelain -- include/xrpl/protocol_autogen src/tests/libxrpl/protocol_autogen)
if [ -n "${DIFF}" ]; then
echo "::error::Generated protocol files are out of date"
git -C .. diff -- include/xrpl/protocol_autogen src/tests/libxrpl/protocol_autogen
echo "${MESSAGE}"
exit 1
echo "::error::Generated protocol files are out of date"
git -C .. diff -- include/xrpl/protocol_autogen src/tests/libxrpl/protocol_autogen
echo "${MESSAGE}"
exit 1
fi
- name: Build the binary
working-directory: ${{ env.BUILD_DIR }}
env:
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
BUILD_NPROC: ${{ runner.os == 'Linux' && '16' || steps.nproc.outputs.nproc }}
BUILD_TYPE: ${{ inputs.build_type }}
CMAKE_TARGET: ${{ inputs.cmake_target }}
run: |
cmake \
--build . \
--config "${BUILD_TYPE}" \
--parallel "${BUILD_NPROC}" \
--target "${CMAKE_TARGET}"
--build . \
--config "${BUILD_TYPE}" \
--parallel "${BUILD_NPROC}" \
--target "${CMAKE_TARGET}"
- name: Show ccache statistics
if: ${{ inputs.ccache_enabled }}
run: |
ccache --show-stats -vv
if [ '${{ runner.debug }}' = '1' ]; then
cat "${CCACHE_LOGFILE}"
curl ${CCACHE_REMOTE_STORAGE%|*}/status || true
cat "${CCACHE_LOGFILE}"
curl ${CCACHE_REMOTE_STORAGE%|*}/status || true
fi
- name: Upload the binary (Linux)
@@ -214,7 +214,7 @@ jobs:
working-directory: ${{ env.BUILD_DIR }}
run: |
set -o pipefail
./xrpld --definitions | python3 -m json.tool >server_definitions.json
./xrpld --definitions | python3 -m json.tool > server_definitions.json
- name: Upload server definitions
if: ${{ github.event.repository.visibility == 'public' && inputs.config_name == 'debian-bookworm-gcc-13-amd64-release' }}
@@ -231,10 +231,10 @@ jobs:
run: |
ldd ./xrpld
if [ "$(ldd ./xrpld | grep -E '(libstdc\+\+|libgcc)' | wc -l)" -eq 0 ]; then
echo 'The binary is statically linked.'
echo 'The binary is statically linked.'
else
echo 'The binary is dynamically linked.'
exit 1
echo 'The binary is dynamically linked.'
exit 1
fi
- name: Verify presence of instrumentation (Linux)
@@ -250,12 +250,12 @@ jobs:
run: |
ASAN_OPTS="include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-asan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/asan.supp"
if [[ "${CONFIG_NAME}" == *gcc* ]]; then
ASAN_OPTS="${ASAN_OPTS}:alloc_dealloc_mismatch=0"
ASAN_OPTS="${ASAN_OPTS}:alloc_dealloc_mismatch=0"
fi
echo "ASAN_OPTIONS=${ASAN_OPTS}" >>${GITHUB_ENV}
echo "TSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-tsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/tsan.supp" >>${GITHUB_ENV}
echo "UBSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-ubsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/ubsan.supp" >>${GITHUB_ENV}
echo "LSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-lsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/lsan.supp" >>${GITHUB_ENV}
echo "ASAN_OPTIONS=${ASAN_OPTS}" >> ${GITHUB_ENV}
echo "TSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-tsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/tsan.supp" >> ${GITHUB_ENV}
echo "UBSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-ubsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/ubsan.supp" >> ${GITHUB_ENV}
echo "LSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-lsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/lsan.supp" >> ${GITHUB_ENV}
- name: Run the separate tests
if: ${{ !inputs.build_only }}
@@ -266,9 +266,9 @@ jobs:
PARALLELISM: ${{ runner.os == 'Windows' && '1' || steps.nproc.outputs.nproc }}
run: |
ctest \
--output-on-failure \
-C "${BUILD_TYPE}" \
-j "${PARALLELISM}"
--output-on-failure \
-C "${BUILD_TYPE}" \
-j "${PARALLELISM}"
- name: Run the embedded tests
if: ${{ !inputs.build_only }}
@@ -278,7 +278,7 @@ jobs:
run: |
set -o pipefail
# Coverage builds are slower due to instrumentation; use fewer parallel jobs to avoid flakiness
[ "$COVERAGE_ENABLED" = "true" ] && BUILD_NPROC=$((BUILD_NPROC - 2))
[ "$COVERAGE_ENABLED" = "true" ] && BUILD_NPROC=$(( BUILD_NPROC - 2 ))
./xrpld --unittest --unittest-jobs "${BUILD_NPROC}" 2>&1 | tee unittest.log
- name: Show test failure summary
@@ -287,19 +287,19 @@ jobs:
WORKING_DIR: ${{ runner.os == 'Windows' && format('{0}\{1}', env.BUILD_DIR, inputs.build_type) || env.BUILD_DIR }}
run: |
if [ ! -d "${WORKING_DIR}" ]; then
echo "Working directory '${WORKING_DIR}' does not exist."
exit 0
echo "Working directory '${WORKING_DIR}' does not exist."
exit 0
fi
cd "${WORKING_DIR}"
if [ ! -f unittest.log ]; then
echo "unittest.log not found; embedded tests may not have run."
exit 0
echo "unittest.log not found; embedded tests may not have run."
exit 0
fi
if ! grep -E "failed" unittest.log; then
echo "Log present but no failure lines found in unittest.log."
echo "Log present but no failure lines found in unittest.log."
fi
- name: Debug failure (Linux)
if: ${{ failure() && runner.os == 'Linux' && !inputs.build_only }}
@@ -317,14 +317,14 @@ jobs:
BUILD_TYPE: ${{ inputs.build_type }}
run: |
cmake \
--build . \
--config "${BUILD_TYPE}" \
--parallel "${BUILD_NPROC}" \
--target coverage
--build . \
--config "${BUILD_TYPE}" \
--parallel "${BUILD_NPROC}" \
--target coverage
- name: Upload coverage report
if: ${{ github.repository == 'XRPLF/rippled' && !inputs.build_only && env.COVERAGE_ENABLED == 'true' }}
uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
with:
disable_search: true
disable_telem: true

View File

@@ -38,9 +38,9 @@ jobs:
run: |
DIFF=$(git status --porcelain)
if [ -n "${DIFF}" ]; then
# Print the differences to give the contributor a hint about what to
# expect when running levelization on their own machine.
git diff
echo "${MESSAGE}"
exit 1
# Print the differences to give the contributor a hint about what to
# expect when running levelization on their own machine.
git diff
echo "${MESSAGE}"
exit 1
fi

View File

@@ -48,9 +48,9 @@ jobs:
run: |
DIFF=$(git status --porcelain)
if [ -n "${DIFF}" ]; then
# Print the differences to give the contributor a hint about what to
# expect when running the renaming scripts on their own machine.
git diff
echo "${MESSAGE}"
exit 1
# Print the differences to give the contributor a hint about what to
# expect when running the renaming scripts on their own machine.
git diff
echo "${MESSAGE}"
exit 1
fi

View File

@@ -70,13 +70,13 @@ jobs:
working-directory: ${{ env.BUILD_DIR }}
run: |
cmake \
-G 'Ninja' \
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
-Dtests=ON \
-Dwerr=ON \
-Dxrpld=ON \
..
-G 'Ninja' \
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
-Dtests=ON \
-Dwerr=ON \
-Dxrpld=ON \
..
# clang-tidy needs headers generated from proto files
- name: Build libxrpl.libpb
@@ -133,7 +133,7 @@ jobs:
- name: Write issue header
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: |
cat >"${ISSUE_FILE}" <<EOF
cat > "${ISSUE_FILE}" <<EOF
## Clang-tidy Check Failed
### Clang-tidy Output:
@@ -144,30 +144,30 @@ jobs:
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: |
if [ -f "${OUTPUT_FILE}" ]; then
# Extract lines containing 'error:', 'warning:', or 'note:'
grep -E '(error:|warning:|note:)' "${OUTPUT_FILE}" >filtered-output.txt || true
# Extract lines containing 'error:', 'warning:', or 'note:'
grep -E '(error:|warning:|note:)' "${OUTPUT_FILE}" > filtered-output.txt || true
# If filtered output is empty, use original (might be a different error format)
if [ ! -s filtered-output.txt ]; then
cp "${OUTPUT_FILE}" filtered-output.txt
fi
# If filtered output is empty, use original (might be a different error format)
if [ ! -s filtered-output.txt ]; then
cp "${OUTPUT_FILE}" filtered-output.txt
fi
# Truncate if too large
head -c 60000 filtered-output.txt >>"${ISSUE_FILE}"
if [ "$(wc -c <filtered-output.txt)" -gt 60000 ]; then
echo "" >>"${ISSUE_FILE}"
echo "... (output truncated, see artifacts for full output)" >>"${ISSUE_FILE}"
fi
# Truncate if too large
head -c 60000 filtered-output.txt >> "${ISSUE_FILE}"
if [ "$(wc -c < filtered-output.txt)" -gt 60000 ]; then
echo "" >> "${ISSUE_FILE}"
echo "... (output truncated, see artifacts for full output)" >> "${ISSUE_FILE}"
fi
rm filtered-output.txt
rm filtered-output.txt
else
echo "No output file found" >>"${ISSUE_FILE}"
echo "No output file found" >> "${ISSUE_FILE}"
fi
- name: Append issue footer
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: |
cat >>"${ISSUE_FILE}" <<EOF
cat >> "${ISSUE_FILE}" <<EOF
\`\`\`
---
@@ -176,7 +176,7 @@ jobs:
- name: Create issue
if: ${{ steps.run_clang_tidy.outcome != 'success' && inputs.create_issue_on_failure }}
uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712
uses: XRPLF/actions/create-issue@36d450d12d301e8410c1b7936e5de70c291cbe36
with:
title: "Clang-tidy check failed"
body_file: ${{ env.ISSUE_FILE }}

View File

@@ -39,7 +39,7 @@ jobs:
id: generate
working-directory: .github/scripts/strategy-matrix
run: |
./generate.py --packaging --config=linux.json >>"${GITHUB_OUTPUT}"
./generate.py --packaging --config=linux.json >> "${GITHUB_OUTPUT}"
generate-version:
runs-on: ubuntu-latest

View File

@@ -42,4 +42,4 @@ jobs:
env:
GENERATE_CONFIG: ${{ inputs.os != '' && format('--config={0}.json', inputs.os) || '' }}
GENERATE_OPTION: ${{ inputs.strategy_matrix == 'all' && '--all' || '' }}
run: ./generate.py ${GENERATE_OPTION} ${GENERATE_CONFIG} >>"${GITHUB_OUTPUT}"
run: ./generate.py ${GENERATE_OPTION} ${GENERATE_CONFIG} >> "${GITHUB_OUTPUT}"

View File

@@ -37,50 +37,37 @@ repos:
exclude: ^include/xrpl/protocol_autogen/(transactions|ledger_entries)/
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: dd18dad857d6133e90bbe478f4f2f22ec0030269 # frozen: v22.1.5
rev: cd481d7b0bfb5c7b3090c21846317f9a8262e891 # frozen: v22.1.0
hooks:
- id: clang-format
args: [--style=file]
"types_or": [c++, c, proto]
exclude: ^include/xrpl/protocol_autogen/(transactions|ledger_entries)/
- repo: https://github.com/BlankSpruce/gersemi-pre-commit
rev: faadd6a9d852369ca94f4d15b2404c967ba8cb01 # frozen: 0.27.6
- repo: https://github.com/BlankSpruce/gersemi
rev: 0.26.0
hooks:
- id: gersemi
- repo: https://github.com/rbubley/mirrors-prettier
rev: 515f543f5718ebfd6ce22e16708bb32c68ff96e1 # frozen: v3.8.3
rev: c2bc67fe8f8f549cc489e00ba8b45aa18ee713b1 # frozen: v3.8.1
hooks:
- id: prettier
args: [--end-of-line=auto]
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 4160603246a6b365d4a2af661c6d71b0a0f50478 # frozen: 26.5.1
rev: ea488cebbfd88a5f50b8bd95d5c829d0bb76feb8 # frozen: 26.1.0
hooks:
- id: black
- repo: https://github.com/scop/pre-commit-shfmt
rev: 05c1426671b9237fb5e1444dd63aa5731bec0dfb # frozen: v3.13.1-1
- repo: https://github.com/openstack/bashate
rev: 5798d24d571676fc407e81df574c1ef57b520f23 # frozen: 2.1.1
hooks:
- id: shfmt
args: [--write, --indent=4, --case-indent=true]
- repo: local
hooks:
- id: format-inline-bash-workflows
name: "format `run:` blocks in workflows/actions"
entry: ./.github/scripts/format-inline-bash.py
language: python
files: ^\.github/(workflows|actions)/.*\.ya?ml$
- id: format-inline-bash-markdown
name: "format ```bash blocks in markdown"
entry: ./.github/scripts/format-inline-bash.py
language: python
files: \.md$
- id: bashate
args: ["--ignore=E006"]
- repo: https://github.com/streetsidesoftware/cspell-cli
rev: 4643f154907327ee0a2c7038f0296e0dd77d9776 # frozen: v10.0.0
rev: a42085ade523f591dca134379a595e7859986445 # frozen: v9.7.0
hooks:
- id: cspell # Spell check changed files
exclude: |

View File

@@ -151,8 +151,8 @@ git init
git remote add origin git@github.com:XRPLF/conan-center-index.git
git sparse-checkout init
for recipe in "${recipes[@]}"; do
echo "Checking out recipe '${recipe}'..."
git sparse-checkout add recipes/${recipe}
echo "Checking out recipe '${recipe}'..."
git sparse-checkout add recipes/${recipe}
done
git fetch origin master
git checkout master
@@ -180,7 +180,7 @@ the new recipe will be automatically pulled from the official Conan Center.
If you see an error similar to the following after running `conan profile show`:
```text
```bash
ERROR: Invalid setting '17' is not a valid 'settings.compiler.version' value.
Possible values are ['5.0', '5.1', '6.0', '6.1', '7.0', '7.3', '8.0', '8.1',
'9.0', '9.1', '10.0', '11.0', '12.0', '13', '13.0', '13.1', '14', '14.0', '15',
@@ -427,19 +427,16 @@ install ccache --version 4.11.3 --allow-downgrade`.
Single-config generators:
```
cmake --build . --parallel N
cmake --build .
```
Multi-config generators:
```
cmake --build . --config Release --parallel N
cmake --build . --config Debug --parallel N
cmake --build . --config Release
cmake --build . --config Debug
```
Replace the `--parallel` parameter N with the desired number of parallel jobs. A common starting point is half of the number of available CPU
cores.
5. Test xrpld.
Single-config generators:

View File

@@ -1,8 +1,8 @@
#!/bin/bash
if [[ $# -ne 1 || "$1" == "--help" || "$1" == "-h" ]]; then
name=$(basename $0)
cat <<-USAGE
name=$( basename $0 )
cat <<- USAGE
Usage: $name <username>
Where <username> is the Github username of the upstream repo. e.g. XRPLF
@@ -14,7 +14,7 @@ fi
shift
user="$1"
# Get the origin URL. Expect it be an SSH-style URL
origin=$(git remote get-url origin)
origin=$( git remote get-url origin )
if [[ "${origin}" == "" ]]; then
echo Invalid origin remote >&2
exit 1
@@ -22,11 +22,11 @@ fi
# echo "Origin: ${origin}"
# Parse the origin
ifs_orig="${IFS}"
IFS=':' read remote originpath <<<"${origin}"
IFS=':' read remote originpath <<< "${origin}"
# echo "Remote: ${remote}, Originpath: ${originpath}"
IFS='@' read sshuser server <<<"${remote}"
IFS='@' read sshuser server <<< "${remote}"
# echo "SSHUser: ${sshuser}, Server: ${server}"
IFS='/' read originuser repo <<<"${originpath}"
IFS='/' read originuser repo <<< "${originpath}"
# echo "Originuser: ${originuser}, Repo: ${repo}"
if [[ "${sshuser}" == "" || "${server}" == "" || "${originuser}" == "" || "${repo}" == "" ]]; then
echo "Can't parse origin URL: ${origin}" >&2
@@ -35,9 +35,9 @@ fi
upstream="https://${server}/${user}/${repo}"
upstreampush="${remote}:${user}/${repo}"
upstreamgroup="upstream upstream-push"
current=$(git remote get-url upstream 2>/dev/null)
currentpush=$(git remote get-url upstream-push 2>/dev/null)
currentgroup=$(git config remotes.upstreams)
current=$( git remote get-url upstream 2>/dev/null )
currentpush=$( git remote get-url upstream-push 2>/dev/null )
currentgroup=$( git config remotes.upstreams )
if [[ "${current}" == "${upstream}" ]]; then
echo "Upstream already set up correctly. Skip"
elif [[ -n "${current}" && "${current}" != "${upstream}" && "${current}" != "${upstreampush}" ]]; then
@@ -45,9 +45,9 @@ elif [[ -n "${current}" && "${current}" != "${upstream}" && "${current}" != "${u
else
if [[ "${current}" == "${upstreampush}" ]]; then
echo "Upstream set to dangerous push URL. Update."
_run git remote rename upstream upstream-push ||
_run git remote remove upstream
currentpush=$(git remote get-url upstream-push 2>/dev/null)
_run git remote rename upstream upstream-push || \
_run git remote remove upstream
currentpush=$( git remote get-url upstream-push 2>/dev/null )
fi
_run git remote add upstream "${upstream}"
fi

View File

@@ -1,8 +1,8 @@
#!/bin/bash
if [[ $# -lt 3 || "$1" == "--help" || "$1" = "-h" ]]; then
name=$(basename $0)
cat <<-USAGE
name=$( basename $0 )
cat <<- USAGE
Usage: $name workbranch base/branch user/branch [user/branch [...]]
* workbranch will be created locally from base/branch
@@ -16,7 +16,7 @@ fi
work="$1"
shift
branches=($(echo "${@}" | sed "s/:/\//"))
branches=( $( echo "${@}" | sed "s/:/\//" ) )
base="${branches[0]}"
unset branches[0]
@@ -24,10 +24,10 @@ set -e
users=()
for b in "${branches[@]}"; do
users+=($(echo $b | cut -d/ -f1))
users+=( $( echo $b | cut -d/ -f1 ) )
done
users=($(printf '%s\n' "${users[@]}" | sort -u))
users=( $( printf '%s\n' "${users[@]}" | sort -u ) )
git fetch --multiple upstreams "${users[@]}"
git checkout -B "$work" --no-track "$base"
@@ -40,7 +40,7 @@ done
# Make sure the commits look right
git log --show-signature "$base..HEAD"
parts=($(echo $base | sed "s/\// /"))
parts=( $( echo $base | sed "s/\// /" ) )
repo="${parts[0]}"
b="${parts[1]}"
push=$repo
@@ -50,7 +50,7 @@ fi
if [[ "$repo" == "upstream" ]]; then
repo="upstreams"
fi
cat <<PUSH
cat << PUSH
-------------------------------------------------------------------
This script will not push. Verify everything is correct, then push

View File

@@ -1,8 +1,8 @@
#!/bin/bash
if [[ $# -ne 3 || "$1" == "--help" || "$1" = "-h" ]]; then
name=$(basename $0)
cat <<-USAGE
name=$( basename $0 )
cat <<- USAGE
Usage: $name workbranch base/branch version
* workbranch will be created locally from base/branch. If it exists,
@@ -16,7 +16,7 @@ fi
work="$1"
shift
base=$(echo "$1" | sed "s/:/\//")
base=$( echo "$1" | sed "s/:/\//" )
shift
version=$1
@@ -28,16 +28,16 @@ git fetch upstreams
git checkout -B "${work}" --no-track "${base}"
push=$(git rev-parse --abbrev-ref --symbolic-full-name '@{push}' \
2>/dev/null) || true
push=$( git rev-parse --abbrev-ref --symbolic-full-name '@{push}' \
2>/dev/null ) || true
if [[ "${push}" != "" ]]; then
echo "Warning: ${push} may already exist."
fi
build=$(find -name BuildInfo.cpp)
sed 's/\(^.*versionString =\).*$/\1 "'${version}'"/' ${build} >version.cpp &&
diff "${build}" version.cpp && exit 1 ||
mv -vi version.cpp ${build}
build=$( find -name BuildInfo.cpp )
sed 's/\(^.*versionString =\).*$/\1 "'${version}'"/' ${build} > version.cpp && \
diff "${build}" version.cpp && exit 1 || \
mv -vi version.cpp ${build}
git diff
@@ -47,7 +47,7 @@ git commit -S -m "Set version to ${version}"
git log --oneline --first-parent ${base}^..
cat <<PUSH
cat << PUSH
-------------------------------------------------------------------
This script will not push. Verify everything is correct, then push

View File

@@ -168,13 +168,7 @@ def main():
if not os.environ.get("TIDY"):
return 0
repo_root = Path(
subprocess.check_output(
["git", "rev-parse", "--show-toplevel"],
cwd=Path(__file__).parent,
text=True,
).strip()
)
repo_root = Path(__file__).parent.parent
files = staged_files(repo_root)
if not files:
return 0

View File

@@ -1044,10 +1044,11 @@
# The online delete process checks periodically
# that xrpld is still in sync with the network,
# and that the validated ledger is less than
# 'age_threshold_seconds' old. If not, then continue
# 'age_threshold_seconds' old, and that all
# recent ledgers are available. If not, then continue
# sleeping for this number of seconds and
# checking until healthy.
# Default is 5.
# Default is 1.
#
# Notes:
# The 'node_db' entry configures the primary, persistent storage.

View File

@@ -1,13 +0,0 @@
# Python dependencies for XRP Ledger code generation scripts
#
# These packages are required to run the code generation scripts that
# parse macro files and generate C++ wrapper classes.
# C preprocessor for Python - used to preprocess macro files
pcpp>=1.30
# Parser combinator library - used to parse the macro DSL
pyparsing>=3.0.0
# Template engine - used to generate C++ code from templates
Mako>=1.2.2

View File

@@ -1,105 +1,13 @@
# This file was autogenerated by uv via the following command:
# uv pip compile requirements.in --generate-hashes --output-file requirements.txt
mako==1.3.12 \
--hash=sha256:8f61569480282dbf557145ce441e4ba888be453c30989f879f0d652e39f53ea9 \
--hash=sha256:9f778e93289bd410bb35daadeb4fc66d95a746f0b75777b942088b7fd7af550a
# via -r requirements.in
markupsafe==3.0.3 \
--hash=sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f \
--hash=sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a \
--hash=sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf \
--hash=sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19 \
--hash=sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf \
--hash=sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c \
--hash=sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175 \
--hash=sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219 \
--hash=sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb \
--hash=sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6 \
--hash=sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab \
--hash=sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26 \
--hash=sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1 \
--hash=sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce \
--hash=sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218 \
--hash=sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634 \
--hash=sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695 \
--hash=sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad \
--hash=sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73 \
--hash=sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c \
--hash=sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe \
--hash=sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa \
--hash=sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559 \
--hash=sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa \
--hash=sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37 \
--hash=sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758 \
--hash=sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f \
--hash=sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8 \
--hash=sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d \
--hash=sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c \
--hash=sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97 \
--hash=sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a \
--hash=sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19 \
--hash=sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9 \
--hash=sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9 \
--hash=sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc \
--hash=sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2 \
--hash=sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4 \
--hash=sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354 \
--hash=sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50 \
--hash=sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698 \
--hash=sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9 \
--hash=sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b \
--hash=sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc \
--hash=sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115 \
--hash=sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e \
--hash=sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485 \
--hash=sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f \
--hash=sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12 \
--hash=sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025 \
--hash=sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009 \
--hash=sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d \
--hash=sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b \
--hash=sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a \
--hash=sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5 \
--hash=sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f \
--hash=sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d \
--hash=sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1 \
--hash=sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287 \
--hash=sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6 \
--hash=sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f \
--hash=sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581 \
--hash=sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed \
--hash=sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b \
--hash=sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c \
--hash=sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026 \
--hash=sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8 \
--hash=sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676 \
--hash=sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6 \
--hash=sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e \
--hash=sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d \
--hash=sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d \
--hash=sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01 \
--hash=sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7 \
--hash=sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419 \
--hash=sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795 \
--hash=sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1 \
--hash=sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5 \
--hash=sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d \
--hash=sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42 \
--hash=sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe \
--hash=sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda \
--hash=sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e \
--hash=sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737 \
--hash=sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523 \
--hash=sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591 \
--hash=sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc \
--hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \
--hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50
# via mako
pcpp==1.30 \
--hash=sha256:05fe08292b6da57f385001c891a87f40d6aa7f46787b03e8ba326d20a3297c6e \
--hash=sha256:5af9fbce55f136d7931ae915fae03c34030a3b36c496e72d9636cedc8e2543a1
# via -r requirements.in
pyparsing==3.3.2 \
--hash=sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d \
--hash=sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc
# via -r requirements.in
# Python dependencies for XRP Ledger code generation scripts
#
# These packages are required to run the code generation scripts that
# parse macro files and generate C++ wrapper classes.
# C preprocessor for Python - used to preprocess macro files
pcpp>=1.30
# Parser combinator library - used to parse the macro DSL
pyparsing>=3.0.0
# Template engine - used to generate C++ code from templates
Mako>=1.2.2

View File

@@ -93,7 +93,6 @@ words:
- daria
- dcmake
- dearmor
- dedented
- deleteme
- demultiplexer
- deserializaton
@@ -200,13 +199,11 @@ words:
- nonxrp
- noreplace
- noripple
- nostdinc
- notifempty
- nudb
- nullptr
- nunl
- Nyffenegger
- onlatest
- ostr
- pargs
- partitioner
@@ -257,7 +254,6 @@ words:
- sfields
- shamap
- shamapitem
- shfmt
- shlibs
- sidechain
- SIGGOOD
@@ -302,7 +298,6 @@ words:
- unauthorizing
- unergonomic
- unfetched
- unfindable
- unflatten
- unfund
- unimpair

View File

@@ -1,48 +0,0 @@
#!/bin/bash
# Sanity-check that the sanitizer runtimes shipped with g++/clang++ work
# end-to-end against the system loader: compile each example with both
# compilers, run it, and confirm the expected diagnostic is emitted.
set -eo pipefail
cpp_files_dir="${1:?usage: $0 <cpp_files_dir>}"
case "$(uname -m)" in
x86_64) loader=/lib64/ld-linux-x86-64.so.2 ;;
aarch64) loader=/lib/ld-linux-aarch64.so.1 ;;
*)
echo "Unsupported arch: $(uname -m)" >&2
exit 1
;;
esac
declare -A sanitize=(
[asan]="-fsanitize=address"
[tsan]="-fsanitize=thread"
[ubsan]="-fsanitize=undefined"
)
declare -A expect=(
[asan]="heap-use-after-free"
[tsan]="data race"
[ubsan]="signed integer overflow"
)
for compiler in g++ clang++; do
for name in asan tsan ubsan; do
bin="/tmp/${name}-${compiler}"
echo "=== Build ${name} with ${compiler} ==="
"$compiler" -std=c++20 -O1 -g ${sanitize[$name]} \
-Wl,--dynamic-linker=$loader \
"${cpp_files_dir}/${name}.cpp" -o "$bin"
echo "=== Run ${name}-${compiler} ==="
output=$("$bin" 2>&1) || true
echo "$output"
echo "$output" | grep -q "${expect[$name]}" ||
{
echo "expected '${expect[$name]}' from $bin"
exit 1
}
rm -f "$bin"
done
done

View File

@@ -1,28 +0,0 @@
#include <atomic>
#include <cstddef>
#include <iostream>
#if defined(__clang__) || defined(__GNUC__)
__attribute__((noinline))
#elif defined(_MSC_VER)
__declspec(noinline)
#endif
int
read_after_free(volatile int* array, std::size_t index)
{
std::atomic_signal_fence(std::memory_order_seq_cst);
int value = array[index];
std::atomic_signal_fence(std::memory_order_seq_cst);
return value;
}
int
main()
{
int* array = new int[5]{10, 20, 30, 40, 50};
delete[] array;
std::cout << "Value at index 2: " << read_after_free(array, 2) << std::endl;
return 0;
}

View File

@@ -1,26 +0,0 @@
#include <iostream>
#include <thread>
static int kCounter = 0;
void
increment()
{
for (int i = 0; i < 100'000; ++i)
{
++kCounter;
}
}
int
main()
{
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout << "Final counter value: " << kCounter << std::endl;
return 0;
}

View File

@@ -1,13 +0,0 @@
#include <iostream>
#include <limits>
int
main()
{
int maxInt = std::numeric_limits<int>::max();
int volatile one = 1;
std::cout << "Current max: " << maxInt << std::endl;
int overflowed = maxInt + one;
std::cout << "Overflowed result: " << overflowed << std::endl;
return 0;
}

View File

@@ -45,30 +45,8 @@ COPY --from=builder /tmp/build/result /nix/ci-env
ENV PATH="/nix/ci-env/bin:$PATH"
# Externally-built dynamically-linked ELF binaries hard-code the loader path
# (e.g. /lib64/ld-linux-x86-64.so.2) in their PT_INTERP header. Copy the
# loader from the Nix store to that path when the base image doesn't already
# provide one (i.e. on nixos/nix).
RUN <<EOF
case "$(uname -m)" in
x86_64) target=/lib64/ld-linux-x86-64.so.2 ;;
aarch64) target=/lib/ld-linux-aarch64.so.1 ;;
*) echo "Unsupported arch: $(uname -m)" >&2; exit 1 ;;
esac
if [ ! -e "$target" ]; then
# Use the loader from the same glibc that gcc links libc against, so
# ld-linux and libc/libpthread share GLIBC_PRIVATE symbols at runtime.
src="$(dirname "$(gcc -print-file-name=libc.so.6)")/$(basename "$target")"
[ -e "$src" ] || { echo "ld-linux not found at $src" >&2; exit 1; }
mkdir -p "$(dirname "$target")"
cp "$src" "$target"
fi
EOF
RUN <<EOF
ccache --version
clang --version
clang++ --version
clang-format --version
cmake --version
conan --version
@@ -86,10 +64,3 @@ python3 --version
run-clang-tidy --help
vim --version
EOF
# Sanity-check that the sanitizer runtimes shipped with g++/clang++ work
# end-to-end against the system loader.
COPY docker/cpp_files/ /tmp/cpp_files/
COPY docker/check-sanitizers.sh /tmp/check-sanitizers.sh
RUN grep -qi ubuntu /etc/os-release 2>/dev/null && /tmp/check-sanitizers.sh /tmp/cpp_files || true

4
flake.lock generated
View File

@@ -15,7 +15,7 @@
"type": "indirect"
}
},
"nixpkgs-custom-glibc": {
"nixpkgs-glibc231": {
"flake": false,
"locked": {
"lastModified": 1593520194,
@@ -35,7 +35,7 @@
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"nixpkgs-custom-glibc": "nixpkgs-custom-glibc"
"nixpkgs-glibc231": "nixpkgs-glibc231"
}
}
},

View File

@@ -6,16 +6,16 @@
# version — matches the system libc on Ubuntu 20.04 LTS. Imported
# manually (flake = false) because this revision predates nixpkgs'
# own flake.nix.
nixpkgs-custom-glibc = {
nixpkgs-glibc231 = {
url = "github:NixOS/nixpkgs/9cd98386a38891d1074fc18036b842dc4416f562";
flake = false;
};
};
outputs =
{ nixpkgs, nixpkgs-custom-glibc, ... }:
{ nixpkgs, nixpkgs-glibc231, ... }:
let
forEachSystem = import ./nix/utils.nix { inherit nixpkgs nixpkgs-custom-glibc; };
forEachSystem = import ./nix/utils.nix { inherit nixpkgs nixpkgs-glibc231; };
in
{
devShells = forEachSystem (import ./nix/devshell.nix);

View File

@@ -7,9 +7,7 @@
#include <limits>
#include <optional>
#include <ostream>
#include <set>
#include <string>
#include <unordered_map>
namespace xrpl {
@@ -46,11 +44,11 @@ isPowerOfTen(T value)
* * min is a power of 10, and
* * max = min * 10 - 1.
*
* The MantissaScale enum indicates properties of the range: size, and some behavioral
* options. This intentionally restricts the number of unique MantissaRanges that can
* be instantiated: one for each scale.
* The mantissa_scale enum indicates whether the range is "small" or "large".
* This intentionally restricts the number of MantissaRanges that can be
* instantiated to two: one for each scale.
*
* The "Small" scale is based on the behavior of STAmount for IOUs. It has a min
* The "small" scale is based on the behavior of STAmount for IOUs. It has a min
* value of 10^15, and a max value of 10^16-1. This was sufficient for
* uses before Lending Protocol was implemented, mostly related to AMM.
*
@@ -61,54 +59,29 @@ isPowerOfTen(T value)
* STNumber field type, and for internal calculations. That necessitated the
* "large" scale.
*
* The "Large" scales are intended to represent all values that can be represented
* The "large" scale is intended to represent all values that can be represented
* by an STAmount - IOUs, XRP, and MPTs. It has a min value of 10^18, and a max
* value of 10^19-1. "LargeLegacy" is like "Large", but preserves
* a rounding error when a computation results in a mantissa of
* Number::kMaxRep that needs to be rounded up, but rounds down
* instead. It will maintain consistent behavior until the fixCleanup3_2_0
* amendment is enabled.
* value of 10^19-1.
*
* Note that if the mentioned amendments are eventually retired, this class
* should be left in place, but the "Small" scale option should be removed. This
* should be left in place, but the "small" scale option should be removed. This
* will allow for future expansion beyond 64-bits if it is ever needed.
*/
struct MantissaRange final
struct MantissaRange
{
using rep = std::uint64_t;
enum class MantissaScale {
Small,
// LargeLegacy can be removed when fixCleanup3_2_0 is retired
LargeLegacy,
Large,
};
// This entire enum can be removed when fixCleanup3_2_0 is retired
enum class CuspRoundingFix : bool {
Disabled = false,
Enabled = true,
};
enum class MantissaScale { Small, Large };
explicit constexpr MantissaRange(MantissaScale scale)
: min(getMin(scale))
, cuspRoundingFixEnabled(isCuspFixEnabled(scale))
, log(logTen(min).value_or(-1))
, scale(scale)
: min(getMin(scale)), log(logTen(min).value_or(-1)), scale(scale)
{
}
rep min;
rep max{(min * 10) - 1};
CuspRoundingFix cuspRoundingFixEnabled;
int log;
MantissaScale scale;
static MantissaRange const&
getMantissaRange(MantissaScale scale);
static std::set<MantissaScale> const&
getAllScales();
private:
static constexpr rep
getMin(MantissaScale scale)
@@ -117,35 +90,15 @@ private:
{
case MantissaScale::Small:
return 1'000'000'000'000'000ULL;
case MantissaScale::LargeLegacy:
case MantissaScale::Large:
return 1'000'000'000'000'000'000ULL;
default:
// If called in a constexpr context, this throw assures that the build fails if an
// Since this can never be called outside a non-constexpr
// context, this throw assures that the build fails if an
// invalid scale is used.
throw std::runtime_error("Unknown mantissa scale"); // LCOV_EXCL_LINE
throw std::runtime_error("Unknown mantissa scale");
}
}
static constexpr CuspRoundingFix
isCuspFixEnabled(MantissaScale scale)
{
switch (scale)
{
case MantissaScale::Small:
case MantissaScale::LargeLegacy:
return CuspRoundingFix::Disabled;
case MantissaScale::Large:
return CuspRoundingFix::Enabled;
default:
// If called in a constexpr context, this throw assures that the build fails if an
// invalid scale is used.
throw std::runtime_error("Unknown mantissa scale"); // LCOV_EXCL_LINE
}
}
static std::unordered_map<MantissaScale, MantissaRange> const&
getRanges();
};
// Like std::integral, but only 64-bit integral types.
@@ -250,7 +203,7 @@ concept Integral64 = std::is_same_v<T, std::int64_t> || std::is_same_v<T, std::u
* amendments are enabled to determine which result to expect.
*
*/
class Number final
class Number
{
using rep = std::int64_t;
using internalrep = MantissaRange::rep;
@@ -471,29 +424,49 @@ public:
return kRange.get().log;
}
/// oneSmall is needed because the ranges are private
static constexpr Number
oneSmall();
/// oneLarge is needed because the ranges are private
static constexpr Number
oneLarge();
// And one is needed because it needs to choose between oneSmall and
// oneLarge based on the current range
static Number
one();
template <
auto MinMantissa,
auto MaxMantissa,
Integral64 T = std::decay_t<decltype(MinMantissa)>,
Integral64 TMax = std::decay_t<decltype(MaxMantissa)>>
template <Integral64 T>
[[nodiscard]]
std::pair<T, int>
normalizeToRange() const;
normalizeToRange(T minMantissa, T maxMantissa) const;
private:
static thread_local RoundingMode mode;
// The available ranges for mantissa
static constexpr MantissaRange kSmallRange{MantissaRange::MantissaScale::Small};
static_assert(isPowerOfTen(kSmallRange.min));
static_assert(kSmallRange.min == 1'000'000'000'000'000LL);
static_assert(kSmallRange.max == 9'999'999'999'999'999LL);
static_assert(kSmallRange.log == 15);
static_assert(kSmallRange.min < kMaxRep);
static_assert(kSmallRange.max < kMaxRep);
static constexpr MantissaRange kLargeRange{MantissaRange::MantissaScale::Large};
static_assert(isPowerOfTen(kLargeRange.min));
static_assert(kLargeRange.min == 1'000'000'000'000'000'000ULL);
static_assert(kLargeRange.max == internalrep(9'999'999'999'999'999'999ULL));
static_assert(kLargeRange.log == 18);
static_assert(kLargeRange.min < kMaxRep);
static_assert(kLargeRange.max > kMaxRep);
// The range for the mantissa when normalized.
// Use reference_wrapper to avoid making copies, and prevent accidentally
// changing the values inside the range.
static thread_local std::reference_wrapper<MantissaRange const> kRange;
void
normalize(MantissaRange const& range);
normalize();
/** Normalize Number components to an arbitrary range.
*
@@ -508,8 +481,7 @@ private:
T& mantissa,
int& exponent,
internalrep const& minMantissa,
internalrep const& maxMantissa,
MantissaRange::CuspRoundingFix cuspRoundingFixEnabled);
internalrep const& maxMantissa);
template <class T>
friend void
@@ -518,8 +490,7 @@ private:
T& mantissa,
int& exponent,
MantissaRange::rep const& minMantissa,
MantissaRange::rep const& maxMantissa,
MantissaRange::CuspRoundingFix cuspRoundingFixEnabled);
MantissaRange::rep const& maxMantissa);
[[nodiscard]] bool
isnormal() const noexcept;
@@ -555,7 +526,7 @@ static constexpr Number kNumZero{};
inline Number::Number(bool negative, internalrep mantissa, int exponent, Normalized)
: Number(negative, mantissa, exponent, Unchecked{})
{
normalize(kRange);
normalize();
}
inline Number::Number(internalrep mantissa, int exponent, Normalized)
@@ -725,19 +696,10 @@ Number::isnormal() const noexcept
kMinExponent <= exponent_ && exponent_ <= kMaxExponent);
}
template <auto MinMantissa, auto MaxMantissa, Integral64 T, Integral64 TMax>
template <Integral64 T>
std::pair<T, int>
Number::normalizeToRange() const
Number::normalizeToRange(T minMantissa, T maxMantissa) const
{
static_assert(std::is_same_v<T, std::uint64_t> || std::is_same_v<T, std::int64_t>);
static_assert(std::is_same_v<T, TMax>);
auto constexpr kMIN = static_cast<T>(MinMantissa);
auto constexpr kMAX = static_cast<T>(MaxMantissa);
static_assert(kMIN > 0);
static_assert(kMIN % 10 == 0);
static_assert(kMAX % 10 == 9);
static_assert((kMAX + 1) / 10 == kMIN);
bool negative = negative_;
internalrep mantissa = mantissa_;
int exponent = exponent_;
@@ -749,10 +711,7 @@ Number::normalizeToRange() const
"xrpl::Number::normalizeToRange",
"Number is non-negative for unsigned range.");
}
// Don't need to worry about the cuspRounding fix because rounding up will never take the
// mantissa over maxMantissa with a ones digit value other than 0. 0 can safely be truncated.
Number::normalize(
negative, mantissa, exponent, kMIN, kMAX, MantissaRange::CuspRoundingFix::Disabled);
Number::normalize(negative, mantissa, exponent, minMantissa, maxMantissa);
auto const sign = negative ? -1 : 1;
return std::make_pair(static_cast<T>(sign * mantissa), exponent);
@@ -804,8 +763,6 @@ to_string(MantissaRange::MantissaScale const& scale)
{
case MantissaRange::MantissaScale::Small:
return "small";
case MantissaRange::MantissaScale::LargeLegacy:
return "largeLegacy";
case MantissaRange::MantissaScale::Large:
return "large";
default:

View File

@@ -181,14 +181,14 @@ private:
beast::insight::Collector::ptr const& collector)
: hook(collector->makeHook(handler))
, size(collector->makeGauge(prefix, "size"))
, hitRate(collector->makeGauge(prefix, "hit_rate"))
, hit_rate(collector->makeGauge(prefix, "hit_rate"))
{
}
beast::insight::Hook hook;
beast::insight::Gauge size;
beast::insight::Gauge hitRate;
beast::insight::Gauge hit_rate;
std::size_t hits{0};
std::size_t misses{0};
@@ -197,16 +197,16 @@ private:
class KeyOnlyEntry
{
public:
clock_type::time_point lastAccess;
clock_type::time_point last_access;
explicit KeyOnlyEntry(clock_type::time_point const& lastAccess) : lastAccess(lastAccess)
explicit KeyOnlyEntry(clock_type::time_point const& lastAccess) : last_access(lastAccess)
{
}
void
touch(clock_type::time_point const& now)
{
lastAccess = now;
last_access = now;
}
};
@@ -214,10 +214,10 @@ private:
{
public:
shared_weak_combo_pointer_type ptr;
clock_type::time_point lastAccess;
clock_type::time_point last_access;
ValueEntry(clock_type::time_point const& lastAccess, shared_pointer_type const& ptr)
: ptr(ptr), lastAccess(lastAccess)
: ptr(ptr), last_access(lastAccess)
{
}
@@ -246,7 +246,7 @@ private:
void
touch(clock_type::time_point const& now)
{
lastAccess = now;
last_access = now;
}
};
@@ -286,13 +286,13 @@ private:
std::string name_;
// Desired number of cache entries (0 = ignore)
int const targetSize_;
int const target_size_;
// Desired maximum cache age
clock_type::duration const targetAge_;
clock_type::duration const target_age_;
// Number of items cached
int cacheCount_{0};
int cache_count_{0};
cache_type cache_; // Hold strong reference to recent objects
std::uint64_t hits_{0};
std::uint64_t misses_{0};

View File

@@ -34,8 +34,8 @@ inline TaggedCache<
, clock_(clock)
, stats_(name, std::bind(&TaggedCache::collectMetrics, this), collector)
, name_(name)
, targetSize_(size)
, targetAge_(expiration)
, target_size_(size)
, target_age_(expiration)
{
}
@@ -86,7 +86,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
getCacheSize() const
{
std::scoped_lock const lock(mutex_);
return cacheCount_;
return cache_count_;
}
template <
@@ -139,7 +139,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
{
std::scoped_lock const lock(mutex_);
cache_.clear();
cacheCount_ = 0;
cache_count_ = 0;
}
template <
@@ -157,7 +157,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
{
std::scoped_lock const lock(mutex_);
cache_.clear();
cacheCount_ = 0;
cache_count_ = 0;
hits_ = 0;
misses_ = 0;
}
@@ -213,21 +213,21 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
{
std::scoped_lock const lock(mutex_);
if (targetSize_ == 0 || (static_cast<int>(cache_.size()) <= targetSize_))
if (target_size_ == 0 || (static_cast<int>(cache_.size()) <= target_size_))
{
whenExpire = now - targetAge_;
whenExpire = now - target_age_;
}
else
{
whenExpire = now - (targetAge_ * targetSize_ / cache_.size());
whenExpire = now - (target_age_ * target_size_ / cache_.size());
clock_type::duration const minimumAge(std::chrono::seconds(1));
if (whenExpire > (now - minimumAge))
whenExpire = now - minimumAge;
JLOG(journal_.trace())
<< name_ << " is growing fast " << cache_.size() << " of " << targetSize_
<< " aging at " << (now - whenExpire).count() << " of " << targetAge_.count();
<< name_ << " is growing fast " << cache_.size() << " of " << target_size_
<< " aging at " << (now - whenExpire).count() << " of " << target_age_.count();
}
std::vector<std::thread> workers;
@@ -242,7 +242,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
for (std::thread& worker : workers)
worker.join();
cacheCount_ -= allRemovals;
cache_count_ -= allRemovals;
}
// At this point allStuffToSweep will go out of scope outside the lock
// and decrement the reference count on each strong pointer.
@@ -280,7 +280,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
if (entry.isCached())
{
--cacheCount_;
--cache_count_;
entry.ptr.convertToWeak();
ret = true;
}
@@ -317,7 +317,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
std::piecewise_construct,
std::forward_as_tuple(key),
std::forward_as_tuple(clock_.now(), data));
++cacheCount_;
++cache_count_;
return false;
}
@@ -366,12 +366,12 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
data = cachedData;
}
++cacheCount_;
++cache_count_;
return true;
}
entry.ptr = data;
++cacheCount_;
++cache_count_;
return false;
}
@@ -477,7 +477,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
auto [it, inserted] = cache_.emplace(
std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(now));
if (!inserted)
it->second.lastAccess = now;
it->second.last_access = now;
return inserted;
}
@@ -626,7 +626,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
if (entry.isCached())
{
// independent of cache size, so not counted as a hit
++cacheCount_;
++cache_count_;
entry.touch(clock_.now());
return entry.ptr.getStrong();
}
@@ -658,7 +658,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
if (total != 0)
hitRate = (hits_ * 100) / total;
}
stats_.hitRate.set(hitRate);
stats_.hit_rate.set(hitRate);
}
}
@@ -706,7 +706,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
++cit;
}
}
else if (cit->second.lastAccess <= whenExpire)
else if (cit->second.last_access <= whenExpire)
{
// strong, expired
++cacheRemovals;
@@ -773,12 +773,12 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
auto cit = partition.begin();
while (cit != partition.end())
{
if (cit->second.lastAccess > now)
if (cit->second.last_access > now)
{
cit->second.lastAccess = now;
cit->second.last_access = now;
++cit;
}
else if (cit->second.lastAccess <= whenExpire)
else if (cit->second.last_access <= whenExpire)
{
cit = partition.erase(cit);
}

View File

@@ -24,20 +24,20 @@ namespace xrpl {
template <class EF>
class ScopeExit
{
EF exitFunction_;
bool executeOnDestruction_{true};
EF exit_function_;
bool execute_on_destruction_{true};
public:
~ScopeExit()
{
if (executeOnDestruction_)
exitFunction_();
if (execute_on_destruction_)
exit_function_();
}
ScopeExit(ScopeExit&& rhs) noexcept(
std::is_nothrow_move_constructible_v<EF> || std::is_nothrow_copy_constructible_v<EF>)
: exitFunction_{std::forward<EF>(rhs.exitFunction_)}
, executeOnDestruction_{rhs.executeOnDestruction_}
: exit_function_{std::forward<EF>(rhs.exit_function_)}
, execute_on_destruction_{rhs.execute_on_destruction_}
{
rhs.release();
}
@@ -51,7 +51,7 @@ public:
std::enable_if_t<
!std::is_same_v<std::remove_cv_t<EFP>, ScopeExit> &&
std::is_constructible_v<EF, EFP>>* = 0) noexcept
: exitFunction_{std::forward<EFP>(f)}
: exit_function_{std::forward<EFP>(f)}
{
static_assert(std::is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>);
}
@@ -59,7 +59,7 @@ public:
void
release() noexcept
{
executeOnDestruction_ = false;
execute_on_destruction_ = false;
}
};
@@ -69,22 +69,22 @@ ScopeExit(EF) -> ScopeExit<EF>;
template <class EF>
class ScopeFail
{
EF exitFunction_;
bool executeOnDestruction_{true};
int uncaughtOnCreation_{std::uncaught_exceptions()};
EF exit_function_;
bool execute_on_destruction_{true};
int uncaught_on_creation_{std::uncaught_exceptions()};
public:
~ScopeFail()
{
if (executeOnDestruction_ && std::uncaught_exceptions() > uncaughtOnCreation_)
exitFunction_();
if (execute_on_destruction_ && std::uncaught_exceptions() > uncaught_on_creation_)
exit_function_();
}
ScopeFail(ScopeFail&& rhs) noexcept(
std::is_nothrow_move_constructible_v<EF> || std::is_nothrow_copy_constructible_v<EF>)
: exitFunction_{std::forward<EF>(rhs.exitFunction_)}
, executeOnDestruction_{rhs.executeOnDestruction_}
, uncaughtOnCreation_{rhs.uncaughtOnCreation_}
: exit_function_{std::forward<EF>(rhs.exit_function_)}
, execute_on_destruction_{rhs.execute_on_destruction_}
, uncaught_on_creation_{rhs.uncaught_on_creation_}
{
rhs.release();
}
@@ -98,7 +98,7 @@ public:
std::enable_if_t<
!std::is_same_v<std::remove_cv_t<EFP>, ScopeFail> &&
std::is_constructible_v<EF, EFP>>* = 0) noexcept
: exitFunction_{std::forward<EFP>(f)}
: exit_function_{std::forward<EFP>(f)}
{
static_assert(std::is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>);
}
@@ -106,7 +106,7 @@ public:
void
release() noexcept
{
executeOnDestruction_ = false;
execute_on_destruction_ = false;
}
};
@@ -116,22 +116,22 @@ ScopeFail(EF) -> ScopeFail<EF>;
template <class EF>
class ScopeSuccess
{
EF exitFunction_;
bool executeOnDestruction_{true};
int uncaughtOnCreation_{std::uncaught_exceptions()};
EF exit_function_;
bool execute_on_destruction_{true};
int uncaught_on_creation_{std::uncaught_exceptions()};
public:
~ScopeSuccess() noexcept(noexcept(exitFunction_()))
~ScopeSuccess() noexcept(noexcept(exit_function_()))
{
if (executeOnDestruction_ && std::uncaught_exceptions() <= uncaughtOnCreation_)
exitFunction_();
if (execute_on_destruction_ && std::uncaught_exceptions() <= uncaught_on_creation_)
exit_function_();
}
ScopeSuccess(ScopeSuccess&& rhs) noexcept(
std::is_nothrow_move_constructible_v<EF> || std::is_nothrow_copy_constructible_v<EF>)
: exitFunction_{std::forward<EF>(rhs.exitFunction_)}
, executeOnDestruction_{rhs.executeOnDestruction_}
, uncaughtOnCreation_{rhs.uncaughtOnCreation_}
: exit_function_{std::forward<EF>(rhs.exit_function_)}
, execute_on_destruction_{rhs.execute_on_destruction_}
, uncaught_on_creation_{rhs.uncaught_on_creation_}
{
rhs.release();
}
@@ -146,14 +146,14 @@ public:
!std::is_same_v<std::remove_cv_t<EFP>, ScopeSuccess> &&
std::is_constructible_v<EF, EFP>>* =
0) noexcept(std::is_nothrow_constructible_v<EF, EFP> || std::is_nothrow_constructible_v<EF, EFP&>)
: exitFunction_{std::forward<EFP>(f)}
: exit_function_{std::forward<EFP>(f)}
{
}
void
release() noexcept
{
executeOnDestruction_ = false;
execute_on_destruction_ = false;
}
};

View File

@@ -77,8 +77,8 @@ private:
std::ostream& os_;
Results results_;
SuiteResults suiteResults_;
CaseResults caseResults_;
SuiteResults suite_results_;
CaseResults case_results_;
public:
Reporter(Reporter const&) = delete;
@@ -196,22 +196,22 @@ template <class Unused>
void
Reporter<Unused>::onSuiteBegin(SuiteInfo const& info)
{
suiteResults_ = SuiteResults{info.fullName()};
suite_results_ = SuiteResults{info.fullName()};
}
template <class Unused>
void
Reporter<Unused>::onSuiteEnd()
{
results_.add(suiteResults_);
results_.add(suite_results_);
}
template <class Unused>
void
Reporter<Unused>::onCaseBegin(std::string const& name)
{
caseResults_ = CaseResults(name);
os_ << suiteResults_.name << (caseResults_.name.empty() ? "" : (" " + caseResults_.name))
case_results_ = CaseResults(name);
os_ << suite_results_.name << (case_results_.name.empty() ? "" : (" " + case_results_.name))
<< std::endl;
}
@@ -219,23 +219,23 @@ template <class Unused>
void
Reporter<Unused>::onCaseEnd()
{
suiteResults_.add(caseResults_);
suite_results_.add(case_results_);
}
template <class Unused>
void
Reporter<Unused>::onPass()
{
++caseResults_.total;
++case_results_.total;
}
template <class Unused>
void
Reporter<Unused>::onFail(std::string const& reason)
{
++caseResults_.failed;
++caseResults_.total;
os_ << "#" << caseResults_.total << " failed" << (reason.empty() ? "" : ": ") << reason
++case_results_.failed;
++case_results_.total;
os_ << "#" << case_results_.total << " failed" << (reason.empty() ? "" : ": ") << reason
<< std::endl;
}

View File

@@ -47,7 +47,7 @@ inline bool
JobQueue::Coro::post()
{
{
std::scoped_lock const lk(mutexRun_);
std::scoped_lock const lk(mutex_run_);
running_ = true;
}
@@ -58,7 +58,7 @@ JobQueue::Coro::post()
}
// The coroutine will not run. Clean up running_.
std::scoped_lock const lk(mutexRun_);
std::scoped_lock const lk(mutex_run_);
running_ = false;
cv_.notify_all();
return false;
@@ -68,7 +68,7 @@ inline void
JobQueue::Coro::resume()
{
{
std::scoped_lock const lk(mutexRun_);
std::scoped_lock const lk(mutex_run_);
running_ = true;
}
{
@@ -92,7 +92,7 @@ JobQueue::Coro::resume()
}
detail::getLocalValues().release();
detail::getLocalValues().reset(saved);
std::scoped_lock const lk(mutexRun_);
std::scoped_lock const lk(mutex_run_);
running_ = false;
cv_.notify_all();
}
@@ -127,7 +127,7 @@ JobQueue::Coro::expectEarlyExit()
inline void
JobQueue::Coro::join()
{
std::unique_lock<std::mutex> lk(mutexRun_);
std::unique_lock<std::mutex> lk(mutex_run_);
cv_.wait(lk, [this]() { return !running_; });
}

View File

@@ -127,7 +127,7 @@ private:
std::function<void()> job_;
std::shared_ptr<LoadEvent> loadEvent_;
std::string name_;
clock_type::time_point queueTime_;
clock_type::time_point queue_time_;
};
using JobCounter = ClosureCounter<void>;

View File

@@ -52,7 +52,7 @@ public:
std::string name_;
bool running_{false};
std::mutex mutex_;
std::mutex mutexRun_;
std::mutex mutex_run_;
std::condition_variable cv_;
boost::coroutines2::coroutine<void>::push_type* yield_{};
boost::coroutines2::coroutine<void>::pull_type coro_;
@@ -246,7 +246,7 @@ private:
// Statistics tracking
perf::PerfLog& perfLog_;
beast::insight::Collector::ptr collector_;
beast::insight::Gauge jobCount_;
beast::insight::Gauge job_count_;
beast::insight::Hook hook_;
std::condition_variable cv_;

View File

@@ -161,7 +161,7 @@ public:
* While the JSON spec doesn't explicitly disallow this, you should avoid
* calling this method twice with the same tag for the same object.
*
* If CHECK_JSON_WRITER is defined, this function throws an exception if
* If CHECK_JSON_WRITER is defined, this function throws an exception if if
* the tag you use has already been used in this object.
*/
template <typename Type>

View File

@@ -9,7 +9,7 @@ class BookDirs
private:
ReadView const* view_ = nullptr;
uint256 const root_;
uint256 const nextQuality_;
uint256 const next_quality_;
uint256 const key_;
std::shared_ptr<SLE const> sle_ = nullptr;
unsigned int entry_ = 0;
@@ -67,15 +67,15 @@ private:
friend class BookDirs;
const_iterator(ReadView const& view, uint256 const& root, uint256 const& dirKey)
: view_(&view), root_(root), key_(dirKey), curKey_(dirKey)
: view_(&view), root_(root), key_(dirKey), cur_key_(dirKey)
{
}
ReadView const* view_ = nullptr;
uint256 root_;
uint256 nextQuality_;
uint256 next_quality_;
uint256 key_;
uint256 curKey_;
uint256 cur_key_;
std::shared_ptr<SLE const> sle_;
unsigned int entry_ = 0;
uint256 index_;

View File

@@ -1,9 +1,7 @@
#pragma once
#include <xrpl/ledger/OrderBookIndex.h>
#include <xrpl/ledger/RawView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/TopOfBookCache.h>
#include <xrpl/ledger/detail/RawStateTable.h>
#include <xrpl/protocol/STArray.h>
#include <xrpl/protocol/XRPAmount.h>
@@ -78,7 +76,7 @@ private:
// monotonic_resource_ must outlive `items_`. Make a pointer so it may be
// easily moved.
std::unique_ptr<boost::container::pmr::monotonic_buffer_resource> monotonicResource_;
std::unique_ptr<boost::container::pmr::monotonic_buffer_resource> monotonic_resource_;
txs_map txs_;
Rules rules_;
LedgerHeader header_;
@@ -91,17 +89,6 @@ private:
bool open_ = true;
// Per-view top-of-book cache. Lifetime is the view's lifetime; on
// OpenView copy (used to snapshot for parallel apply / batch views),
// the underlying data is copied but counters reset.
mutable TopOfBookCache topOfBookCache_;
// Per-view ordered order-book index (Plan 9). Generalizes the cache from
// "best page" to the full quality-ordered offer sequence, letting the
// crossing path iterate via an in-memory cursor instead of re-walking the
// SHAMap with succ() per offer. Maintained off the same notifications.
mutable OrderBookIndex orderBookIndex_;
public:
OpenView() = delete;
OpenView&
@@ -213,46 +200,6 @@ public:
std::shared_ptr<SLE const>
read(Keylet const& k) const override;
// Top-of-book cache hooks
[[nodiscard]] std::optional<uint256>
topOfBookFirstPage(Book const& book) const override;
void
recordTopOfBook(Book const& book, uint256 const& firstPageKey) const override;
void
notifyOfferInserted(Book const& book, uint256 const& dirKey, uint256 const& offerKey)
const override;
void
notifyOfferDeleted(Book const& book, uint256 const& dirKey, uint256 const& offerKey)
const override;
[[nodiscard]] std::optional<std::vector<uint256>>
orderedBook(Book const& book) const override;
[[nodiscard]] TopOfBookCache const&
topOfBookCache() const noexcept
{
return topOfBookCache_;
}
[[nodiscard]] OrderBookIndex const&
orderBookIndex() const noexcept
{
return orderBookIndex_;
}
// Non-const access for seeding (rebuild-from-state at attach time) and for
// the cursor's lazy populate. The index is auxiliary, so this never affects
// the authoritative state.
[[nodiscard]] OrderBookIndex&
orderBookIndex() noexcept
{
return orderBookIndex_;
}
std::unique_ptr<SlesType::iter_base>
slesBegin() const override;

View File

@@ -1,181 +0,0 @@
#pragma once
#include <xrpl/basics/base_uint.h>
#include <xrpl/ledger/detail/PersistentOrderTree.h>
#include <xrpl/protocol/Book.h>
#include <atomic>
#include <cstddef>
#include <cstdint>
#include <optional>
#include <shared_mutex>
#include <unordered_map>
#include <utility>
#include <vector>
namespace xrpl {
class ReadView;
/** Deterministic, ordered, **persistent** in-memory index of every active order
book.
`BookTip::step()` finds the next offer to cross by calling `ReadView::succ()`
— an O(log N) SHAMap successor walk from the book root, re-done once per
consumed offer. Profiling shows that walk is ~32% of crossing-apply cost.
This index materializes the same quality-ordered offer sequence so iteration
becomes an in-memory cursor advance instead of a trie re-walk.
It generalizes `TopOfBookCache` from "the best directory page" to "the full
ordered book". Like `FlatStateMap`, it is **auxiliary**: the SHAMap remains
the authoritative state and the source of the consensus root. The index is
rebuildable from the SHAMap at any time (`rebuildBook`) and differentially
validated against it (`validateMatchesShaMap`); a divergence is a bug in the
maintenance hooks, never a fallback.
**Persistence.** Each book's offers live in an immutable, structurally-shared
weight-balanced tree ([[detail/PersistentOrderTree.h]]). `clone()` copies only
the per-book `shared_ptr` roots (O(#books)), not the offers — so the
open-ledger copy-on-write (`OpenView` copy per `modify()`) preserves the index
cheaply and it stays warm across transactions, instead of cold-starting and
rebuilding per tx. Immutable nodes also make the COW rollback of a discarded
sandbox free: it simply drops its own root pointers.
Ordering invariant (the load-bearing property for bit-exact crossing):
- Books are keyed by `Book` (which already carries the permissioned-DEX
`domain`), so each book — open or domain — is indexed independently.
- Within a book, the tree is keyed by `(dirRoot, insertSeq)`. `dirRoot` is
the quality-directory root key; ascending == best-quality-first ==
`succ()` order. `insertSeq` is a per-book monotonic counter capturing
directory append order; since `dirRemove` preserves relative order and
offer keys are never reused, in-order traversal reproduces the SHAMap
directory walk byte-for-byte.
Maintenance drives `insertOffer`/`deleteOffer` from the offer-mutation
notifications (`notifyOfferInserted`/`notifyOfferDeleted`), which fire with
the quality-directory root key and the offer key.
*/
class OrderBookIndex
{
public:
OrderBookIndex() = default;
/** Move-construct by locking the source and stealing its book map.
Counters are not transferred (a fresh view starts its own accounting). */
OrderBookIndex(OrderBookIndex&& other);
OrderBookIndex(OrderBookIndex const&) = delete;
OrderBookIndex&
operator=(OrderBookIndex const&) = delete;
OrderBookIndex&
operator=(OrderBookIndex&&) = delete;
/** Cheap structural copy: clones the per-book tree roots (O(#books)
shared_ptr copies), sharing all offer nodes. Used by the `OpenView` copy
ctor so the index stays warm across the open-ledger COW. Counters reset. */
[[nodiscard]] OrderBookIndex
clone() const;
// --- maintenance (apply-path hooks) ---
/** Record that `offerKey` was inserted into `book` at quality-directory root
`dirRoot`. Appended (next insertSeq) so it sorts after same-level offers,
preserving directory order. */
void
insertOffer(Book const& book, uint256 const& dirRoot, uint256 const& offerKey);
/** Record that `offerKey` was removed from `book` at quality-directory root
`dirRoot`. The book is dropped when it empties. Removing an absent key is
a no-op. */
void
deleteOffer(Book const& book, uint256 const& dirRoot, uint256 const& offerKey);
// --- ordered read access (BookTip seam) ---
/** All offer keys of `book`, best-quality-first, directory order within a
level. Empty if the book is absent. */
[[nodiscard]] std::vector<uint256>
flatten(Book const& book) const;
/** The best (first) offer key of `book`, or nullopt if absent. */
[[nodiscard]] std::optional<uint256>
firstOffer(Book const& book) const;
// --- rebuild / validation (composition with the authoritative SHAMap) ---
/** Repopulate `book` from `view` by the canonical quality-ordered walk
(`succ()` over directory roots + directory iteration within each). */
void
rebuildBook(ReadView const& view, Book const& book);
/** True iff the maintained sequence for `book` equals a fresh walk of
`view`. The differential invariant. */
[[nodiscard]] bool
validateMatchesShaMap(ReadView const& view, Book const& book) const;
// --- bookkeeping ---
/** True if `book` has an entry (at least one offer). O(1). Present implies
non-empty (empty books are dropped). */
[[nodiscard]] bool
contains(Book const& book) const;
void
eraseBook(Book const& book);
void
clear();
[[nodiscard]] std::size_t
bookCount() const;
[[nodiscard]] std::size_t
offerCount(Book const& book) const;
[[nodiscard]] std::uint64_t
inserts() const noexcept
{
return inserts_.load(std::memory_order_relaxed);
}
[[nodiscard]] std::uint64_t
deletes() const noexcept
{
return deletes_.load(std::memory_order_relaxed);
}
[[nodiscard]] std::uint64_t
rebuilds() const noexcept
{
return rebuilds_.load(std::memory_order_relaxed);
}
// --- operator-facing kill switch (mirrors TopOfBookCache) ---
[[nodiscard]] static bool
enabled() noexcept;
static void
setEnabled(bool on) noexcept;
private:
struct BookState
{
detail::OrderTreePtr root; // persistent (dirRoot, insertSeq) -> offerKey
std::uint64_t nextSeq{0}; // per-book monotonic append counter
};
// Canonical quality-ordered walk of `book` in `view`: (dirRoot, offerKey)
// for each offer, best-quality-first, directory order within a level.
[[nodiscard]] static std::vector<std::pair<uint256, uint256>>
walkBook(ReadView const& view, Book const& book);
mutable std::shared_mutex mutex_;
std::unordered_map<Book, BookState> books_;
std::atomic<std::uint64_t> inserts_{0};
std::atomic<std::uint64_t> deletes_{0};
std::atomic<std::uint64_t> rebuilds_{0};
};
} // namespace xrpl

View File

@@ -3,7 +3,6 @@
#include <xrpl/basics/chrono.h>
#include <xrpl/beast/hash/uhash.h>
#include <xrpl/ledger/detail/ReadViewFwdRange.h>
#include <xrpl/protocol/Book.h>
#include <xrpl/protocol/Fees.h>
#include <xrpl/protocol/IOUAmount.h>
#include <xrpl/protocol/Indexes.h>
@@ -17,7 +16,6 @@
#include <cstdint>
#include <optional>
#include <unordered_set>
#include <vector>
namespace xrpl {
@@ -190,68 +188,6 @@ public:
return count;
}
//
// Top-of-book cache hooks
//
// The default implementations make every non-overriding view a no-op
// pass-through, so non-orderbook code is unaffected. OpenView overrides
// these to maintain a real `TopOfBookCache`; views that wrap a base
// (ApplyViewBase, PaymentSandbox, ...) delegate to that base.
/** Return the cached keylet of the best (lowest-keyed) directory page
for `book`, if known. std::nullopt forces a `succ()` fallback.
*/
[[nodiscard]] virtual std::optional<uint256>
topOfBookFirstPage(Book const& book) const
{
return std::nullopt;
}
/** Populate the cache after a `succ()`-driven discovery. Called from
the cold path of `BookTip::step()`.
*/
virtual void
recordTopOfBook(Book const& book, uint256 const& firstPageKey) const
{
}
/** Apply-path notification: an offer was inserted into `book` at
directory keylet `dirKey`. The cache may use this to update or
invalidate its entry; the call must be safe under any base view.
*/
virtual void
notifyOfferInserted(Book const& book, uint256 const& dirKey, uint256 const& offerKey) const
{
}
/** Apply-path notification: an offer was deleted from `book` at
directory keylet `dirKey`. If the deleted offer was on the
cached top page, the cache invalidates that entry.
`offerKey` is the deleted offer's ledger key — unused by the cache,
consumed by the order-book index.
*/
virtual void
notifyOfferDeleted(Book const& book, uint256 const& dirKey, uint256 const& offerKey) const
{
}
/** Return `book`'s offer keys best-quality-first (the order the crossing
path consumes them), or std::nullopt to force the `succ()`-based walk.
Lets `BookTip` iterate the book from an in-memory cursor instead of
re-walking the SHAMap with `succ()` per offer. A returned vector is
guaranteed complete for `book` — implementations rebuild from the
authoritative state on a miss, so the cursor can never under-include.
Empty/absent books return nullopt (the cheap `succ()` path finds
nothing). Default: no index, always nullopt.
*/
[[nodiscard]] virtual std::optional<std::vector<uint256>>
orderedBook(Book const& book) const
{
return std::nullopt;
}
// used by the implementation
[[nodiscard]] virtual std::unique_ptr<SlesType::iter_base>
slesBegin() const = 0;

View File

@@ -35,7 +35,6 @@ public:
apply(RawView& to)
{
items_.apply(to);
flushTopOfBookNotifications();
}
};

View File

@@ -1,163 +0,0 @@
#pragma once
#include <xrpl/basics/base_uint.h>
#include <xrpl/protocol/Book.h>
#include <xrpl/protocol/Protocol.h>
#include <atomic>
#include <cstdint>
#include <mutex>
#include <optional>
#include <unordered_map>
namespace xrpl {
/** One entry in the top-of-book cache.
Records the keylet of the best-quality (lowest-keyed) directory page
for a single order book at the time the entry was recorded.
*/
struct TopOfBookEntry
{
/// Keylet of the best directory page for the book.
uint256 firstPageKey;
/// Quality bits encoded in firstPageKey (decoded for fast comparison).
std::uint64_t bestQuality{0};
/// Ledger sequence at which this entry was populated.
LedgerIndex asOfLedger{0};
};
/** Cache of "best directory page" keylet per active order book.
Reads of the top of an order book usually return the same directory page
over and over, but `BookTip::step()` re-walks the SHAMap on every call.
This cache memoizes that result. Lookups become a single hash-map probe;
the SHAMap successor walk happens only on cold or invalidated entries.
The cache is auxiliary — invalidating an entry is always safe, since the
next read repopulates lazily via `ReadView::succ()`. That property is what
lets the cache ship without an amendment.
Maintenance rules, applied at the apply path:
- **Offer inserted**: if the new offer's directory keylet is at-or-better
than the cached top, update the entry. Otherwise no-op.
- **Offer deleted**: if the deleted offer was on the cached top page,
invalidate. Otherwise no-op.
A best-page key is `keylet::quality(keylet::kBook(book), rate).key`. All
pages of a single book share the same prefix, so lower uint256 key =
better quality. Comparisons in this file rely on that ordering.
*/
class TopOfBookCache
{
public:
TopOfBookCache() = default;
/** Copy-construct (used when snapshotting open->closed ledger).
Hit/miss/invalidation counters are not copied; only the data is.
*/
TopOfBookCache(TopOfBookCache const& other);
/** Move-construct by locking the source and stealing its map.
Needed because views that own a cache (OpenView) are moveable;
std::mutex is not, so the move is implemented via lock-and-move.
Counters are not transferred.
*/
TopOfBookCache(TopOfBookCache&& other);
TopOfBookCache&
operator=(TopOfBookCache const&) = delete;
TopOfBookCache&
operator=(TopOfBookCache&&) = delete;
/** Look up the cached top of `book`.
Returns std::nullopt on miss. Hit/miss counters are updated.
*/
[[nodiscard]] std::optional<TopOfBookEntry>
get(Book const& book) const;
/** Record (or overwrite) a top-of-book entry for `book`.
Called from the cold path after `succ()` discovers the first page.
*/
void
record(Book const& book, uint256 const& firstPageKey, LedgerIndex seq);
/** Notify the cache that an offer was inserted into `book` at directory
keylet `dirKey`.
If the new keylet is better than (less than) the cached top, the entry
is updated. If it is equal, no change. If worse, no change.
If no entry exists for `book`, this is a no-op: the next read will
populate from `succ()`.
*/
void
onOfferInsert(Book const& book, uint256 const& dirKey, LedgerIndex seq);
/** Notify the cache that an offer was deleted from `book` at directory
keylet `dirKey`.
If the delete was on the cached top page, invalidate (the page may
now be empty, or the offer count is irrelevant — next read repopulates).
Otherwise no-op.
*/
void
onOfferDelete(Book const& book, uint256 const& dirKey);
/** Drop the entry for `book` unconditionally.
Used as a safety hatch and by tests.
*/
void
invalidate(Book const& book);
/** Drop every entry. */
void
clear();
[[nodiscard]] std::size_t
size() const;
[[nodiscard]] std::uint64_t
hits() const noexcept
{
return hits_.load(std::memory_order_relaxed);
}
[[nodiscard]] std::uint64_t
misses() const noexcept
{
return misses_.load(std::memory_order_relaxed);
}
[[nodiscard]] std::uint64_t
invalidations() const noexcept
{
return invalidations_.load(std::memory_order_relaxed);
}
/** Operator-facing kill switch.
When false, `BookTip` skips cache consults and writes entirely,
falling back to plain `succ()`. Default is true.
*/
[[nodiscard]] static bool
enabled() noexcept;
static void
setEnabled(bool on) noexcept;
private:
mutable std::mutex mutex_;
std::unordered_map<Book, TopOfBookEntry> map_;
mutable std::atomic<std::uint64_t> hits_{0};
mutable std::atomic<std::uint64_t> misses_{0};
std::atomic<std::uint64_t> invalidations_{0};
};
} // namespace xrpl

View File

@@ -57,7 +57,7 @@ isVaultPseudoAccountFrozen(
ReadView const& view,
AccountID const& account,
MPTIssue const& mptShare,
std::uint8_t depth);
int depth);
[[nodiscard]] bool
isLPTokenFrozen(

View File

@@ -3,13 +3,8 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/detail/ApplyStateTable.h>
#include <xrpl/protocol/Book.h>
#include <xrpl/protocol/XRPAmount.h>
#include <unordered_set>
#include <utility>
#include <vector>
namespace xrpl::detail {
class ApplyViewBase : public ApplyView, public RawView
@@ -48,26 +43,6 @@ public:
[[nodiscard]] std::shared_ptr<SLE const>
read(Keylet const& k) const override;
// Top-of-book cache hooks — delegated to the wrapped base view so
// sandboxed views share the underlying open-ledger cache.
[[nodiscard]] std::optional<uint256>
topOfBookFirstPage(Book const& book) const override;
void
recordTopOfBook(Book const& book, uint256 const& firstPageKey) const override;
void
notifyOfferInserted(Book const& book, uint256 const& dirKey, uint256 const& offerKey)
const override;
void
notifyOfferDeleted(Book const& book, uint256 const& dirKey, uint256 const& offerKey)
const override;
[[nodiscard]] std::optional<std::vector<uint256>>
orderedBook(Book const& book) const override;
[[nodiscard]] std::unique_ptr<SlesType::iter_base>
slesBegin() const override;
@@ -120,45 +95,10 @@ public:
void
rawDestroyXRP(XRPAmount const& feeDrops) override;
/** Flush buffered top-of-book notifications to the wrapped base view.
Called by `Sandbox::apply` (and similar commit points) after the
state table itself has been applied. Notifications buffered during
the sandbox's lifetime are replayed against `base_` in insertion
order so the parent cache only sees changes that actually commit.
*/
void
flushTopOfBookNotifications() const;
/** Discard buffered notifications (e.g. when a sandbox is dropped
without applying). Safe to call multiple times.
*/
void
discardTopOfBookNotifications() const noexcept;
protected:
ApplyFlags flags_;
ReadView const* base_;
detail::ApplyStateTable items_;
// Top-of-book cache notifications are buffered here for the lifetime
// of the sandbox and only flushed to `base_` on `apply()`. This keeps
// rolled-back transactions (e.g. FillOrKill via the sbCancel branch
// of OfferCreate) from polluting the parent's cache.
//
// `dirtyBooks_` records every book mutated by buffered notifications;
// reads against `topOfBookFirstPage` skip the cache for these books so
// we never observe our own un-committed state. Outside of the dirty
// set, the parent's cache is trusted as usual.
struct OfferNote
{
Book book;
uint256 dirKey;
uint256 offerKey;
bool isDelete;
};
mutable std::vector<OfferNote> pendingTopOfBookNotifications_;
mutable std::unordered_set<Book> dirtyBooks_;
};
} // namespace xrpl::detail

View File

@@ -1,257 +0,0 @@
#pragma once
#include <xrpl/basics/base_uint.h>
#include <cstdint>
#include <memory>
#include <optional>
#include <vector>
namespace xrpl::detail {
/** Persistent (immutable, structurally-shared) ordered tree for the order-book
index.
A weight-balanced BST (Adams BB[α], the family used by Haskell `Data.Map`
and std::map-replacement libraries) of immutable `shared_ptr<const Node>`.
Keyed by `(dirRoot, insertSeq)`:
- `dirRoot` ascending == best-quality-first (book directory pages share a
prefix, quality is in the low bytes — lower key = better quality).
- `insertSeq` ascending within a `dirRoot` == directory append order
(the per-book monotonic counter mirrors `dirAppend`; `dirRemove`
preserves relative order, so this reproduces the directory walk
byte-for-byte).
Operations are persistent via path-copying: insert/delete reallocate only
the O(log n) nodes on the root→leaf path and SHARE every untouched subtree.
A "copy" of a tree is just copying the root `shared_ptr` — O(1) — which is
what lets the order-book index survive the open-ledger copy-on-write cheaply
and stay warm across transactions.
Immutable nodes are safe to share across threads/snapshots without locking.
*/
struct OrderTreeNode
{
uint256 dirRoot;
std::uint64_t insertSeq;
uint256 offerKey;
std::uint32_t size; // subtree node count (balance + rank)
std::shared_ptr<OrderTreeNode const> left;
std::shared_ptr<OrderTreeNode const> right;
};
using OrderTreePtr = std::shared_ptr<OrderTreeNode const>;
// Weight-balance parameters (Adams). delta bounds the size ratio between
// siblings; gamma chooses single vs double rotation.
inline constexpr std::uint32_t kOtDelta = 3;
inline constexpr std::uint32_t kOtGamma = 2;
[[nodiscard]] inline std::uint32_t
otSize(OrderTreePtr const& t) noexcept
{
return t ? t->size : 0;
}
// -1 / 0 / +1 ordering on (dirRoot, insertSeq).
[[nodiscard]] inline int
otCmp(
uint256 const& aDir,
std::uint64_t aSeq,
uint256 const& bDir,
std::uint64_t bSeq) noexcept
{
if (aDir < bDir)
return -1;
if (bDir < aDir)
return 1;
if (aSeq < bSeq)
return -1;
if (bSeq < aSeq)
return 1;
return 0;
}
[[nodiscard]] inline OrderTreePtr
otNode(
uint256 const& dir,
std::uint64_t seq,
uint256 const& off,
OrderTreePtr l,
OrderTreePtr r)
{
auto n = std::make_shared<OrderTreeNode>();
n->dirRoot = dir;
n->insertSeq = seq;
n->offerKey = off;
n->left = std::move(l);
n->right = std::move(r);
n->size = otSize(n->left) + otSize(n->right) + 1;
return n;
}
// Rebalance a node whose subtrees may violate the weight balance by one step.
[[nodiscard]] inline OrderTreePtr
otBalance(
uint256 const& dir,
std::uint64_t seq,
uint256 const& off,
OrderTreePtr const& l,
OrderTreePtr const& r)
{
auto const ln = otSize(l);
auto const rn = otSize(r);
if (ln + rn <= 1)
return otNode(dir, seq, off, l, r);
if (rn > kOtDelta * ln)
{
// Right-heavy.
auto const& rl = r->left;
auto const& rr = r->right;
if (otSize(rl) < kOtGamma * otSize(rr))
// single left rotation
return otNode(
r->dirRoot,
r->insertSeq,
r->offerKey,
otNode(dir, seq, off, l, rl),
rr);
// double left rotation
return otNode(
rl->dirRoot,
rl->insertSeq,
rl->offerKey,
otNode(dir, seq, off, l, rl->left),
otNode(r->dirRoot, r->insertSeq, r->offerKey, rl->right, rr));
}
if (ln > kOtDelta * rn)
{
// Left-heavy.
auto const& ll = l->left;
auto const& lr = l->right;
if (otSize(lr) < kOtGamma * otSize(ll))
// single right rotation
return otNode(
l->dirRoot,
l->insertSeq,
l->offerKey,
ll,
otNode(dir, seq, off, lr, r));
// double right rotation
return otNode(
lr->dirRoot,
lr->insertSeq,
lr->offerKey,
otNode(l->dirRoot, l->insertSeq, l->offerKey, ll, lr->left),
otNode(dir, seq, off, lr->right, r));
}
return otNode(dir, seq, off, l, r);
}
[[nodiscard]] inline OrderTreePtr
otInsert(OrderTreePtr const& t, uint256 const& dir, std::uint64_t seq, uint256 const& off)
{
if (!t)
return otNode(dir, seq, off, nullptr, nullptr);
int const c = otCmp(dir, seq, t->dirRoot, t->insertSeq);
if (c < 0)
return otBalance(
t->dirRoot, t->insertSeq, t->offerKey, otInsert(t->left, dir, seq, off), t->right);
if (c > 0)
return otBalance(
t->dirRoot, t->insertSeq, t->offerKey, t->left, otInsert(t->right, dir, seq, off));
// Equal key: replace payload (keys are unique in practice; never hit).
return otNode(t->dirRoot, t->insertSeq, off, t->left, t->right);
}
// Remove the minimum node of a non-null tree; write its fields into `outMin`.
[[nodiscard]] inline OrderTreePtr
otDeleteMin(OrderTreePtr const& t, OrderTreeNode& outMin)
{
if (!t->left)
{
outMin = *t;
return t->right;
}
return otBalance(
t->dirRoot, t->insertSeq, t->offerKey, otDeleteMin(t->left, outMin), t->right);
}
// Join two subtrees (all keys in l < all keys in r) by promoting r's minimum.
[[nodiscard]] inline OrderTreePtr
otGlue(OrderTreePtr const& l, OrderTreePtr const& r)
{
if (!l)
return r;
if (!r)
return l;
OrderTreeNode minN;
auto const r2 = otDeleteMin(r, minN);
return otBalance(minN.dirRoot, minN.insertSeq, minN.offerKey, l, r2);
}
[[nodiscard]] inline OrderTreePtr
otDelete(OrderTreePtr const& t, uint256 const& dir, std::uint64_t seq)
{
if (!t)
return nullptr;
int const c = otCmp(dir, seq, t->dirRoot, t->insertSeq);
if (c < 0)
return otBalance(
t->dirRoot, t->insertSeq, t->offerKey, otDelete(t->left, dir, seq), t->right);
if (c > 0)
return otBalance(
t->dirRoot, t->insertSeq, t->offerKey, t->left, otDelete(t->right, dir, seq));
return otGlue(t->left, t->right);
}
// In-order traversal: appends offer keys best-quality-first, append order
// within a level.
inline void
otInorder(OrderTreePtr const& t, std::vector<uint256>& out)
{
if (!t)
return;
otInorder(t->left, out);
out.push_back(t->offerKey);
otInorder(t->right, out);
}
// Leftmost (best) offer key.
[[nodiscard]] inline std::optional<uint256>
otFirst(OrderTreePtr t)
{
if (!t)
return std::nullopt;
while (t->left)
t = t->left;
return t->offerKey;
}
// Find the insertSeq for (dirRoot, offerKey). All nodes sharing a dirRoot form
// a contiguous in-order range that may straddle a node's two children, so when
// dirRoot matches we must check the node and both subtrees. O(level-size) worst
// case; effectively O(log n) for front deletions (crossing consumes front-first
// and the target is then the level's leftmost remaining node).
[[nodiscard]] inline std::optional<std::uint64_t>
otFindSeq(OrderTreePtr const& t, uint256 const& dir, uint256 const& off)
{
if (!t)
return std::nullopt;
if (dir < t->dirRoot)
return otFindSeq(t->left, dir, off);
if (t->dirRoot < dir)
return otFindSeq(t->right, dir, off);
if (t->offerKey == off)
return t->insertSeq;
if (auto const l = otFindSeq(t->left, dir, off))
return l;
return otFindSeq(t->right, dir, off);
}
} // namespace xrpl::detail

View File

@@ -22,14 +22,14 @@ public:
static constexpr size_t kInitialBufferSize = kilobytes(256);
RawStateTable()
: monotonicResource_{std::make_unique<boost::container::pmr::monotonic_buffer_resource>(
: monotonic_resource_{std::make_unique<boost::container::pmr::monotonic_buffer_resource>(
kInitialBufferSize)}
, items_{monotonicResource_.get()} {};
, items_{monotonic_resource_.get()} {};
RawStateTable(RawStateTable const& rhs)
: monotonicResource_{std::make_unique<boost::container::pmr::monotonic_buffer_resource>(
: monotonic_resource_{std::make_unique<boost::container::pmr::monotonic_buffer_resource>(
kInitialBufferSize)}
, items_{rhs.items_, monotonicResource_.get()}
, items_{rhs.items_, monotonic_resource_.get()}
, dropsDestroyed_{rhs.dropsDestroyed_} {};
RawStateTable(RawStateTable&&) = default;
@@ -101,7 +101,7 @@ private:
boost::container::pmr::polymorphic_allocator<std::pair<key_type const, SleAction>>>;
// monotonic_resource_ must outlive `items_`. Make a pointer so it may be
// easily moved.
std::unique_ptr<boost::container::pmr::monotonic_buffer_resource> monotonicResource_;
std::unique_ptr<boost::container::pmr::monotonic_buffer_resource> monotonic_resource_;
items_t items_;
XRPAmount dropsDestroyed_{0};

View File

@@ -4,38 +4,8 @@
#include <xrpl/protocol/Rules.h>
#include <xrpl/protocol/st.h>
#include <string_view>
namespace xrpl {
/**
* Broker cover preclaim precision guard (fixCleanup3_2_0).
*
* Prevents a "silent sub-ULP no-op" where a deposit, withdrawal, or clawback
* amount is so small that it rounds to zero at `sfCoverAvailable`'s scale.
* Without this guard, both the pseudo trust-line and `sfCoverAvailable` would
* identically absorb the rounded zero, resulting in a successful transaction
* (tesSUCCESS) where no funds actually moved.
*
* @param view Read view (rules used for amendment gating).
* @param sleBroker The loan broker SLE (read-only).
* @param vaultAsset The underlying vault asset (the broker's cover asset).
* @param amount The effective subtraction/addition amount.
* @param j Journal for logging.
* @param logPrefix Transactor name for log diagnostics.
*
* @return `tecPRECISION_LOSS` if the request rounds to zero at cover scale.
* `tesSUCCESS` if the amendment is disabled or the request is safely supra-ULP.
*/
[[nodiscard]] TER
canApplyToBrokerCover(
ReadView const& view,
SLE::const_ref sleBroker,
Asset const& vaultAsset,
STAmount const& amount,
beast::Journal j,
std::string_view logPrefix);
// Lending protocol has dependencies, so capture them here.
bool
checkLendingProtocolDependencies(Rules const& rules, STTx const& tx);
@@ -203,21 +173,6 @@ getAssetsTotalScale(SLE::const_ref vaultSle)
return scale(vaultSle->at(sfAssetsTotal), vaultSle->at(sfAsset));
}
// Compute the minimum required broker cover, rounded consistently.
// DebtTotal is a broker-level aggregate maintained at vault scale, so the
// rounding must also use vault scale — never an individual loan's scale.
inline Number
minimumBrokerCover(Number const& debtTotal, TenthBips32 coverRateMinimum, SLE::const_ref vaultSle)
{
XRPL_ASSERT(
vaultSle && vaultSle->getType() == ltVAULT, "xrpl::minimumBrokerCover : valid Vault sle");
NumberRoundModeGuard const mg(Number::RoundingMode::Upward);
return roundToAsset(
vaultSle->at(sfAsset),
tenthBipsOfValue(debtTotal, coverRateMinimum),
getAssetsTotalScale(vaultSle));
}
TER
checkLoanGuards(
Asset const& vaultAsset,

View File

@@ -27,18 +27,14 @@ isGlobalFrozen(ReadView const& view, MPTIssue const& mptIssue);
isIndividualFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue);
[[nodiscard]] bool
isFrozen(
ReadView const& view,
AccountID const& account,
MPTIssue const& mptIssue,
std::uint8_t depth = 0);
isFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue, int depth = 0);
[[nodiscard]] bool
isAnyFrozen(
ReadView const& view,
std::initializer_list<AccountID> const& accounts,
MPTIssue const& mptIssue,
std::uint8_t depth = 0);
int depth = 0);
//------------------------------------------------------------------------------
//
@@ -92,7 +88,7 @@ requireAuth(
MPTIssue const& mptIssue,
AccountID const& account,
AuthType authType = AuthType::Legacy,
std::uint8_t depth = 0);
int depth = 0);
/** Enforce account has MPToken to match its authorization.
*
@@ -108,78 +104,23 @@ enforceMPTokenAuthorization(
XRPAmount const& priorBalance,
beast::Journal j);
/** Resolve the underlying asset of a vault share.
*
* Reads sfReferenceHolding from @p sleShareIssuance to determine which
* asset the vault wraps. @p sleHolding must be the SLE that
* sfReferenceHolding points to — either an ltMPTOKEN (returns its
* MPTIssue) or an ltRIPPLE_STATE (returns its low/high Issue).
*
* @pre Both SLEs must exist and @p sleHolding must be of type ltMPTOKEN
* or ltRIPPLE_STATE. Passing any other type is undefined behaviour.
* @param sleShareIssuance MPTokenIssuance SLE for the vault share token.
* @param sleHolding SLE referenced by sfReferenceHolding.
* @return The underlying Asset (MPTIssue or Issue).
*/
[[nodiscard]] Asset
assetOfHolding(SLE const& sleShareIssuance, SLE const& sleHolding);
/** Check whether @p to may receive the given MPT from @p from.
*
* The check passes when any of the following is true:
* - @p waive is WaiveMPTCanTransfer::Yes (recovery-path exemption), or
* - @p from or @p to is the issuer, or
* - lsfMPTCanTransfer is set on the MPTokenIssuance.
*
* For vault shares (MPTokenIssuances that carry sfReferenceHolding) the
* check recurses into the underlying asset's transferability. This
* recursion is defensive; vault-of-vault-shares is rejected at vault
* creation, so in practice depth never exceeds 1.
*
* @param view Ledger state to read from.
* @param mptIssue The MPT issuance being transferred.
* @param from Sending account.
* @param to Receiving account.
* @param waive WaiveMPTCanTransfer::Yes skips the lsfMPTCanTransfer
* check. Use for recovery paths (e.g. unwinding SAV or
* Lending Protocol positions after an issuer revokes
* transferability).
* @param depth Recursion depth; bounded at kMaxAssetCheckDepth.
* @return tesSUCCESS if the transfer is allowed, tecNO_AUTH otherwise.
/** Check if the destination account is allowed
* to receive MPT. Return tecNO_AUTH if it doesn't
* and tesSUCCESS otherwise.
*/
[[nodiscard]] TER
canTransfer(
ReadView const& view,
MPTIssue const& mptIssue,
AccountID const& from,
AccountID const& to,
WaiveMPTCanTransfer waive = WaiveMPTCanTransfer::No,
std::uint8_t depth = 0);
/** Check whether @p asset may be traded on the DEX.
*
* For IOU assets the check delegates to the existing offer/AMM freeze
* logic. For MPT assets it checks lsfMPTCanTrade on the MPTokenIssuance.
* Vault shares recurse into the underlying asset's tradability via
* sfReferenceHolding; depth is bounded at kMaxAssetCheckDepth.
*
* @param view Ledger state to read from.
* @param asset The asset to check.
* @param depth Recursion depth; bounded at kMaxAssetCheckDepth.
* @return tesSUCCESS if trading is allowed, tecNO_PERMISSION otherwise.
*/
[[nodiscard]] TER
canTrade(ReadView const& view, Asset const& asset, std::uint8_t depth = 0);
/** Convenience to combine canTrade/Transfer. Returns tesSUCCESS if Asset is Issue.
*/
[[nodiscard]] TER
canMPTTradeAndTransfer(
ReadView const& v,
Asset const& asset,
AccountID const& from,
AccountID const& to);
/** Check if Asset can be traded on DEX. return tecNO_PERMISSION
* if it doesn't and tesSUCCESS otherwise.
*/
[[nodiscard]] TER
canTrade(ReadView const& view, Asset const& asset);
//------------------------------------------------------------------------------
//
// Empty holding operations (MPT-specific)
@@ -286,4 +227,17 @@ issuerFundsToSelfIssue(ReadView const& view, MPTIssue const& issue);
void
issuerSelfDebitHookMPT(ApplyView& view, MPTIssue const& issue, std::uint64_t amount);
//------------------------------------------------------------------------------
//
// MPT DEX
//
//------------------------------------------------------------------------------
/* Return true if a transaction is allowed for the specified MPT/account. The
* function checks MPTokenIssuance and MPToken objects flags to determine if the
* transaction is allowed.
*/
TER
checkMPTTxAllowed(ReadView const& v, TxType tx, Asset const& asset, AccountID const& accountID);
} // namespace xrpl

View File

@@ -93,7 +93,7 @@ isFrozen(ReadView const& view, AccountID const& account, Issue const& issue)
// Overload with depth parameter for uniformity with MPTIssue version.
// The depth parameter is ignored for IOUs since they don't have vault recursion.
[[nodiscard]] inline bool
isFrozen(ReadView const& view, AccountID const& account, Issue const& issue, std::uint8_t /*depth*/)
isFrozen(ReadView const& view, AccountID const& account, Issue const& issue, int /*depth*/)
{
return isFrozen(view, account, issue);
}
@@ -110,7 +110,7 @@ isDeepFrozen(
ReadView const& view,
AccountID const& account,
Issue const& issue,
std::uint8_t = 0 /*ignored*/)
int = 0 /*ignored*/)
{
return isDeepFrozen(view, account, issue.currency, issue.account);
}

View File

@@ -34,15 +34,6 @@ enum class WaiveTransferFee : bool { No = false, Yes };
/** Controls whether accountSend is allowed to overflow OutstandingAmount **/
enum class AllowMPTOverflow : bool { No = false, Yes };
/** Controls whether canTransfer enforces lsfMPTCanTransfer on MPTs.
*
* Default is No (enforce). Use Yes at call sites that must remain available
* even when an MPT issuer has cleared lsfMPTCanTransfer - for example,
* unwinding existing positions in SAV or the Lending Protocol. Has no
* effect on the IOU branch of canTransfer.
*/
enum class WaiveMPTCanTransfer : bool { No = false, Yes };
/* Check if MPToken (for MPT) or trust line (for IOU) exists:
* - StrongAuth - before checking if authorization is required
* - WeakAuth
@@ -63,26 +54,16 @@ enum class AuthType { StrongAuth, WeakAuth, Legacy };
[[nodiscard]] bool
isGlobalFrozen(ReadView const& view, Asset const& asset);
[[nodiscard]] TER
checkGlobalFrozen(ReadView const& view, Asset const& asset);
[[nodiscard]] bool
isIndividualFrozen(ReadView const& view, AccountID const& account, Asset const& asset);
[[nodiscard]] TER
checkIndividualFrozen(ReadView const& view, AccountID const& account, Asset const& asset);
/**
* isFrozen check is recursive for MPT shares in a vault, descending to
* assets in the vault, up to maxAssetCheckDepth recursion depth. This is
* purely defensive, as we currently do not allow such vaults to be created.
*/
[[nodiscard]] bool
isFrozen(
ReadView const& view,
AccountID const& account,
Asset const& asset,
std::uint8_t depth = 0);
isFrozen(ReadView const& view, AccountID const& account, Asset const& asset, int depth = 0);
[[nodiscard]] TER
checkFrozen(ReadView const& view, AccountID const& account, Issue const& issue);
@@ -104,14 +85,14 @@ isAnyFrozen(
ReadView const& view,
std::initializer_list<AccountID> const& accounts,
Asset const& asset,
std::uint8_t depth = 0);
int depth = 0);
[[nodiscard]] bool
isDeepFrozen(
ReadView const& view,
AccountID const& account,
MPTIssue const& mptIssue,
std::uint8_t depth = 0);
int depth = 0);
/**
* isFrozen check is recursive for MPT shares in a vault, descending to
@@ -119,11 +100,7 @@ isDeepFrozen(
* purely defensive, as we currently do not allow such vaults to be created.
*/
[[nodiscard]] bool
isDeepFrozen(
ReadView const& view,
AccountID const& account,
Asset const& asset,
std::uint8_t depth = 0);
isDeepFrozen(ReadView const& view, AccountID const& account, Asset const& asset, int depth = 0);
[[nodiscard]] TER
checkDeepFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue);
@@ -257,13 +234,7 @@ requireAuth(
AuthType authType = AuthType::Legacy);
[[nodiscard]] TER
canTransfer(
ReadView const& view,
Asset const& asset,
AccountID const& from,
AccountID const& to,
WaiveMPTCanTransfer waive = WaiveMPTCanTransfer::No,
std::uint8_t depth = 0);
canTransfer(ReadView const& view, Asset const& asset, AccountID const& from, AccountID const& to);
//------------------------------------------------------------------------------
//

View File

@@ -1,7 +1,5 @@
#pragma once
#include <xrpl/ledger/ReadView.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STLedgerEntry.h>
@@ -45,14 +43,6 @@ sharesToAssetsDeposit(
/** Controls whether to truncate shares instead of rounding. */
enum class TruncateShares : bool { No = false, Yes = true };
/** Controls whether the withdraw conversion helpers
(assetsToSharesWithdraw and sharesToAssetsWithdraw) subtract
sfLossUnrealized from sfAssetsTotal before computing the exchange rate.
The default (No) applies the standard discounted rate; Yes is used when
the redeemer is the sole remaining shareholder.
*/
enum class WaiveUnrealizedLoss : bool { No = false, Yes = true };
/** From the perspective of a vault, return the number of shares to demand from
the depositor when they ask to withdraw a fixed amount of assets. Since
shares are MPT this number is integral, and it will be rounded to nearest
@@ -62,8 +52,6 @@ enum class WaiveUnrealizedLoss : bool { No = false, Yes = true };
@param issuance The MPTokenIssuance SLE for the vault's shares.
@param assets The amount of assets to convert.
@param truncate Whether to truncate instead of rounding.
@param waive Whether to waive the unrealized-loss discount when computing
the exchange rate.
@return The number of shares, or nullopt on error.
*/
@@ -72,8 +60,7 @@ assetsToSharesWithdraw(
std::shared_ptr<SLE const> const& vault,
std::shared_ptr<SLE const> const& issuance,
STAmount const& assets,
TruncateShares truncate = TruncateShares::No,
WaiveUnrealizedLoss waive = WaiveUnrealizedLoss::No);
TruncateShares truncate = TruncateShares::No);
/** From the perspective of a vault, return the number of assets to give the
depositor when they redeem a fixed amount of shares. Note, since shares are
@@ -82,8 +69,6 @@ assetsToSharesWithdraw(
@param vault The vault SLE.
@param issuance The MPTokenIssuance SLE for the vault's shares.
@param shares The amount of shares to convert.
@param waive Whether to waive (i.e. not subtract) the vault's unrealized
loss when computing the exchange rate.
@return The number of assets, or nullopt on error.
*/
@@ -91,22 +76,6 @@ assetsToSharesWithdraw(
sharesToAssetsWithdraw(
std::shared_ptr<SLE const> const& vault,
std::shared_ptr<SLE const> const& issuance,
STAmount const& shares,
WaiveUnrealizedLoss waive = WaiveUnrealizedLoss::No);
/** Returns true iff `account` holds all of the vault's outstanding shares —
i.e. is the sole remaining shareholder. Returns false if the account
holds no shares or fewer than the total outstanding.
@param view The ledger view.
@param account The candidate sole shareholder.
@param issuance The MPTokenIssuance SLE for the vault's shares; provides
both the share MPTID and the outstanding-amount total.
*/
[[nodiscard]] bool
isSoleShareholder(
ReadView const& view,
AccountID const& account,
std::shared_ptr<SLE const> const& issuance);
STAmount const& shares);
} // namespace xrpl

View File

@@ -21,13 +21,13 @@ public:
bool sslVerify,
beast::Journal j,
boost::asio::ssl::context_base::method method = boost::asio::ssl::context::sslv23)
: sslContext_{method}, j_(j), verify_{sslVerify}
: ssl_context_{method}, j_(j), verify_{sslVerify}
{
boost::system::error_code ec;
if (sslVerifyFile.empty())
{
registerSSLCerts(sslContext_, ec, j_);
registerSSLCerts(ssl_context_, ec, j_);
if (ec && sslVerifyDir.empty())
{
@@ -37,12 +37,12 @@ public:
}
else
{
sslContext_.load_verify_file(sslVerifyFile);
ssl_context_.load_verify_file(sslVerifyFile);
}
if (!sslVerifyDir.empty())
{
sslContext_.add_verify_path(sslVerifyDir, ec);
ssl_context_.add_verify_path(sslVerifyDir, ec);
if (ec)
{
@@ -55,7 +55,7 @@ public:
boost::asio::ssl::context&
context()
{
return sslContext_;
return ssl_context_;
}
[[nodiscard]] bool
@@ -153,7 +153,7 @@ public:
}
private:
boost::asio::ssl::context sslContext_;
boost::asio::ssl::context ssl_context_;
beast::Journal const j_;
bool const verify_;
};

View File

@@ -83,6 +83,10 @@ public:
virtual Status
fetch(uint256 const& hash, std::shared_ptr<NodeObject>* pObject) = 0;
/** Fetch a batch synchronously. */
virtual std::pair<std::vector<std::shared_ptr<NodeObject>>, Status>
fetchBatch(std::vector<uint256> const& hashes) = 0;
/** Store a single object.
Depending on the implementation this may happen immediately
or deferred using a scheduled task.

View File

@@ -67,6 +67,9 @@ public:
backend_->sync();
}
std::vector<std::shared_ptr<NodeObject>>
fetchBatch(std::vector<uint256> const& hashes);
void
asyncFetch(
uint256 const& hash,

View File

@@ -140,8 +140,8 @@ private:
using issue_hasher = std::hash<xrpl::Issue>;
using mptissue_hasher = std::hash<xrpl::MPTIssue>;
issue_hasher mIssueHasher_;
mptissue_hasher mMptissueHasher_;
issue_hasher m_issue_hasher_;
mptissue_hasher m_mptissue_hasher_;
public:
explicit hash() = default;
@@ -151,11 +151,11 @@ public:
{
return asset.visit(
[&](xrpl::Issue const& issue) {
value_type const result(mIssueHasher_(issue));
value_type const result(m_issue_hasher_(issue));
return result;
},
[&](xrpl::MPTIssue const& issue) {
value_type const result(mMptissueHasher_(issue));
value_type const result(m_mptissue_hasher_(issue));
return result;
});
}
@@ -170,8 +170,8 @@ private:
using asset_hasher = std::hash<xrpl::Asset>;
using uint256_hasher = xrpl::uint256::hasher;
asset_hasher issueHasher_;
uint256_hasher uint256Hasher_;
asset_hasher issue_hasher_;
uint256_hasher uint256_hasher_;
public:
hash() = default;
@@ -182,11 +182,11 @@ public:
value_type
operator()(argument_type const& value) const
{
value_type result(issueHasher_(value.in));
boost::hash_combine(result, issueHasher_(value.out));
value_type result(issue_hasher_(value.in));
boost::hash_combine(result, issue_hasher_(value.out));
if (value.domain)
boost::hash_combine(result, uint256Hasher_(*value.domain));
boost::hash_combine(result, uint256_hasher_(*value.domain));
return result;
}

View File

@@ -172,24 +172,24 @@ struct ErrorInfo
{
// Default ctor needed to produce an empty std::array during constexpr eval.
constexpr ErrorInfo()
: code(RpcUnknown), token("unknown"), message("An unknown error code."), httpStatus(200)
: code(RpcUnknown), token("unknown"), message("An unknown error code."), http_status(200)
{
}
constexpr ErrorInfo(ErrorCodeI code, char const* token, char const* message)
: code(code), token(token), message(message), httpStatus(200)
: code(code), token(token), message(message), http_status(200)
{
}
constexpr ErrorInfo(ErrorCodeI code, char const* token, char const* message, int httpStatus)
: code(code), token(token), message(message), httpStatus(httpStatus)
: code(code), token(token), message(message), http_status(httpStatus)
{
}
ErrorCodeI code;
json::StaticString token;
json::StaticString message;
int httpStatus;
int http_status;
};
/** Returns an ErrorInfo that reflects the error code. */

View File

@@ -122,17 +122,4 @@ private:
std::optional<Rules> saved_;
};
class NumberSO;
class NumberMantissaScaleGuard;
bool
useRulesGuards(Rules const& rules);
void
createGuards(
Rules const& rules,
std::optional<NumberSO>& stNumberSO,
std::optional<CurrentTransactionRulesGuard>& rulesGuard,
std::optional<NumberMantissaScaleGuard>& mantissaScaleGuard);
} // namespace xrpl

View File

@@ -365,8 +365,8 @@ using SF_XCHAIN_BRIDGE = TypedField<STXChainBridge>;
#define UNTYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) extern SField const sfName;
#define TYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) extern SF_##stiSuffix const sfName;
extern SField const sfInvalid; // NOLINT(readability-identifier-naming)
extern SField const sfGeneric; // NOLINT(readability-identifier-naming)
extern SField const kSfInvalid;
extern SField const kSfGeneric;
#include <xrpl/protocol/detail/sfields.macro>

View File

@@ -3,13 +3,11 @@
#include <xrpl/basics/CountedObject.h>
#include <xrpl/basics/LocalValue.h>
#include <xrpl/basics/Number.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/protocol/Asset.h>
#include <xrpl/protocol/IOUAmount.h>
#include <xrpl/protocol/Issue.h>
#include <xrpl/protocol/MPTAmount.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STBase.h>
#include <xrpl/protocol/Serializer.h>
@@ -186,23 +184,6 @@ public:
[[nodiscard]] STAmount const&
value() const noexcept;
/**
* Checks if this amount evaluates to zero when constrained to a specific
* accounting scale.
* For XRP and MPT `roundToScale` is a no-op, returns true only when the amount itself is zero.
* The `scale` argument is ignored in that case.
* For IOU, the amount is rounded to the given scale using Number::RoundingMode::ToNearest mode
* and the result is checked for zero; if `scale <= exponent()`, `roundToScale` short-circuits
* and returns the value unchanged, so this returns false for any non-zero amount.
*
* @param scale The target accounting scale to evaluate against.
* @return `true` if this amount rounds to zero at the given scale, `false` otherwise.
*
* @see roundToScale
*/
[[nodiscard]] bool
isZeroAtScale(int scale) const;
//--------------------------------------------------------------------------
//
// Operators
@@ -559,7 +540,7 @@ STAmount::fromNumber(A const& a, Number const& number)
return STAmount{asset, intValue, 0, negative};
}
auto const [mantissa, exponent] = working.normalizeToRange<kMinValue, kMaxValue>();
auto const [mantissa, exponent] = working.normalizeToRange(kMinValue, kMaxValue);
return STAmount{asset, mantissa, exponent, negative};
}
@@ -594,25 +575,12 @@ STAmount::value() const noexcept
return *this;
}
[[nodiscard]] inline bool
inline bool
isLegalNet(STAmount const& value)
{
return !value.native() || (value.mantissa() <= STAmount::kMaxNativeN);
}
[[nodiscard]] inline bool
isLegalMPT(STAmount const& value)
{
return !value.holds<MPTIssue>() ||
(!value.negative() && value.exponent() == 0 && value.mantissa() <= kMaxMpTokenAmount);
}
/* Check recursively if an object has invalid MPTAmount or XRPAmount in STAmount field.
* Calls isLegalNet() and isLegalMPT().
*/
[[nodiscard]] bool
hasInvalidAmount(STBase const& field, beast::Journal j);
//------------------------------------------------------------------------------
//
// Operators

View File

@@ -24,7 +24,7 @@ public:
STBlob(SField const& f, void const* data, std::size_t size);
STBlob(SField const& f, Buffer&& b);
STBlob(SField const& n);
STBlob(SerialIter&, SField const& name = sfGeneric);
STBlob(SerialIter&, SField const& name = kSfGeneric);
[[nodiscard]] std::size_t
size() const;

View File

@@ -21,8 +21,8 @@ class STPathElement final : public CountedObject<STPathElement>
PathAsset assetID_;
AccountID issuerID_;
bool isOffer_;
std::size_t hashValue_;
bool is_offer_;
std::size_t hash_value_;
public:
// Bitwise values (typeCurrency | typeMPT)
@@ -235,9 +235,9 @@ private:
// ------------ STPathElement ------------
inline STPathElement::STPathElement() : type_(TypeNone), isOffer_(true)
inline STPathElement::STPathElement() : type_(TypeNone), is_offer_(true)
{
hashValue_ = getHash(*this);
hash_value_ = getHash(*this);
}
inline STPathElement::STPathElement(
@@ -248,11 +248,11 @@ inline STPathElement::STPathElement(
{
if (!account)
{
isOffer_ = true;
is_offer_ = true;
}
else
{
isOffer_ = false;
is_offer_ = false;
accountID_ = *account;
type_ |= TypeAccount;
XRPL_ASSERT(
@@ -272,7 +272,7 @@ inline STPathElement::STPathElement(
XRPL_ASSERT(issuerID_ != noAccount(), "xrpl::STPathElement::STPathElement : issuer is set");
}
hashValue_ = getHash(*this);
hash_value_ = getHash(*this);
}
inline STPathElement::STPathElement(
@@ -284,9 +284,9 @@ inline STPathElement::STPathElement(
, accountID_(account)
, assetID_(asset)
, issuerID_(issuer)
, isOffer_(isXRP(accountID_))
, is_offer_(isXRP(accountID_))
{
if (!isOffer_)
if (!is_offer_)
type_ |= TypeAccount;
if (forceAsset || !isXRP(assetID_))
@@ -295,7 +295,7 @@ inline STPathElement::STPathElement(
if (!isXRP(issuer))
type_ |= TypeIssuer;
hashValue_ = getHash(*this);
hash_value_ = getHash(*this);
}
inline STPathElement::STPathElement(
@@ -307,12 +307,12 @@ inline STPathElement::STPathElement(
, accountID_(account)
, assetID_(asset)
, issuerID_(issuer)
, isOffer_(isXRP(accountID_))
, is_offer_(isXRP(accountID_))
{
assetID_.visit(
[&](Currency const&) { type_ = type_ & (~Type::TypeMpt); },
[&](MPTID const&) { type_ = type_ & (~Type::TypeCurrency); });
hashValue_ = getHash(*this);
hash_value_ = getHash(*this);
}
inline auto
@@ -324,7 +324,7 @@ STPathElement::getNodeType() const
inline bool
STPathElement::isOffer() const
{
return isOffer_;
return is_offer_;
}
inline bool
@@ -404,7 +404,7 @@ STPathElement::getIssuerID() const
inline bool
STPathElement::operator==(STPathElement const& t) const
{
return (type_ & TypeAccount) == (t.type_ & TypeAccount) && hashValue_ == t.hashValue_ &&
return (type_ & TypeAccount) == (t.type_ & TypeAccount) && hash_value_ == t.hash_value_ &&
accountID_ == t.accountID_ && assetID_ == t.assetID_ && issuerID_ == t.issuerID_;
}

View File

@@ -27,7 +27,7 @@ enum class TxnSql : char {
class STTx final : public STObject, public CountedObject<STTx>
{
uint256 tid_;
TxType txType_;
TxType tx_type_;
public:
static constexpr std::size_t kMinMultiSigners = 1;
@@ -187,7 +187,7 @@ inline STTx::STTx(SerialIter&& sit) // NOLINT(cppcoreguidelines-rvalue-referenc
inline TxType
STTx::getTxnType() const
{
return txType_;
return tx_type_;
}
inline Blob

View File

@@ -15,7 +15,7 @@
// Add new amendments to the top of this list.
// Keep it sorted in reverse chronological order.
XRPL_FIX (Cleanup3_2_0, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FIX (Cleanup3_2_0, Supported::No, VoteBehavior::DefaultNo)
XRPL_FEATURE(MPTokensV2, Supported::No, VoteBehavior::DefaultNo)
XRPL_FIX (Cleanup3_1_3, Supported::Yes, VoteBehavior::DefaultYes)
XRPL_FIX (BatchInnerSigs, Supported::No, VoteBehavior::DefaultNo)

View File

@@ -400,7 +400,6 @@ LEDGER_ENTRY(ltMPTOKEN_ISSUANCE, 0x007e, MPTokenIssuance, mpt_issuance, ({
{sfPreviousTxnLgrSeq, SoeRequired},
{sfDomainID, SoeOptional},
{sfMutableFlags, SoeDefault},
{sfReferenceHolding, SoeOptional},
}))
/** A ledger object which tracks MPToken
@@ -592,7 +591,7 @@ LEDGER_ENTRY(ltLOAN, 0x0089, Loan, loan, ({
// LoanBroker.ManagementFeeRate
// The unrounded true total fee still owed to the broker.
//
// Note the "True" values may differ significantly from the tracked
// Note the the "True" values may differ significantly from the tracked
// rounded values.
{sfPaymentRemaining, SoeDefault},
{sfPeriodicPayment, SoeRequired},

View File

@@ -205,7 +205,6 @@ TYPED_SFIELD(sfParentBatchID, UINT256, 36)
TYPED_SFIELD(sfLoanBrokerID, UINT256, 37,
SField::kSmdPseudoAccount | SField::kSmdDefault)
TYPED_SFIELD(sfLoanID, UINT256, 38)
TYPED_SFIELD(sfReferenceHolding, UINT256, 39)
// number (common)
TYPED_SFIELD(sfNumber, NUMBER, 1)

View File

@@ -688,7 +688,6 @@ TRANSACTION(ttLEDGER_STATE_FIX, 53, LedgerStateFix,
({
{sfLedgerFixType, SoeRequired},
{sfOwner, SoeOptional},
{sfBookDirectory, SoeOptional},
}))
/** This transaction type creates a MPTokensIssuance instance */

View File

@@ -15,8 +15,8 @@ Generation requires a one-time setup step to create a virtual environment
and install Python dependencies, followed by running the generation target:
```bash
cmake --build . --target setup_code_gen # create venv and install dependencies (once)
cmake --build . --target code_gen # generate code
cmake --build . --target setup_code_gen # create venv and install dependencies (once)
cmake --build . --target code_gen # generate code
```
By default, `CODEGEN_VENV_DIR` points to `.venv` in the project root. The

View File

@@ -278,30 +278,6 @@ public:
{
return this->sle_->isFieldPresent(sfMutableFlags);
}
/**
* @brief Get sfReferenceHolding (SoeOptional)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_UINT256::type::value_type>
getReferenceHolding() const
{
if (hasReferenceHolding())
return this->sle_->at(sfReferenceHolding);
return std::nullopt;
}
/**
* @brief Check if sfReferenceHolding is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasReferenceHolding() const
{
return this->sle_->isFieldPresent(sfReferenceHolding);
}
};
/**
@@ -493,17 +469,6 @@ public:
return *this;
}
/**
* @brief Set sfReferenceHolding (SoeOptional)
* @return Reference to this builder for method chaining.
*/
MPTokenIssuanceBuilder&
setReferenceHolding(std::decay_t<typename SF_UINT256::type::value_type> const& value)
{
object_[sfReferenceHolding] = value;
return *this;
}
/**
* @brief Build and return the completed MPTokenIssuance wrapper.
* @param index The ledger entry index.

View File

@@ -83,32 +83,6 @@ public:
{
return this->tx_->isFieldPresent(sfOwner);
}
/**
* @brief Get sfBookDirectory (SoeOptional)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_UINT256::type::value_type>
getBookDirectory() const
{
if (hasBookDirectory())
{
return this->tx_->at(sfBookDirectory);
}
return std::nullopt;
}
/**
* @brief Check if sfBookDirectory is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasBookDirectory() const
{
return this->tx_->isFieldPresent(sfBookDirectory);
}
};
/**
@@ -175,17 +149,6 @@ public:
return *this;
}
/**
* @brief Set sfBookDirectory (SoeOptional)
* @return Reference to this builder for method chaining.
*/
LedgerStateFixBuilder&
setBookDirectory(std::decay_t<typename SF_UINT256::type::value_type> const& value)
{
object_[sfBookDirectory] = value;
return *this;
}
/**
* @brief Build and return the LedgerStateFix wrapper.
* @param publicKey The public key for signing.

View File

@@ -21,7 +21,7 @@ struct Entry : public beast::List<Entry>::Node
@param now Construction time of Entry.
*/
explicit Entry(clock_type::time_point const now)
: refcount(0), localBalance(now), remoteBalance(0)
: refcount(0), local_balance(now), remote_balance(0)
{
}
@@ -46,7 +46,7 @@ struct Entry : public beast::List<Entry>::Node
int
balance(clock_type::time_point const now)
{
return localBalance.value(now) + remoteBalance;
return local_balance.value(now) + remote_balance;
}
// Add a charge and return normalized balance
@@ -54,7 +54,7 @@ struct Entry : public beast::List<Entry>::Node
int
add(int charge, clock_type::time_point const now)
{
return localBalance.add(charge, now) + remoteBalance;
return local_balance.add(charge, now) + remote_balance;
}
// The public key of the peer
@@ -67,10 +67,10 @@ struct Entry : public beast::List<Entry>::Node
int refcount;
// Exponentially decaying balance of resource consumption
DecayingSample<kDecayWindowSeconds, clock_type> localBalance;
DecayingSample<kDecayWindowSeconds, clock_type> local_balance;
// Normalized balance contribution from imports
int remoteBalance;
int remote_balance;
// Time of the last warning
clock_type::time_point lastWarningTime;

View File

@@ -25,11 +25,11 @@ struct Key
std::size_t
operator()(Key const& v) const
{
return addrHash_(v.address);
return addr_hash_(v.address);
}
private:
beast::Uhash<> addrHash_;
beast::Uhash<> addr_hash_;
};
struct KeyEqual

View File

@@ -194,34 +194,34 @@ public:
for (auto& inboundEntry : inbound_)
{
int const localBalance = inboundEntry.localBalance.value(now);
if ((localBalance + inboundEntry.remoteBalance) >= threshold)
int const localBalance = inboundEntry.local_balance.value(now);
if ((localBalance + inboundEntry.remote_balance) >= threshold)
{
json::Value& entry = (ret[inboundEntry.toString()] = json::ValueType::Object);
entry[jss::local] = localBalance;
entry[jss::remote] = inboundEntry.remoteBalance;
entry[jss::remote] = inboundEntry.remote_balance;
entry[jss::type] = "inbound";
}
}
for (auto& outboundEntry : outbound_)
{
int const localBalance = outboundEntry.localBalance.value(now);
if ((localBalance + outboundEntry.remoteBalance) >= threshold)
int const localBalance = outboundEntry.local_balance.value(now);
if ((localBalance + outboundEntry.remote_balance) >= threshold)
{
json::Value& entry = (ret[outboundEntry.toString()] = json::ValueType::Object);
entry[jss::local] = localBalance;
entry[jss::remote] = outboundEntry.remoteBalance;
entry[jss::remote] = outboundEntry.remote_balance;
entry[jss::type] = "outbound";
}
}
for (auto& adminEntry : admin_)
{
int const localBalance = adminEntry.localBalance.value(now);
if ((localBalance + adminEntry.remoteBalance) >= threshold)
int const localBalance = adminEntry.local_balance.value(now);
if ((localBalance + adminEntry.remote_balance) >= threshold)
{
json::Value& entry = (ret[adminEntry.toString()] = json::ValueType::Object);
entry[jss::local] = localBalance;
entry[jss::remote] = adminEntry.remoteBalance;
entry[jss::remote] = adminEntry.remote_balance;
entry[jss::type] = "admin";
}
}
@@ -242,7 +242,7 @@ public:
for (auto& inboundEntry : inbound_)
{
Gossip::Item item;
item.balance = inboundEntry.localBalance.value(now);
item.balance = inboundEntry.local_balance.value(now);
if (item.balance >= kMinimumGossipBalance)
{
item.address = inboundEntry.key->address;
@@ -278,7 +278,7 @@ public:
Import::Item item;
item.balance = gossipItem.balance;
item.consumer = newInboundEndpoint(gossipItem.address);
item.consumer.entry().remoteBalance += item.balance;
item.consumer.entry().remote_balance += item.balance;
next.items.push_back(item);
}
}
@@ -295,14 +295,14 @@ public:
Import::Item item;
item.balance = gossipItem.balance;
item.consumer = newInboundEndpoint(gossipItem.address);
item.consumer.entry().remoteBalance += item.balance;
item.consumer.entry().remote_balance += item.balance;
next.items.push_back(item);
}
Import& prev(resultIt->second);
for (auto& item : prev.items)
{
item.consumer.entry().remoteBalance -= item.balance;
item.consumer.entry().remote_balance -= item.balance;
}
std::swap(next, prev);
@@ -345,7 +345,7 @@ public:
for (auto itemIter(import.items.begin()); itemIter != import.items.end();
++itemIter)
{
itemIter->consumer.entry().remoteBalance -= itemIter->balance;
itemIter->consumer.entry().remote_balance -= itemIter->balance;
}
iter = importTable_.erase(iter);
@@ -520,8 +520,8 @@ public:
item["count"] = entry.refcount;
item["name"] = entry.toString();
item["balance"] = entry.balance(now);
if (entry.remoteBalance != 0)
item["remote_balance"] = entry.remoteBalance;
if (entry.remote_balance != 0)
item["remote_balance"] = entry.remote_balance;
}
}

View File

@@ -21,7 +21,7 @@ struct Handoff
bool moved = false;
// If response is set, this determines the keep alive
bool keepAlive = false;
bool keep_alive = false;
// When set, this will be sent back
std::shared_ptr<Writer> response;

View File

@@ -30,19 +30,19 @@ struct Port
boost::asio::ip::address ip;
std::uint16_t port = 0;
std::set<std::string, boost::beast::iless> protocol;
std::vector<boost::asio::ip::network_v4> adminNetsV4;
std::vector<boost::asio::ip::network_v6> adminNetsV6;
std::vector<boost::asio::ip::network_v4> secureGatewayNetsV4;
std::vector<boost::asio::ip::network_v6> secureGatewayNetsV6;
std::vector<boost::asio::ip::network_v4> admin_nets_v4;
std::vector<boost::asio::ip::network_v6> admin_nets_v6;
std::vector<boost::asio::ip::network_v4> secure_gateway_nets_v4;
std::vector<boost::asio::ip::network_v6> secure_gateway_nets_v6;
std::string user;
std::string password;
std::string adminUser;
std::string adminPassword;
std::string sslKey;
std::string sslCert;
std::string sslChain;
std::string sslCiphers;
boost::beast::websocket::permessage_deflate pmdOptions;
std::string admin_user;
std::string admin_password;
std::string ssl_key;
std::string ssl_cert;
std::string ssl_chain;
std::string ssl_ciphers;
boost::beast::websocket::permessage_deflate pmd_options;
std::shared_ptr<boost::asio::ssl::context> context;
// How many incoming connections are allowed on this
@@ -50,7 +50,7 @@ struct Port
int limit = 0;
// Websocket disconnects if send queue exceeds this limit
std::uint16_t wsQueueLimit{};
std::uint16_t ws_queue_limit{};
// Returns `true` if any websocket protocols are specified
[[nodiscard]] bool
@@ -78,22 +78,22 @@ struct ParsedPort
std::set<std::string, boost::beast::iless> protocol;
std::string user;
std::string password;
std::string adminUser;
std::string adminPassword;
std::string sslKey;
std::string sslCert;
std::string sslChain;
std::string sslCiphers;
boost::beast::websocket::permessage_deflate pmdOptions;
std::string admin_user;
std::string admin_password;
std::string ssl_key;
std::string ssl_cert;
std::string ssl_chain;
std::string ssl_ciphers;
boost::beast::websocket::permessage_deflate pmd_options;
int limit = 0;
std::uint16_t wsQueueLimit{};
std::uint16_t ws_queue_limit{};
std::optional<boost::asio::ip::address> ip;
std::optional<std::uint16_t> port;
std::vector<boost::asio::ip::network_v4> adminNetsV4;
std::vector<boost::asio::ip::network_v6> adminNetsV6;
std::vector<boost::asio::ip::network_v4> secureGatewayNetsV4;
std::vector<boost::asio::ip::network_v6> secureGatewayNetsV6;
std::vector<boost::asio::ip::network_v4> admin_nets_v4;
std::vector<boost::asio::ip::network_v6> admin_nets_v6;
std::vector<boost::asio::ip::network_v4> secure_gateway_nets_v4;
std::vector<boost::asio::ip::network_v6> secure_gateway_nets_v6;
};
void

View File

@@ -58,13 +58,13 @@ protected:
Handler& handler_;
boost::asio::executor_work_guard<boost::asio::executor> work_;
boost::asio::strand<boost::asio::executor> strand_;
endpoint_type remoteAddress_;
endpoint_type remote_address_;
beast::Journal const journal_;
std::string id_;
std::size_t nid_;
boost::asio::streambuf readBuf_;
boost::asio::streambuf read_buf_;
http_request_type message_;
std::vector<Buffer> wq_;
std::vector<Buffer> wq2_;
@@ -73,9 +73,9 @@ protected:
bool complete_ = false;
boost::system::error_code ec_;
int requestCount_ = 0;
std::size_t bytesIn_ = 0;
std::size_t bytesOut_ = 0;
int request_count_ = 0;
std::size_t bytes_in_ = 0;
std::size_t bytes_out_ = 0;
//--------------------------------------------------------------------------
@@ -151,7 +151,7 @@ protected:
beast::IP::Endpoint
remoteAddress() override
{
return beast::IPAddressConversion::fromAsio(remoteAddress_);
return beast::IPAddressConversion::fromAsio(remote_address_);
}
http_request_type&
@@ -191,23 +191,23 @@ BaseHTTPPeer<Handler, Impl>::BaseHTTPPeer(
, handler_(handler)
, work_(boost::asio::make_work_guard(executor))
, strand_(boost::asio::make_strand(executor))
, remoteAddress_(std::move(remoteAddress))
, remote_address_(std::move(remoteAddress))
, journal_(journal)
{
readBuf_.commit(
boost::asio::buffer_copy(readBuf_.prepare(boost::asio::buffer_size(buffers)), buffers));
read_buf_.commit(
boost::asio::buffer_copy(read_buf_.prepare(boost::asio::buffer_size(buffers)), buffers));
static std::atomic<int> kSid;
nid_ = ++kSid;
id_ = std::string("#") + std::to_string(nid_) + " ";
JLOG(journal_.trace()) << id_ << "accept: " << remoteAddress_.address();
JLOG(journal_.trace()) << id_ << "accept: " << remote_address_.address();
}
template <class Handler, class Impl>
BaseHTTPPeer<Handler, Impl>::~BaseHTTPPeer()
{
handler_.onClose(session(), ec_);
JLOG(journal_.trace()) << id_ << "destroyed: " << requestCount_
<< ((requestCount_ == 1) ? " request" : " requests");
JLOG(journal_.trace()) << id_ << "destroyed: " << request_count_
<< ((request_count_ == 1) ? " request" : " requests");
}
template <class Handler, class Impl>
@@ -245,7 +245,7 @@ BaseHTTPPeer<Handler, Impl>::startTimer()
boost::beast::get_lowest_layer(impl().stream_)
.expires_after(
std::chrono::seconds(
remoteAddress_.address().is_loopback() ? kTimeoutSecondsLocal : kTimeoutSeconds));
remote_address_.address().is_loopback() ? kTimeoutSecondsLocal : kTimeoutSeconds));
}
// Convenience for discarding the error code
@@ -274,7 +274,7 @@ BaseHTTPPeer<Handler, Impl>::doRead(yield_context doYield)
complete_ = false;
error_code ec;
startTimer();
boost::beast::http::async_read(impl().stream_, readBuf_, message_, doYield[ec]);
boost::beast::http::async_read(impl().stream_, read_buf_, message_, doYield[ec]);
cancelTimer();
if (ec == boost::beast::http::error::end_of_stream)
return doClose();
@@ -296,7 +296,7 @@ BaseHTTPPeer<Handler, Impl>::onWrite(error_code const& ec, std::size_t bytesTran
return onTimer();
if (ec)
return fail(ec, "write");
bytesOut_ += bytesTransferred;
bytes_out_ += bytesTransferred;
{
std::scoped_lock const lock(mutex_);
wq2_.clear();

View File

@@ -27,7 +27,7 @@ protected:
Port const& port_;
Handler& handler_;
endpoint_type remoteAddress_;
endpoint_type remote_address_;
beast::WrappedSink sink_;
beast::Journal const j_;
@@ -65,7 +65,7 @@ BasePeer<Handler, Impl>::BasePeer(
beast::Journal journal)
: port_(port)
, handler_(handler)
, remoteAddress_(std::move(remoteAddress))
, remote_address_(std::move(remoteAddress))
, sink_(
journal.sink(),
[] {

View File

@@ -42,15 +42,15 @@ private:
/// The socket has been closed, or will close after the next write
/// finishes. Do not do any more writes, and don't try to close
/// again.
bool doClose_ = false;
bool do_close_ = false;
boost::beast::websocket::close_reason cr_;
waitable_timer timer_;
bool closeOnTimer_ = false;
bool pingActive_ = false;
bool close_on_timer_ = false;
bool ping_active_ = false;
boost::beast::websocket::ping_data payload_;
error_code ec_;
std::function<void(boost::beast::websocket::frame_type, boost::beast::string_view)>
controlCallback_;
control_callback_;
public:
template <class Body, class Headers>
@@ -85,7 +85,7 @@ public:
[[nodiscard]] boost::asio::ip::tcp::endpoint const&
remoteEndpoint() const override
{
return this->remoteAddress_;
return this->remote_address_;
}
void
@@ -173,14 +173,14 @@ BaseWSPeer<Handler, Impl>::run()
{
if (!strand_.running_in_this_thread())
return post(strand_, std::bind(&BaseWSPeer::run, impl().shared_from_this()));
impl().ws_.set_option(port().pmdOptions);
impl().ws_.set_option(port().pmd_options);
// Must manage the control callback memory outside of the `control_callback`
// function
controlCallback_ =
control_callback_ =
std::bind(&BaseWSPeer::onPingPong, this, std::placeholders::_1, std::placeholders::_2);
impl().ws_.control_callback(controlCallback_);
impl().ws_.control_callback(control_callback_);
startTimer();
closeOnTimer_ = true;
close_on_timer_ = true;
impl().ws_.set_option(boost::beast::websocket::stream_base::decorator([](auto& res) {
res.set(boost::beast::http::field::server, BuildInfo::getFullVersionString());
}));
@@ -198,9 +198,9 @@ BaseWSPeer<Handler, Impl>::send(std::shared_ptr<WSMsg> w)
{
if (!strand_.running_in_this_thread())
return post(strand_, std::bind(&BaseWSPeer::send, impl().shared_from_this(), std::move(w)));
if (doClose_)
if (do_close_)
return;
if (wq_.size() > port().wsQueueLimit)
if (wq_.size() > port().ws_queue_limit)
{
cr_.code = safeCast<decltype(cr_.code)>(boost::beast::websocket::close_code::policy_error);
cr_.reason = "Policy error: client is too slow.";
@@ -227,9 +227,9 @@ BaseWSPeer<Handler, Impl>::close(boost::beast::websocket::close_reason const& re
{
if (!strand_.running_in_this_thread())
return post(strand_, [self = impl().shared_from_this(), reason] { self->close(reason); });
if (doClose_)
if (do_close_)
return;
doClose_ = true;
do_close_ = true;
if (wq_.empty())
{
impl().ws_.async_close(
@@ -260,7 +260,7 @@ BaseWSPeer<Handler, Impl>::onWsHandshake(error_code const& ec)
{
if (ec)
return fail(ec, "on_ws_handshake");
closeOnTimer_ = false;
close_on_timer_ = false;
doRead();
}
@@ -313,7 +313,7 @@ BaseWSPeer<Handler, Impl>::onWriteFin(error_code const& ec)
if (ec)
return fail(ec, "write_fin");
wq_.pop_front();
if (doClose_)
if (do_close_)
{
impl().ws_.async_close(
cr_,
@@ -409,7 +409,7 @@ BaseWSPeer<Handler, Impl>::onPing(error_code const& ec)
{
if (ec == boost::asio::error::operation_aborted)
return;
pingActive_ = false;
ping_active_ = false;
if (!ec)
return;
fail(ec, "on_ping");
@@ -426,7 +426,7 @@ BaseWSPeer<Handler, Impl>::onPingPong(
boost::beast::string_view const p(payload_.begin());
if (payload == p)
{
closeOnTimer_ = false;
close_on_timer_ = false;
JLOG(this->j_.trace()) << "got matching pong";
}
else
@@ -444,11 +444,11 @@ BaseWSPeer<Handler, Impl>::onTimer(error_code ec)
return;
if (!ec)
{
if (!closeOnTimer_ || !pingActive_)
if (!close_on_timer_ || !ping_active_)
{
startTimer();
closeOnTimer_ = true;
pingActive_ = true;
close_on_timer_ = true;
ping_active_ = true;
// cryptographic is probably overkill..
beast::rngfill(payload_.begin(), payload_.size(), cryptoPrng());
impl().ws_.async_ping(

View File

@@ -23,6 +23,7 @@
#include <sys/resource.h>
#include <dirent.h>
#include <unistd.h>
#endif
#include <algorithm>
@@ -60,7 +61,7 @@ private:
boost::asio::io_context& ioc_;
stream_type stream_;
socket_type& socket_;
endpoint_type remoteAddress_;
endpoint_type remote_address_;
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
beast::Journal const j_;
@@ -89,19 +90,16 @@ private:
acceptor_type acceptor_;
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
bool ssl_{
port_.protocol.contains("https") || port_.protocol.contains("wss") ||
port_.protocol.contains("wss2") || port_.protocol.contains("peer")};
port_.protocol.count("https") > 0 || port_.protocol.count("wss") > 0 ||
port_.protocol.count("wss2") > 0 || port_.protocol.count("peer") > 0};
bool plain_{
port_.protocol.contains("http") || port_.protocol.contains("ws") ||
(port_.protocol.contains("ws2"))};
port_.protocol.count("http") > 0 || port_.protocol.count("ws") > 0 ||
(port_.protocol.count("ws2") != 0u)};
static constexpr std::chrono::milliseconds kInitialAcceptDelay{50};
static constexpr std::chrono::milliseconds kMaxAcceptDelay{2000};
std::chrono::milliseconds acceptDelay_{kInitialAcceptDelay};
boost::asio::steady_timer backoffTimer_;
static constexpr std::uint64_t kMaxUsedFdPercent = 70;
static constexpr std::chrono::milliseconds kFdSampleInterval{250};
clock_type::time_point fdSampleAt_;
bool cachedThrottle_{false};
std::chrono::milliseconds accept_delay_{kInitialAcceptDelay};
boost::asio::steady_timer backoff_timer_;
static constexpr double kFreeFdThreshold = 0.70;
struct FDStats
{
@@ -166,7 +164,7 @@ Door<Handler>::Detector::Detector(
, ioc_(ioc)
, stream_(std::move(stream))
, socket_(stream_.socket())
, remoteAddress_(std::move(remoteAddress))
, remote_address_(std::move(remoteAddress))
, strand_(boost::asio::make_strand(ioc_))
, j_(j)
{
@@ -201,18 +199,18 @@ Door<Handler>::Detector::doDetect(boost::asio::yield_context doYield)
if (ssl)
{
if (auto sp = ios().template emplace<SSLHTTPPeer<Handler>>(
port_, handler_, ioc_, j_, remoteAddress_, buf.data(), std::move(stream_)))
port_, handler_, ioc_, j_, remote_address_, buf.data(), std::move(stream_)))
sp->run();
return;
}
if (auto sp = ios().template emplace<PlainHTTPPeer<Handler>>(
port_, handler_, ioc_, j_, remoteAddress_, buf.data(), std::move(stream_)))
port_, handler_, ioc_, j_, remote_address_, buf.data(), std::move(stream_)))
sp->run();
return;
}
if (ec != boost::asio::error::operation_aborted)
{
JLOG(j_.trace()) << "Error detecting ssl: " << ec.message() << " from " << remoteAddress_;
JLOG(j_.trace()) << "Error detecting ssl: " << ec.message() << " from " << remote_address_;
}
}
@@ -281,8 +279,7 @@ Door<Handler>::Door(
, ioc_(ioContext)
, acceptor_(ioContext)
, strand_(boost::asio::make_strand(ioContext))
, backoffTimer_(ioContext)
, fdSampleAt_(clock_type::now() - kFdSampleInterval)
, backoff_timer_(ioContext)
{
reOpen();
}
@@ -305,7 +302,7 @@ Door<Handler>::close()
return boost::asio::post(
strand_, std::bind(&Door<Handler>::close, this->shared_from_this()));
}
backoffTimer_.cancel();
backoff_timer_.cancel();
error_code ec;
acceptor_.close(ec);
}
@@ -341,11 +338,11 @@ Door<Handler>::doAccept(boost::asio::yield_context doYield)
{
if (shouldThrottleForFds())
{
JLOG(j_.warn()) << "Throttling do_accept for " << acceptDelay_.count() << "ms.";
backoffTimer_.expires_after(acceptDelay_);
backoff_timer_.expires_after(accept_delay_);
boost::system::error_code tec;
backoffTimer_.async_wait(doYield[tec]);
acceptDelay_ = std::min(acceptDelay_ * 2, kMaxAcceptDelay);
backoff_timer_.async_wait(doYield[tec]);
accept_delay_ = std::min(accept_delay_ * 2, kMaxAcceptDelay);
JLOG(j_.warn()) << "Throttling do_accept for " << accept_delay_.count() << "ms.";
continue;
}
@@ -362,17 +359,14 @@ Door<Handler>::doAccept(boost::asio::yield_context doYield)
if (ec == boost::asio::error::no_descriptors ||
ec == boost::asio::error::no_buffer_space)
{
char const* const cause = (ec == boost::asio::error::no_descriptors)
? "too many open files"
: "kernel buffer space exhausted";
JLOG(j_.warn()) << "accept: " << cause << ". Pausing for " << acceptDelay_.count()
<< "ms.";
JLOG(j_.warn()) << "accept: Too many open files. Pausing for "
<< accept_delay_.count() << "ms.";
backoffTimer_.expires_after(acceptDelay_);
backoff_timer_.expires_after(accept_delay_);
boost::system::error_code tec;
backoffTimer_.async_wait(doYield[tec]);
backoff_timer_.async_wait(doYield[tec]);
acceptDelay_ = std::min(acceptDelay_ * 2, kMaxAcceptDelay);
accept_delay_ = std::min(accept_delay_ * 2, kMaxAcceptDelay);
}
else
{
@@ -381,7 +375,7 @@ Door<Handler>::doAccept(boost::asio::yield_context doYield)
continue;
}
acceptDelay_ = kInitialAcceptDelay;
accept_delay_ = kInitialAcceptDelay;
if (ssl_ && plain_)
{
@@ -434,15 +428,14 @@ Door<Handler>::shouldThrottleForFds()
#if BOOST_OS_WINDOWS
return false;
#else
auto const now = clock_type::now();
if (now - fdSampleAt_ < kFdSampleInterval)
return cachedThrottle_;
fdSampleAt_ = now;
auto const stats = queryFdStats();
cachedThrottle_ =
stats && stats->limit > 0 && stats->used * 100 > stats->limit * kMaxUsedFdPercent;
return cachedThrottle_;
if (!stats || stats->limit == 0)
return false;
auto const& s = *stats;
auto const free = (s.limit > s.used) ? (s.limit - s.used) : 0ull;
double const freeRatio = static_cast<double>(free) / static_cast<double>(s.limit);
return freeRatio < kFreeFdThreshold;
#endif
}

View File

@@ -82,7 +82,7 @@ template <class Handler>
void
PlainHTTPPeer<Handler>::run()
{
if (!this->handler_.onAccept(this->session(), this->remoteAddress_))
if (!this->handler_.onAccept(this->session(), this->remote_address_))
{
util::spawn(this->strand_, std::bind(&PlainHTTPPeer::doClose, this->shared_from_this()));
return;
@@ -103,7 +103,7 @@ PlainHTTPPeer<Handler>::websocketUpgrade()
auto ws = this->ios().template emplace<PlainWSPeer<Handler>>(
this->port_,
this->handler_,
this->remoteAddress_,
this->remote_address_,
std::move(this->message_),
std::move(stream_),
this->journal_);
@@ -114,20 +114,20 @@ template <class Handler>
void
PlainHTTPPeer<Handler>::doRequest()
{
++this->requestCount_;
++this->request_count_;
auto const what =
this->handler_.onHandoff(this->session(), std::move(this->message_), this->remoteAddress_);
this->handler_.onHandoff(this->session(), std::move(this->message_), this->remote_address_);
if (what.moved)
return;
boost::system::error_code ec;
if (what.response)
{
// half-close on Connection: close
if (!what.keepAlive)
if (!what.keep_alive)
socket_.shutdown(socket_type::shutdown_receive, ec);
if (ec)
return this->fail(ec, "request");
return this->write(what.response, what.keepAlive);
return this->write(what.response, what.keep_alive);
}
// Perform half-close when Connection: close and not SSL

View File

@@ -26,7 +26,7 @@ private:
using yield_context = boost::asio::yield_context;
using error_code = boost::system::error_code;
std::unique_ptr<stream_type> streamPtr_;
std::unique_ptr<stream_type> stream_ptr_;
stream_type& stream_;
socket_type& socket_;
@@ -80,8 +80,8 @@ SSLHTTPPeer<Handler>::SSLHTTPPeer(
journal,
remoteAddress,
buffers)
, streamPtr_(std::make_unique<stream_type>(middle_type(std::move(stream)), *port.context))
, stream_(*streamPtr_)
, stream_ptr_(std::make_unique<stream_type>(middle_type(std::move(stream)), *port.context))
, stream_(*stream_ptr_)
, socket_(stream_.next_layer().socket())
{
}
@@ -91,7 +91,7 @@ template <class Handler>
void
SSLHTTPPeer<Handler>::run()
{
if (!this->handler_.onAccept(this->session(), this->remoteAddress_))
if (!this->handler_.onAccept(this->session(), this->remote_address_))
{
util::spawn(this->strand_, std::bind(&SSLHTTPPeer::doClose, this->shared_from_this()));
return;
@@ -110,9 +110,9 @@ SSLHTTPPeer<Handler>::websocketUpgrade()
auto ws = this->ios().template emplace<SSLWSPeer<Handler>>(
this->port_,
this->handler_,
this->remoteAddress_,
this->remote_address_,
std::move(this->message_),
std::move(this->streamPtr_),
std::move(this->stream_ptr_),
this->journal_);
return ws;
}
@@ -124,8 +124,8 @@ SSLHTTPPeer<Handler>::doHandshake(yield_context doYield)
boost::system::error_code ec;
stream_.set_verify_mode(boost::asio::ssl::verify_none);
this->startTimer();
this->readBuf_.consume(
stream_.async_handshake(stream_type::server, this->readBuf_.data(), doYield[ec]));
this->read_buf_.consume(
stream_.async_handshake(stream_type::server, this->read_buf_.data(), doYield[ec]));
this->cancelTimer();
if (ec == boost::beast::error::timeout)
return this->onTimer();
@@ -148,13 +148,13 @@ template <class Handler>
void
SSLHTTPPeer<Handler>::doRequest()
{
++this->requestCount_;
++this->request_count_;
auto const what = this->handler_.onHandoff(
this->session(), std::move(streamPtr_), std::move(this->message_), this->remoteAddress_);
this->session(), std::move(stream_ptr_), std::move(this->message_), this->remote_address_);
if (what.moved)
return;
if (what.response)
return this->write(what.response, what.keepAlive);
return this->write(what.response, what.keep_alive);
// legacy
this->handler_.onRequest(this->session());
}

View File

@@ -28,7 +28,7 @@ class SSLWSPeer : public BaseWSPeer<Handler, SSLWSPeer<Handler>>,
using stream_type = boost::beast::ssl_stream<socket_type>;
using waitable_timer = boost::asio::basic_waitable_timer<clock_type>;
std::unique_ptr<stream_type> streamPtr_;
std::unique_ptr<stream_type> stream_ptr_;
boost::beast::websocket::stream<stream_type&> ws_;
public:
@@ -61,8 +61,8 @@ SSLWSPeer<Handler>::SSLWSPeer(
remoteEndpoint,
std::move(request),
journal)
, streamPtr_(std::move(streamPtr))
, ws_(*streamPtr_)
, stream_ptr_(std::move(streamPtr))
, ws_(*stream_ptr_)
{
}

View File

@@ -66,7 +66,7 @@ private:
Handler& handler_;
beast::Journal const j_;
boost::asio::io_context& ioContext_;
boost::asio::io_context& io_context_;
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
std::optional<boost::asio::executor_work_guard<boost::asio::io_context::executor_type>> work_;
@@ -104,7 +104,7 @@ public:
boost::asio::io_context&
getIoContext()
{
return ioContext_;
return io_context_;
}
bool
@@ -122,9 +122,9 @@ ServerImpl<Handler>::ServerImpl(
beast::Journal journal)
: handler_(handler)
, j_(journal)
, ioContext_(ioContext)
, strand_(boost::asio::make_strand(ioContext_))
, work_(std::in_place, boost::asio::make_work_guard(ioContext_))
, io_context_(ioContext)
, strand_(boost::asio::make_strand(io_context_))
, work_(std::in_place, boost::asio::make_work_guard(io_context_))
{
}
@@ -150,7 +150,7 @@ ServerImpl<Handler>::ports(std::vector<Port> const& ports)
{
ports_.push_back(port);
auto& internalPort = ports_.back();
if (auto sp = ios_.emplace<Door<Handler>>(handler_, ioContext_, internalPort, j_))
if (auto sp = ios_.emplace<Door<Handler>>(handler_, io_context_, internalPort, j_))
{
list_.push_back(sp);

View File

@@ -231,7 +231,7 @@ The `fetchNodeNT()` method goes through three phases:
will be 0.
2. If the node is not in the TreeNodeCache, we attempt to locate the node
in the historic data stored by the data base. The call to
in the historic data stored by the data base. The call to to
`fetchNodeFromDB(hash)` does that work for us.
3. Finally if a filter exists, we check if it can supply the node. This is

View File

@@ -398,15 +398,6 @@ private:
static NotTEC
preflight2(PreflightContext const& ctx);
/** Universal validations
- Valid MPTAmount and XRPAmount
Do not try to call preflightUniversal from preflight() in derived classes. See
the description of invokePreflight for details.
*/
static NotTEC
preflightUniversal(PreflightContext const& ctx);
/** Check transaction-specific invariants only.
*
* Walks every modified ledger entry via visitInvariantEntry, then
@@ -472,9 +463,6 @@ Transactor::invokePreflight(PreflightContext const& ctx)
if (auto const ret = preflight1(ctx, T::getFlagsMask(ctx)))
return ret;
if (auto const ret = preflightUniversal(ctx))
return ret;
if (auto const ret = T::preflight(ctx))
return ret;

View File

@@ -1,27 +0,0 @@
#pragma once
#include <xrpl/basics/base_uint.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/XRPAmount.h>
#include <memory>
namespace xrpl {
class ValidBookDirectory
{
bool badBookDirectory_ = false;
hash_set<uint256> rootIndexes_;
public:
void
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
};
} // namespace xrpl

View File

@@ -6,7 +6,6 @@
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/tx/invariants/AMMInvariant.h>
#include <xrpl/tx/invariants/DirectoryInvariant.h>
#include <xrpl/tx/invariants/FreezeInvariant.h>
#include <xrpl/tx/invariants/LoanBrokerInvariant.h>
#include <xrpl/tx/invariants/LoanInvariant.h>
@@ -373,21 +372,6 @@ public:
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
};
/** Verify that MPT/XRP STAmounts are canonical in any ledger entries left after the
* transaction applies.
*/
class ValidAmounts
{
std::vector<std::shared_ptr<SLE const>> afterEntries_;
public:
void
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
[[nodiscard]] bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&) const;
};
// additional invariant checks can be declared above and then added to this
// tuple
using InvariantChecks = std::tuple<
@@ -409,16 +393,13 @@ using InvariantChecks = std::tuple<
ValidMPTIssuance,
ValidPermissionedDomain,
ValidPermissionedDEX,
ValidBookDirectory,
ValidAMM,
NoModifiedUnmodifiableFields,
ValidPseudoAccounts,
ValidLoanBroker,
ValidLoan,
ValidVault,
ValidMPTPayment,
ValidAmounts,
ValidMPTTransfer>;
ValidMPTPayment>;
/**
* @brief get a tuple of all invariant checks

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