Compare commits

...

129 Commits

Author SHA1 Message Date
Denis Angell
78cdff0d45 chore: merge token-paychan into token-paychan-clawback 2026-10-07 11:02:23 -04:00
Denis Angell
d260b4be6d docs: state what the claim precision check guarantees 2026-10-07 10:57:54 -04:00
Denis Angell
a2dc3cdbb3 chore: merge token-paychan into token-paychan-clawback 2026-10-07 10:38:52 -04:00
Denis Angell
df4835d4f0 test: show IOU escrow credit rounding and the close-refund limit check 2026-10-07 10:31:12 -04:00
Denis Angell
b036761950 chore: merge token-paychan into token-paychan-clawback 2026-10-06 21:22:00 -04:00
Denis Angell
522689aea6 chore: merge develop into token-paychan 2026-10-06 21:12:40 -04:00
Denis Angell
c6dc7401ca fix: make PaymentChannelClawback delegable 2026-10-06 20:12:49 -04:00
Denis Angell
8ea30dba68 fix: move PaymentChannelClawback to transaction type 96 2026-10-06 19:50:52 -04:00
Denis Angell
f694dd9642 chore: merge token-paychan into token-paychan-clawback 2026-10-06 19:42:06 -04:00
Shawn Xie
60195e6d37 fix: Fix MPT partial payment overflow (#8302) 2026-10-06 23:16:13 +00:00
Ayaz Salikhov
3d526d456e build: Use LLVM 23 (#8522) 2026-10-06 21:19:57 +00:00
Denis Angell
795eb2fdfb test: close an expired token channel through fund without creating a holding 2026-10-06 16:28:47 -04:00
Denis Angell
e1ce7f40d8 fix: reject token channel locks that would round the source balance 2026-10-06 16:10:01 -04:00
Denis Angell
f05c9f7913 refactor: Extract escrow lock helpers and paychan test helpers (#7882)
Co-authored-by: Mayukha Vadari <mvadari@ripple.com>
2026-10-06 19:58:52 +00:00
Harshit Gupta
c2a4bc3aa1 fix: Validate vetoed parameter type in feature RPC (#7583)
Co-authored-by: Mayukha Vadari <mvadari@ripple.com>
2026-10-06 19:44:56 +00:00
Mayukha Vadari
718185e3b2 refactor: Use CheckEntry everywhere (#8349) 2026-10-06 19:26:35 +00:00
Ayaz Salikhov
1d7783bb86 build: Make conan retry with Conan Center's source backups (#8524) 2026-10-06 19:23:38 +00:00
Denis Angell
6bb9a9751d fix: check token channel remainder exactness in ValidPaymentChannel 2026-10-06 14:00:14 -04:00
Mayukha Vadari
9fd2c552f5 refactor: Use AmendmentsEntry everywhere (#8368) 2026-10-06 17:59:44 +00:00
Denis Angell
85c52c473b fix: keep the remainder exact on partial channel clawback 2026-10-06 13:51:02 -04:00
Denis Angell
f89ac907b7 chore: merge token-paychan into token-paychan-clawback 2026-10-06 13:39:18 -04:00
Denis Angell
cac9d753e1 docs: list token paychan API changes under 3.5.0 2026-10-06 13:19:57 -04:00
Denis Angell
9696e9021a refactor: move escrow and paychan helper specializations to source files 2026-10-06 13:18:28 -04:00
Denis Angell
8e82bc8de1 chore: merge develop into token-paychan 2026-10-06 13:06:44 -04:00
Denis Angell
21c4a3b02d fix: reject vault shares in token payment channels 2026-10-06 12:53:03 -04:00
Ayaz Salikhov
70b8fd301b chore: Update docker images; link Conan-built tools with a static runtime (#8520) 2026-10-06 16:47:35 +00:00
Denis Angell
6a1cb5fc1a fix: keep a token channel's unclaimed remainder exact 2026-10-06 12:38:22 -04:00
Denis Angell
b54caefc7f Merge branch 'token-paychan' into dangell7/token-paychan-clawback 2026-10-06 11:41:35 -04:00
Denis Angell
346316e9a3 fix: release the channel reserve before the token refund on close 2026-10-06 11:17:05 -04:00
Mayukha Vadari
e6564f553d refactor: Use NegativeUNLEntry everywhere (#8365) 2026-10-06 14:23:24 +00:00
Ayaz Salikhov
ed96e60ce3 build: Make clang-tools custom in Nix, to match what's being built (#8521) 2026-10-06 13:59:12 +00:00
Alex Kremer
2ebd745a1b refactor: Migrate handlers to rpc-spec (A) (#8345) 2026-10-06 13:19:20 +00:00
Denis Angell
ec20129800 fix: treat an overflowing IOU difference as inexact in isExactDifference 2026-10-06 08:13:57 -04:00
Mayukha Vadari
cfcbe45b60 test: Declare, not define, entry instantiations in SLEBase test (#8357) 2026-10-06 12:12:22 +00:00
Denis Angell
9aeb1d1cf7 Merge branch 'token-paychan' into dangell7/token-paychan-clawback 2026-10-06 08:01:27 -04:00
Denis Angell
41aeb2149a fix: treat an overflowing IOU sum as inexact in isExactSum 2026-10-05 20:27:23 -04:00
Denis Angell
489d2d84fa Merge remote-tracking branch 'origin/develop' into token-paychan 2026-10-05 20:11:45 -04:00
yinyiqian1
9cbf78ba99 test: Add more tests for granular permissions (#8459)
Co-authored-by: Bart <bthomee@users.noreply.github.com>
2026-10-05 23:18:58 +00:00
Timur Yalymov
b8d8738f81 fix: Enforce that MPT issuance flags are never cleared (#8152) 2026-10-05 23:17:36 +00:00
Timur Yalymov
63c97e719f feat: Allow lending transactions in Batch (#8244)
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Vito Tumas <5780819+Tapanito@users.noreply.github.com>
2026-10-05 23:17:26 +00:00
Mayukha Vadari
3ac26f23c7 feat: Add full support for all objects in ledger_entry (#6319)
Co-authored-by: Timur Yalymov <36795566+tyalymov@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Vito Tumas <5780819+Tapanito@users.noreply.github.com>
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2026-10-05 23:17:14 +00:00
Bart
ff9410bc56 build: Define XRPL_ASAN, XRPL_TSAN, and XRPL_UBSAN compile definitions (#8483)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-10-05 23:15:08 +00:00
Mayukha Vadari
1798262d7a refactor: Use LedgerHashesEntry everywhere (#8369) 2026-10-05 18:15:02 +00:00
Mayukha Vadari
cd633b9ac9 refactor: Use EscrowEntry everywhere (#8354) 2026-10-05 17:51:18 +00:00
Denis Angell
2faa8042e1 Merge branch 'token-paychan' into dangell7/token-paychan-clawback 2026-10-05 13:38:19 -04:00
Denis Angell
32c8893ee8 test: name the isExactSum operands so the swapped-argument check passes 2026-10-05 13:19:30 -04:00
Ayaz Salikhov
5c5f7d315a chore: Update nix flake file (#8479) 2026-10-05 16:58:41 +00:00
Mayukha Vadari
0f7493ce50 refactor: Use FeeSettingsEntry everywhere (#8370) 2026-10-05 16:56:41 +00:00
Harshit Gupta
40f61f828a fix: Add string type validation for channel_id and signature (#7582) 2026-10-05 16:55:14 +00:00
Denis Angell
d6a80f54bc fix: require an exact IOU remainder on partial channel clawback 2026-10-05 12:44:15 -04:00
Denis Angell
2102fab8f7 fix: make PaymentChannelClawback non-delegable 2026-10-05 12:22:40 -04:00
Denis Angell
6c9ed92183 Merge remote-tracking branch 'origin/token-paychan' into dangell7/token-paychan-clawback 2026-10-05 12:09:47 -04:00
Denis Angell
20b1c3efc2 fix: serialize token claim authorizations as the Amount field value 2026-10-05 11:42:45 -04:00
Denis Angell
59975e1742 fix: require an exact IOU sum when funding a payment channel 2026-10-05 11:32:36 -04:00
Mayukha Vadari
108277f4b7 test: Migrate three beast suites from beast::unit_test to gtest (#7993) 2026-10-05 15:28:05 +00:00
Denis Angell
0dc1ae9783 test: expect the large mantissa under MPTokensV2 in PayChanToken 2026-10-05 10:43:00 -04:00
Denis Angell
a5610d8443 Merge remote-tracking branch 'refs/remotes/origin/develop' into token-paychan 2026-10-05 10:31:26 -04:00
Denis Angell
0536d4f0dd fix: include optional in PayChanToken test 2026-10-05 10:29:55 -04:00
Bart
651bb207b4 refactor: Build Throw messages with std::format (#8474)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-10-03 16:45:34 +00:00
Denis Angell
41bcd23edd fix: Guard MPT channel funding against sfAmount overflow 2026-10-03 06:41:46 +00:00
Denis Angell
4dbffc8201 fix: Validate PaymentChannelClaim Amount asset independently of Balance 2026-10-03 00:26:44 +00:00
Peter Chen
c45363fd8b feat: Implement Confidential mpt holder key update (#8266) 2026-10-02 22:54:38 +00:00
Chenna Keshava B S
f1744cb76e fix: Do not block MPToken deletion on unrelated confidential balances (#8209) 2026-10-02 22:54:31 +00:00
Gregory Tsipenyuk
bcbaa4df07 fix: Enable the large Number mantissa with MPTokensV2 (#8330) 2026-10-02 21:42:14 +00:00
Denis Angell
d2ac3a0b58 Local merge develop into token-paychan 2026-10-02 21:26:19 +00:00
Alex Kremer
3cd357949c chore: Add ignore revs for recent style changes (#8463) 2026-10-02 21:21:09 +00:00
Ayaz Salikhov
a9027bb997 ci: Make release always go into stable channel (#8469) 2026-10-02 19:02:46 +00:00
Bart
0a6da4de74 test: Restore config test environment variables with a guard (#8333)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-02 18:24:41 +00:00
Ayaz Salikhov
6a05339c6c ci: Add more guardrails for merging releases back to develop (#8466) 2026-10-02 15:43:18 +00:00
Shawn Xie
0c41a87604 feat: Add MPT transaction stream to subscribe RPC (#5671) 2026-10-02 14:55:23 +00:00
Ayaz Salikhov
f5938e4097 docs: Document new release process (#8467) 2026-10-02 14:55:23 +00:00
Pratik Mankawde
c7d10c1b60 docs: Document the LedgerMaster class (#8160)
Signed-off-by: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
2026-10-02 14:50:09 +00:00
Kassaking7
84e2a155b9 fix: Paginate account_lines/offers/channels past new owner-dir types (#8274) 2026-10-02 14:48:48 +00:00
Félix
cbade49976 feat: Add lean toolchain to nix (#8186) 2026-10-02 14:48:17 +00:00
Denis Angell
80c40f099f fix: Return tesSUCCESS from PaymentChannelClawback on an already-drained channel 2026-10-01 21:05:32 +00:00
Denis Angell
830bc0d1f3 docs: Add token-enabled PaymentChannel schema changes to API-CHANGELOG 2026-10-01 20:57:24 +00:00
Denis Angell
9214e7d3fd fix: Gate MPT-denominated PaymentChannelClaim fields on featureMPTokensV1 2026-10-01 20:57:22 +00:00
Ayaz Salikhov
97fbea23cc build: Determine version based on tags only (#8457) 2026-10-01 20:52:53 +00:00
Ayaz Salikhov
e6055ddbe1 build: Push docker image for antithesis with voidstar (#8341) 2026-10-01 19:12:36 +00:00
Ayaz Salikhov
a5c76fde2d ci: Add guardrails for release backporting (#8449) 2026-10-01 13:35:58 +00:00
Ayaz Salikhov
eed6527946 style: Update pre-commit hooks (#8456) 2026-10-01 13:35:37 +00:00
Alex Kremer
ddbc5f1a24 fix: Resolve IntrusivePointer leak (#8328)
Co-authored-by: Valentin Balaschenko <13349202+vlntb@users.noreply.github.com>
2026-09-30 15:51:25 +00:00
Denis Angell
0c0a0e8794 fix: satisfy clang-tidy in token channel RPC tests 2026-09-30 11:49:52 -04:00
Denis Angell
86b3835d54 feat: accept token amounts in channel_authorize and channel_verify 2026-09-30 11:28:39 -04:00
Alex Kremer
97a1824537 chore: CamelCase for typedef/using in clang-tidy (#8177) 2026-09-30 15:17:18 +00:00
Denis Angell
7990cfb8a0 fix: drop unused SeqProxy include from TestHelpers 2026-09-30 10:43:59 -04:00
Denis Angell
c01a0539fe Merge remote-tracking branch 'origin/develop' into token-paychan 2026-09-30 10:41:48 -04:00
Denis Angell
cdfe9cb65d fix: guard paychan rate helper and share gateway locked totals 2026-09-30 10:15:21 -04:00
Ayaz Salikhov
b44c87613c release: Merge release/3.4.x into develop
Content was already merged via #8239 (rebased); this records the merge so future release/3.4.x merges don't replay it.
2026-09-30 14:08:23 +01:00
Bart
b3bbf50d40 refactor: Make the config name constants constexpr string views (#8332)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-09-30 10:50:18 +00:00
Bart
53246e5b15 fix: Count cluster traffic only from cluster members (#8319)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-09-30 10:32:25 +00:00
Bart
7e82b0660f fix: Queue a transaction hash only for peers that asked for it (#8309) 2026-09-30 10:31:21 +00:00
Bart
4a4fded2eb chore: Bump version to 3.4.0 2026-09-16 18:23:54 +02:00
yinyiqian1
c8e767afa4 fix: Reject PaymentBurn payments that cross zero balance 2026-09-16 18:23:28 +02:00
Pratik Mankawde
00eeb0a005 fix: Reject variable-length prefixes the encoder cannot write 2026-09-16 18:23:28 +02:00
Vito Tumas
a18839d92d fix: Relax MPT authorize cap for LoanSet and VaultWithdraw 2026-09-16 18:23:28 +02:00
Gregory Tsipenyuk
8c594c7ed9 fix: Skip CheckCash limit waiver for the issuer 2026-09-16 18:22:39 +02:00
Ayaz Salikhov
ebd810b184 build: Add missing script to conan package 2026-09-16 18:22:26 +02:00
Jingchen
3e4e56d6bb fix: Make calculateBaseFee exception-safe 2026-09-16 18:22:26 +02:00
Ayaz Salikhov
76da5d4475 build: Fix test installation on debian:11 due to EOL 2026-09-16 18:22:26 +02:00
Ayaz Salikhov
c0d0fd0d97 build: Add assert-enabled builds and packages 2026-09-16 18:22:26 +02:00
Timothy Banks
9aebb5ebea fix: Cap TMTransactions list size and charge fee for undeserializable transactions 2026-09-16 18:22:26 +02:00
Vito Tumas
796f2f8f1e fix: Relax Loan Invariants to allow zero-principal LoanPay transaction 2026-09-16 18:22:26 +02:00
Timothy Banks
b190f2b14f test: Add ProtocolMessage harness for testing TMPing 2026-09-16 18:22:25 +02:00
Denis Angell
9b1f98b020 Merge branch 'token-paychan' into token-paychan-clawback 2026-09-13 19:25:35 -04:00
Denis Angell
4258eca938 fix: include TestHelpers.h in PayChan_test for the Gate helper from develop 2026-09-13 19:25:35 -04:00
Denis Angell
23f44fe05c Merge branch 'token-paychan' into token-paychan-clawback
# Conflicts:
#	src/test/app/Delegate_test.cpp
2026-09-13 19:21:08 -04:00
Denis Angell
01919230a5 Merge remote-tracking branch 'origin/develop' into token-paychan 2026-09-13 19:19:33 -04:00
Timothy Banks
6099940c2c fix: Unbounded Database Seek via TMGetLedger 2026-09-04 15:32:36 +01:00
Ed Hennis
0db7b766e6 fix: Trim unknown fields when parsing incoming peer protobuf messages 2026-09-04 10:32:08 +00:00
Mayukha Vadari
ea6226b8b9 fix: Prevent simulate from updating the orderbook db 2026-09-04 06:17:43 -04:00
Timothy Banks
eae0a35415 fix: Use a hardened hash on the STPathElement 2026-09-03 17:06:27 -04:00
Denis Angell
2ba6f4cc68 Merge remote-tracking branch 'origin/develop' into token-paychan
# Conflicts:
#	include/xrpl/ledger/helpers/EscrowHelpers.h
#	src/libxrpl/tx/invariants/MPTInvariant.cpp
#	src/libxrpl/tx/transactors/escrow/EscrowCreate.cpp
#	src/libxrpl/tx/transactors/escrow/EscrowFinish.cpp
#	src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp
#	src/test/jtx/impl/TestHelpers.cpp
2026-08-31 11:35:47 -04:00
Denis Angell
c5ae59c4a0 fix: gate paychan claim MPToken invariant relaxation on featureTokenPaychan 2026-08-25 11:10:39 -04:00
Denis Angell
1e5e8ef018 feat: add PaymentChannelClawback for issuer clawback of channeled tokens 2026-08-03 12:26:45 -04:00
Denis Angell
1ac1d40d06 fix: satisfy clang-tidy include-cleaner and brace style in paychan 2026-08-03 12:26:20 -04:00
Denis Angell
fb10515cff Merge remote-tracking branch 'origin/develop' into token-paychan
# Conflicts:
#	include/xrpl/protocol/detail/features.macro
2026-08-03 11:38:43 -04:00
Denis Angell
3c85a0180f refactor: address review nits 2026-08-02 16:05:25 -04:00
Denis Angell
096fa967da fix: repair bad develop merge resolutions 2026-08-02 16:05:22 -04:00
dangell8
1ced7dc8f3 Merge branch 'develop' into token-paychan
Includes post-merge compile fixes (build-verified).
2026-07-17 15:02:03 +00:00
Denis Angell
df1458a136 test: expand token paychan transactor phase coverage 2026-07-13 19:25:43 -04:00
Denis Angell
cdd5ebf4c1 fix: validate paychan asset match in preclaim with tecWRONG_ASSET 2026-07-13 16:33:49 -04:00
Denis Angell
1a9a11fc31 style: remove includes flagged by misc-include-cleaner 2026-07-13 15:28:42 -04:00
Denis Angell
a9430d4778 style: conform doxygen comments to check-doxygen-style hook 2026-07-13 15:11:48 -04:00
Denis Angell
fed5093488 fix: adapt token paychan to develop merge helpers and sponsor reserve 2026-07-13 14:59:54 -04:00
Denis Angell
6c74fc1a7d Merge branch 'develop' into token-paychan 2026-07-13 14:05:56 -04:00
dangell8
939f8b1a49 Merge develop into token-paychan 2026-07-11 04:27:08 +00:00
Denis Angell
1f8c462c42 feat: XLS-93d Token-Enabled Payment Channels 2026-07-10 12:14:12 -04:00
Denis Angell
47df026dcc refactor: Move escrow lock/unlock helpers to EscrowHelpers.h 2026-07-10 11:55:13 -04:00
1080 changed files with 24920 additions and 10479 deletions

View File

@@ -90,6 +90,13 @@ CheckOptions:
readability-identifier-naming.ClassCase: CamelCase
readability-identifier-naming.StructCase: CamelCase
readability-identifier-naming.UnionCase: CamelCase
readability-identifier-naming.TypeAliasCase: CamelCase
readability-identifier-naming.TypedefCase: CamelCase
# Member type names mandated by std/Boost concepts. Subtrees that need more
# than these carry their own .clang-tidy (include/xrpl/{beast,basics,protocol,
# peerfinder}, src/test/beast); one-off cases use an inline NOLINT.
readability-identifier-naming.TypeAliasIgnoredRegexp: "^(const_iterator|const_reference|difference_type|duration|iterator|iterator_category|key_type|mapped_type|period|pointer|reference|rep|result_type|size_type|time_point|value_type)$"
readability-identifier-naming.TypedefIgnoredRegexp: "^(const_iterator|const_reference|difference_type|duration|iterator|iterator_category|key_type|mapped_type|period|pointer|reference|rep|result_type|size_type|time_point|value_type)$"
readability-identifier-naming.EnumCase: CamelCase
readability-identifier-naming.EnumConstantCase: CamelCase
readability-identifier-naming.ScopedEnumConstantCase: CamelCase
@@ -122,5 +129,5 @@ CheckOptions:
readability-identifier-naming.GlobalFunctionIgnoredRegexp: "^(to_string|hash_append|tuple_hash)$"
HeaderFilterRegex: '^.*/(tests?|xrpl|xrpld)/.*\.(h|hpp|ipp)$'
ExcludeHeaderFilterRegex: '^.*/protocol_autogen/.*\.(h|hpp)$'
ExcludeHeaderFilterRegex: '^.*/protocol_autogen/.*\.(h|hpp)$|^.*\.pb\.h$'
WarningsAsErrors: "*"

View File

@@ -255,6 +255,7 @@ words:
- queuable
- Raphson
- rcflags
- reencrypted
- replayer
- repodata
- repomd

4
.envrc
View File

@@ -8,3 +8,7 @@ watch_file rust-toolchain.toml
watch_dir conan
use flake
# Optional, untracked local overrides. To use a different shell, put e.g.
# `use flake .#formal-verification` in .envrc.local.
source_env_if_exists .envrc.local

View File

@@ -5,6 +5,18 @@
# This file is sorted in reverse chronological order, with the most recent commits at the top.
# The commits listed here are ignored by git blame, which is useful for formatting-only commits that would otherwise obscure the history of changes to a file.
# chore: CamelCase for typedef/using in `clang-tidy` (#8177)
97a1824537d20d82d25bf151a37a7a4532ebf085
# chore: Rename CamelCase namespaces to snake_case (#7933)
06488c1318d96f56d0536251bee08ac85fa7fdd3
# style: Unify style for all Doxygen comments (#7776)
73b6852a122854140336e6e6bc30a3a4b41aa5fd
# style: More clang-tidy identifier renaming (#7290)
a830ab10efed8d3e59ef2fc15d66efdf9c6bb0d8
# refactor: Rename static constants (#7120)
5b6e8b6f93b19c1e3f6a3467a25639031d9d9a53
# chore: More fixes for bad renames (#7092)
7afdd71a54d562b32a50b29a5aa00bb997dc9053
# refactor: Enable clang-tidy `readability-identifier-naming` check (#6571)
8995564ed6b9e453e144bb663303072a3c1ba305
# refactor: Enable remaining clang-tidy `cppcoreguidelines` checks (#6538)

View File

@@ -44,4 +44,12 @@ runs:
--conf:all tools.build:jobs=${BUILD_NPROC} \
--conf:all tools.build:verbosity="${LOG_VERBOSITY}" \
--conf:all tools.compilation:verbosity="${LOG_VERBOSITY}" \
.
--format=json \
. >"${RUNNER_TEMP}/conan-graph.json"
# Tools that run during the build may only load glibc from the Nix store,
# as their package ID survives a GCC runtime update.
- name: Check build-context packages for Nix store dependencies (Linux)
if: ${{ runner.os == 'Linux' }}
shell: bash
run: ./bin/check-build-context-runtime.sh "${RUNNER_TEMP}/conan-graph.json"

View File

@@ -15,30 +15,25 @@ outputs:
runs:
using: composite
steps:
# A tag names its own version. Anything else takes it from BuildInfo.cpp and
# appends the commit hash as build metadata, joined with a plus sign because a
# Conan version cannot contain two hyphens.
# A tag names its own version. Anything else is a development build named by
# its commit hash, matching what cmake/XrplVersion.cmake derives: the head of
# a pull request rather than the merge commit GitHub creates for it.
- name: Determine version
id: version
shell: bash
env:
IS_TAG: ${{ startsWith(github.ref, 'refs/tags/') }}
REF_NAME: ${{ github.ref_name }}
SHA: ${{ github.sha }}
SHA: ${{ github.event.pull_request.head.sha || github.sha }}
run: |
if [[ "${IS_TAG}" == "true" ]]; then
version="${REF_NAME}"
else
version="$(awk -F'"' '/versionString =/ { print $2 }' src/libxrpl/protocol/BuildInfo.cpp)"
if [[ -z "${version}" ]]; then
echo "Unable to read versionString from BuildInfo.cpp." >&2
exit 1
fi
version="${version}+${SHA:0:7}"
version="0.0.0-dev+${SHA:0:7}"
fi
echo "version=${version}" | tee -a "${GITHUB_OUTPUT}"
- name: Determine release channel and package release
id: release_info
uses: XRPLF/actions/release-info@ebcf6cea14eee258697308a51fea55cad777581b
uses: XRPLF/actions/release-info@a9f2eeca6fb3980ba3a84cf68566f1c69ad30674

View File

@@ -0,0 +1,40 @@
#!/usr/bin/env bash
# Exit the script as soon as an error occurs.
set -euo pipefail
# This script fails if <head> merges a release back into <base>,
# but also adds commits that aren't on a release or staging branch, see RELEASING.md.
# Merge commits are allowed.
# Usage: .github/scripts/releasing/check-merge-back-commits.sh <base> <head>
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <base> <head>"
exit 1
fi
BASE=$1
HEAD=$2
SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}")
# shellcheck source=.github/scripts/releasing/common.sh
source "${SCRIPT_DIR}/common.sh"
load_release_branches
# A PR is a merge-back if some of its commits are on a release or staging branch.
PR_COUNT=$(git rev-list --no-merges --count "${BASE}..${HEAD}")
NEW_COUNT=$(git rev-list --no-merges --count "${BASE}..${HEAD}" --not "${BRANCHES[@]}")
if ((NEW_COUNT == PR_COUNT)); then
echo "This PR doesn't merge a release back."
exit 0
fi
if ((NEW_COUNT == 0)); then
echo "This merge-back adds no commits of its own."
exit 0
fi
echo "This PR merges a release back, but also adds commits that aren't on a release or staging branch:"
git log --no-merges --format=' %h %s' "${BASE}..${HEAD}" --not "${BRANCHES[@]}"
echo
echo "Make these changes in a separate PR, see RELEASING.md."
exit 1

View File

@@ -0,0 +1,46 @@
#!/usr/bin/env bash
# Exit the script as soon as an error occurs.
set -euo pipefail
# This script fails if the commits in <base>..<head> copy commits from a release or staging branch
# (e.g. by rebasing or cherry-picking them) instead of merging that branch, see RELEASING.md.
# Commits are compared by patch-id,
# and only against release and staging commits that <head> does not already contain.
# Usage: .github/scripts/releasing/check-no-copied-release-commits.sh <base> <head>
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <base> <head>"
exit 1
fi
BASE=$1
HEAD=$2
patch_ids() {
git log --no-merges --patch --no-color --no-ext-diff "$@" | git patch-id --stable | sort
}
SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}")
# shellcheck source=.github/scripts/releasing/common.sh
source "${SCRIPT_DIR}/common.sh"
load_release_branches
# Each line is "<patch-id> <commit>".
RELEASE_PATCHES=$(patch_ids "${BRANCHES[@]}" --not "${HEAD}")
PR_PATCHES=$(patch_ids "${BASE}..${HEAD}")
# Each line is "<patch-id> <release commit> <PR commit>".
COPIES=$(join <(echo "${RELEASE_PATCHES}") <(echo "${PR_PATCHES}"))
if [ -z "${COPIES}" ]; then
echo "No copied release commits found."
exit 0
fi
echo "These commits copy release commits instead of merging them:"
while read -r _ RELEASE_COMMIT PR_COMMIT; do
echo " $(git log -1 --format='%h %s' "${PR_COMMIT}") (copies ${RELEASE_COMMIT:0:10})"
done <<<"${COPIES}"
echo
echo "Merge the release tag (or branch) instead, see RELEASING.md."
exit 1

View File

@@ -0,0 +1,38 @@
#!/usr/bin/env bash
# Exit the script as soon as an error occurs.
set -euo pipefail
# This script fails if <head> contains release or staging commits that <base> does not,
# i.e. if <head> merges a release back into <base>.
# Used in the merge queue, which squashes PRs and would drop the merge commit, see RELEASING.md.
# Usage: .github/scripts/releasing/check-no-merge-back.sh <base> <head>
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <base> <head>"
exit 1
fi
BASE=$1
HEAD=$2
SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}")
# shellcheck source=.github/scripts/releasing/common.sh
source "${SCRIPT_DIR}/common.sh"
load_release_branches
RELEASE_COMMITS=$(git rev-list "${BRANCHES[@]}" --not "${BASE}")
HEAD_COMMITS=$(git rev-list "${BASE}..${HEAD}")
# The release commits in <head>, newest first.
MERGED=$(grep -xF -f <(echo "${RELEASE_COMMITS}") <<<"${HEAD_COMMITS}" || true)
if [ -z "${MERGED}" ]; then
echo "No release commits are merged back."
exit 0
fi
echo "This PR merges $(wc -l <<<"${MERGED}" | tr -d ' ') release commits back, e.g.:"
head -5 <<<"${MERGED}" | xargs git log --no-walk --format=' %h %s'
echo
echo "Merge-backs must not go through the merge queue, which squashes them."
echo "Fast-forward develop to the PR branch instead, see RELEASING.md."
exit 1

View File

@@ -0,0 +1,46 @@
#!/usr/bin/env bash
# Exit the script as soon as an error occurs.
set -euo pipefail
# This script fails if a final release (a tag like 3.4.0) on a release branch
# is not merged back into <develop> within a few days, see RELEASING.md.
# Usage: .github/scripts/releasing/check-releases-merged.sh <develop>
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <develop>"
exit 1
fi
DEVELOP=$1
GRACE_DAYS=3
mapfile -t MERGED_ARGS < <(git for-each-ref --format='--merged=%(refname)' 'refs/remotes/*/release/*')
if [ "${#MERGED_ARGS[@]}" -eq 0 ]; then
echo "Error: No release branches found."
exit 1
fi
# Tags on a release branch that <develop> does not contain.
TAGS=$(git for-each-ref --format='%(refname:short) %(creatordate:unix)' \
"${MERGED_ARGS[@]}" --no-merged="${DEVELOP}" 'refs/tags/[0-9]*')
MISSING=0
while read -r TAG CREATED; do
if ! [[ "${TAG}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
continue
fi
if (($(date +%s) - CREATED < GRACE_DAYS * 86400)); then
echo "${TAG}: not merged yet, still within the ${GRACE_DAYS}-day grace period."
else
echo "${TAG}: not merged into develop."
MISSING=1
fi
done <<<"${TAGS}"
if [ "${MISSING}" -ne 0 ]; then
echo
echo "Merge the missing releases back into develop, see RELEASING.md."
exit 1
fi
echo "No releases past the grace period are missing from develop."

12
.github/scripts/releasing/common.sh vendored Normal file
View File

@@ -0,0 +1,12 @@
# shellcheck shell=bash
# Helpers shared by the release checks in this directory, see RELEASING.md.
# Sets BRANCHES to all release and staging branches, and fails if there are none.
load_release_branches() {
mapfile -t BRANCHES < <(git for-each-ref --format='%(refname)' 'refs/remotes/*/release/*' 'refs/remotes/*/staging/*')
if [ "${#BRANCHES[@]}" -eq 0 ]; then
echo "Error: No release or staging branches found."
exit 1
fi
}

View File

@@ -62,7 +62,7 @@ ${SED_COMMAND} -i 's@ripple/@xrpld/@g' src/test/core/Config_test.cpp
${SED_COMMAND} -i 's/Rippled/File/g' src/test/core/Config_test.cpp
# Restore the old config file name in the code that maintains support for now.
${SED_COMMAND} -i 's/kConfigLegacyName = "xrpld.cfg"/kConfigLegacyName = "rippled.cfg"/g' src/xrpld/core/detail/Config.cpp
${SED_COMMAND} -i 's/kConfigLegacyName = "xrpld.cfg"/kConfigLegacyName = "rippled.cfg"/g' src/xrpld/core/Config.h
# Restore an URL.
${SED_COMMAND} -i 's/connect-your-xrpld-to-the-xrp-test-net.html/connect-your-rippled-to-the-xrp-test-net.html/g' cfg/xrpld-example.cfg

View File

@@ -90,7 +90,7 @@ ${SED_COMMAND} -i 's/www.ripple.com/www.xrpl.org/g' src/test/protocol/Seed_test.
# Restore specific changes.
${SED_COMMAND} -i 's@b5efcc/src/xrpld@b5efcc/src/ripple@' include/xrpl/protocol/README.md
${SED_COMMAND} -i 's/dbPrefix_ = "xrpldb"/dbPrefix_ = "rippledb"/' src/xrpld/app/misc/SHAMapStoreImp.h # cspell: disable-line
${SED_COMMAND} -i 's/kConfigLegacyName = "xrpld.cfg"/kConfigLegacyName = "rippled.cfg"/' src/xrpld/core/detail/Config.cpp
${SED_COMMAND} -i 's/kConfigLegacyName = "xrpld.cfg"/kConfigLegacyName = "rippled.cfg"/' src/xrpld/core/Config.h
popd
echo "Renaming complete."

View File

@@ -1,5 +1,5 @@
{
"image_tag": "sha-060957e",
"image_tag": "sha-ed96e60",
"configs": {
"ubuntu": [
{
@@ -74,7 +74,7 @@
"extra_cmake_args": "-Dvalidator_keys=ON",
"package": {
"type": "deb",
"image": "ghcr.io/xrplf/xrpld/packaging-debian:sha-49cdc10"
"image": "ghcr.io/xrplf/xrpld/packaging-debian:sha-e6055dd"
}
},
{
@@ -86,7 +86,7 @@
"extra_cmake_args": "-Dvalidator_keys=ON -Dassert=ON",
"package": {
"type": "deb",
"image": "ghcr.io/xrplf/xrpld/packaging-debian:sha-49cdc10",
"image": "ghcr.io/xrplf/xrpld/packaging-debian:sha-e6055dd",
"variant": "assert"
}
}
@@ -101,7 +101,7 @@
"extra_cmake_args": "-Dvalidator_keys=ON",
"package": {
"type": "rpm",
"image": "ghcr.io/xrplf/xrpld/packaging-rhel:sha-49cdc10"
"image": "ghcr.io/xrplf/xrpld/packaging-rhel:sha-e6055dd"
}
}
]

View File

@@ -13,7 +13,6 @@ on:
- "!nix/devshell.nix"
- "!nix/check-tools/**"
- "bin/default-loader-path.sh"
- "bin/install-sanitizer-libs.sh"
pull_request:
paths:
- ".github/workflows/build-nix-images.yml"

View File

@@ -5,14 +5,13 @@ on:
branches:
- develop
paths:
- ".github/workflows/build-packaging-images.yml"
- "bin/install-packaging-tools.sh"
- "package/docker/**"
- "package/images/packaging/**"
pull_request:
paths:
- ".github/workflows/build-packaging-images.yml"
- "bin/install-packaging-tools.sh"
- "package/docker/**"
- "package/images/packaging/**"
workflow_dispatch:
concurrency:
@@ -44,6 +43,6 @@ jobs:
uses: XRPLF/actions/.github/workflows/build-multiarch-image.yml@696384b292577293292daed06af0306d1b83bd7d
with:
image_name: xrpld/packaging-${{ matrix.distro.name }}
dockerfile: package/docker/Dockerfile
dockerfile: package/images/packaging/Dockerfile
base_image: ${{ matrix.distro.base_image }}
push: ${{ github.event_name == 'push' }}

View File

@@ -5,7 +5,6 @@ on:
branches:
- develop
paths:
- ".github/workflows/build-pre-commit-image.yml"
- "bin/pre-commit/Dockerfile"
- "rust-toolchain.toml"
pull_request:

View File

@@ -34,7 +34,7 @@ permissions:
jobs:
audit:
runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-060957e
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-ed96e60
permissions:
contents: read
# Needed to open an issue on scheduled failures.

View File

@@ -13,7 +13,6 @@ on:
- ready_for_review
branches:
- develop
- "release-*"
- "release/*"
- "staging/*"

View File

@@ -13,7 +13,6 @@ on:
- ready_for_review
branches:
- develop
- "release-*"
- "release/*"
- "staging/*"

View File

@@ -0,0 +1,60 @@
# This workflow checks that every final release on a release branch
# has been merged back into develop, see RELEASING.md.
name: Check releases merged
on:
schedule:
# 06:47 UTC every Monday.
- cron: "47 6 * * 1"
push:
branches:
- "develop"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
defaults:
run:
shell: bash
env:
OUTPUT_FILE: /tmp/releases-merged.txt
ISSUE_FILE: /tmp/releases-merged-issue.md
jobs:
releases-merged:
runs-on: ubuntu-latest
permissions:
contents: read
# Needed to open an issue on scheduled failures.
issues: write
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# The check needs the full history of develop, the release branches and tags.
fetch-depth: 0
- name: Check releases are merged into develop
run: |
set -o pipefail
.github/scripts/releasing/check-releases-merged.sh origin/develop | tee "${OUTPUT_FILE}"
- name: Prepare issue body
if: ${{ failure() && github.event_name == 'schedule' && github.repository == 'XRPLF/rippled' }}
run: |
{
echo '```'
cat "${OUTPUT_FILE}"
echo '```'
} >"${ISSUE_FILE}"
- name: Create issue
if: ${{ failure() && github.event_name == 'schedule' && github.repository == 'XRPLF/rippled' }}
uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712
with:
title: "Releases not merged back into develop"
body_file: ${{ env.ISSUE_FILE }}
labels: "Bug"

View File

@@ -150,6 +150,48 @@ jobs:
if: ${{ needs.should-run.outputs.go == 'true' }}
uses: ./.github/workflows/reusable-check-rename.yml
# Runs regardless of the changed files.
# PRs into staging branches are skipped, since fixes may be cherry-picked between release lines.
check-release-commits:
needs: should-run
if: ${{ github.event.pull_request.base.ref == 'develop' || github.event.merge_group.base_ref == 'refs/heads/develop' }}
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# The check needs the full history of the release and staging branches.
fetch-depth: 0
persist-credentials: false
- name: Check for copied release commits
if: ${{ github.event_name == 'pull_request' }}
env:
BASE: ${{ github.event.pull_request.base.sha }}
HEAD: ${{ github.event.pull_request.head.sha }}
run: .github/scripts/releasing/check-no-copied-release-commits.sh "${BASE}" "${HEAD}"
# Runs even if the previous check fails, so that both problems are reported at once.
- name: Check merge-back has no new commits
if: ${{ !cancelled() && github.event_name == 'pull_request' }}
env:
BASE: ${{ github.event.pull_request.base.sha }}
HEAD: ${{ github.event.pull_request.head.sha }}
run: .github/scripts/releasing/check-merge-back-commits.sh "${BASE}" "${HEAD}"
# The queue squashes PRs, so check the PR's own branch, named in the queue branch.
- name: Check the merge queue doesn't merge a release back
if: ${{ github.event_name == 'merge_group' }}
env:
BASE: ${{ github.event.merge_group.base_sha }}
HEAD_REF: ${{ github.event.merge_group.head_ref }}
run: |
if ! [[ "${HEAD_REF}" =~ /pr-([0-9]+)-[0-9a-f]+$ ]]; then
echo "Error: Can't find the PR number in '${HEAD_REF}'."
exit 1
fi
git fetch --no-tags origin "refs/pull/${BASH_REMATCH[1]}/head"
.github/scripts/releasing/check-no-merge-back.sh "${BASE}" FETCH_HEAD
clang-tidy:
needs: should-run
if: ${{ needs.should-run.outputs.go == 'true' }}
@@ -230,6 +272,7 @@ jobs:
- check-autogen
- check-levelization
- check-rename
- check-release-commits
- clang-tidy
- build-test
- rust

View File

@@ -1,9 +1,12 @@
# When a versioned tag is pushed, this workflow:
#
# - uploads the libxrpl recipe to the Conan remote
# - builds and tests the release binaries
# - uploads the libxrpl recipe to the Conan remote
# - builds the DEB and RPM packages
# - publishes those packages to the XRPLF package repositories
#
# Nothing is published unless the build passes, which is also where CMake
# rejects a tag that is not a valid version, e.g. 3.2.01.
name: Tag
on:
@@ -22,6 +25,7 @@ defaults:
jobs:
upload-recipe:
if: ${{ github.repository == 'XRPLF/rippled' }}
needs: build-test
uses: ./.github/workflows/reusable-upload-recipe.yml
secrets:
remote_username: ${{ secrets.NEXUS_REMOTE_USERNAME }}
@@ -51,3 +55,6 @@ jobs:
remote_password: ${{ secrets.NEXUS_REMOTE_PASSWORD }}
signing_key: ${{ secrets.NEXUS_PACKAGES_PRIVATE_KEY }}
dockerhub_token: ${{ secrets.DOCKERHUB_TOKEN }}
antithesis_docker_host: ${{ secrets.ANTITHESIS_DOCKER_HOST }}
antithesis_docker_path: ${{ secrets.ANTITHESIS_DOCKER_PATH }}
antithesis_docker_credentials: ${{ secrets.ANTITHESIS_DOCKER_CREDENTIALS }}

View File

@@ -130,3 +130,6 @@ jobs:
remote_password: ${{ secrets.NEXUS_REMOTE_PASSWORD }}
signing_key: ${{ secrets.NEXUS_PACKAGES_PRIVATE_KEY }}
dockerhub_token: ${{ secrets.DOCKERHUB_TOKEN }}
antithesis_docker_host: ${{ secrets.ANTITHESIS_DOCKER_HOST }}
antithesis_docker_path: ${{ secrets.ANTITHESIS_DOCKER_PATH }}
antithesis_docker_credentials: ${{ secrets.ANTITHESIS_DOCKER_CREDENTIALS }}

View File

@@ -17,4 +17,4 @@ jobs:
uses: XRPLF/actions/.github/workflows/pre-commit.yml@279ec358f4a1be4088be3e024b07916fa97c75b6
with:
runs_on: ubuntu-latest
container: '{ "image": "ghcr.io/xrplf/xrpld/pre-commit:sha-473fe44" }'
container: '{ "image": "ghcr.io/xrplf/xrpld/pre-commit:sha-3a2d19f" }'

View File

@@ -41,7 +41,7 @@ env:
jobs:
build:
runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-060957e
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-ed96e60
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

View File

@@ -196,6 +196,19 @@ jobs:
env:
BUILD_TYPE: ${{ inputs.build_type }}
CMAKE_ARGS: ${{ inputs.cmake_args }}
# GitHub creates a merge commit for a PR
# https://www.kenmuse.com/blog/the-many-shas-of-a-github-pull-request/
#
# We:
# - explicitly provide branch name
# - use `github.event.pull_request.head.sha` to get the SHA of last commit in the PR branch
#
# This way it works both for PRs and pushes to branches.
GITHUB_BRANCH_NAME: "${{ github.head_ref || github.ref_name }}"
GITHUB_HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}"
#
# If tag is being pushed, we use that version.
FORCE_XRPLD_VERSION: ${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || '' }}
run: |
cmake \
-G '${{ runner.os == 'Windows' && 'Visual Studio 18 2026' || 'Ninja' }}' \

View File

@@ -34,7 +34,7 @@ jobs:
needs: [determine-files]
if: ${{ needs.determine-files.outputs.cpp_changed_files != '' || needs.determine-files.outputs.need_full_run == 'true' }}
runs-on: ["self-hosted", "Linux", "X64", "heavy"]
container: "ghcr.io/xrplf/xrpld/nix-debian:sha-060957e"
container: "ghcr.io/xrplf/xrpld/nix-debian:sha-ed96e60"
permissions:
contents: read
issues: write

View File

@@ -9,8 +9,9 @@
# never reaches Nexus
# - 'publish' uploads with the image's publish_pkg.py, doing a --dry-run
# unless 'publish: true'
# - 'docker' builds an Ubuntu image from the tested DEB, pushing it to Docker
# Hub only with 'publish: true'
# - 'docker' builds an Ubuntu image from the tested DEB, and one with the
# voidstar binary for Antithesis, pushing them to Docker Hub and to the
# Antithesis registry only with 'publish: true'
#
# Only linux/amd64 is supported; the runner is hardcoded in the jobs below.
name: Package
@@ -37,10 +38,19 @@ on:
description: "The password or token for that Nexus account."
required: false
signing_key:
description: "Armoured PGP private key used to sign the RPMs. Required when publishing."
description: "Armoured PGP private key used to sign the RPMs."
required: false
dockerhub_token:
description: "A Docker Hub organization access token for xrplf, with push access to xrplf/xrpld. Required when publishing."
description: "A Docker Hub organization access token for xrplf, with push access to xrplf/xrpld."
required: false
antithesis_docker_host:
description: "The host of the Antithesis container registry, e.g. us-central1-docker.pkg.dev."
required: false
antithesis_docker_path:
description: "The repository path in that registry, the image name excluded."
required: false
antithesis_docker_credentials:
description: "The JSON key of a service account with push access to that repository."
required: false
defaults:
@@ -247,18 +257,35 @@ jobs:
docker:
needs: [test-install-deb, test-install-rpm]
name: "docker${{ !inputs.publish && ' (dry run)' || '' }}"
strategy:
fail-fast: false
matrix:
target: [xrpld, voidstar]
name: "docker ${{ matrix.target }}${{ !inputs.publish && ' (dry run)' || '' }}"
permissions:
contents: read
runs-on: ubuntu-latest
timeout-minutes: 5
timeout-minutes: 15
env:
IMAGE: xrplf/xrpld:${{ github.ref_type == 'tag' && github.ref_name || 'develop' }}
CONTEXT: image-context
IMAGE: ${{ matrix.target == 'voidstar' && 'xrpld-voidstar' || 'xrplf/xrpld' }}:${{ github.ref_type == 'tag' && github.ref_name || 'develop' }}
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Determine release info
id: release_info
uses: ./.github/actions/release-info
# Docker Hub is public, so it only gets builds whose packages are public:
# those of a public codebase, and stable releases.
# The Antithesis registry is private, so it gets every build.
- name: Decide whether to push
env:
PUSH: ${{ inputs.publish && (matrix.target == 'voidstar' || github.event.repository.visibility == 'public' || steps.release_info.outputs.channel == 'stable') }}
run: echo "PUSH=${PUSH}" | tee -a "${GITHUB_ENV}"
- name: Download package artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
@@ -266,13 +293,20 @@ jobs:
merge-multiple: true
path: ${{ env.PACKAGE_DIR }}
- name: Download voidstar binary
if: ${{ matrix.target == 'voidstar' }}
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: xrpld-ubuntu-clang-debug-amd64-voidstar
path: ${{ env.CONTEXT }}
- name: Build image
env:
CONTEXT: image-context
TARGET: ${{ matrix.target }}
run: |
mkdir -p "${CONTEXT}"
find "${PACKAGE_DIR}" -type f -name 'xrpld_[0-9]*.deb' -exec cp {} "${CONTEXT}/" \;
docker build --pull --file package/image/Dockerfile --tag "${IMAGE}" "${CONTEXT}"
docker build --pull --file package/images/xrpld/Dockerfile --target "${TARGET}" --tag "${IMAGE}" "${CONTEXT}"
- name: Start the server
run: |
@@ -290,14 +324,25 @@ jobs:
docker logs "${container}"
exit 1
# Docker Hub is public, so a private build never reaches it.
- name: Log in to Docker Hub
if: ${{ inputs.publish && github.event.repository.visibility == 'public' }}
if: ${{ env.PUSH == 'true' && matrix.target == 'xrpld' }}
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
username: xrplf
password: ${{ secrets.dockerhub_token }}
- name: Log in to the Antithesis registry
if: ${{ env.PUSH == 'true' && matrix.target == 'voidstar' }}
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ${{ secrets.antithesis_docker_host }}
username: _json_key
password: ${{ secrets.antithesis_docker_credentials }}
- name: Push image
if: ${{ inputs.publish && github.event.repository.visibility == 'public' }}
run: docker push "${IMAGE}"
if: ${{ env.PUSH == 'true' }}
env:
REGISTRY: ${{ matrix.target == 'voidstar' && format('{0}/{1}/', secrets.antithesis_docker_host, secrets.antithesis_docker_path) || '' }}
run: |
docker tag "${IMAGE}" "${REGISTRY}${IMAGE}"
docker push "${REGISTRY}${IMAGE}"

View File

@@ -28,7 +28,7 @@ permissions:
jobs:
clippy:
runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-060957e
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-ed96e60
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -41,7 +41,7 @@ jobs:
coverage:
runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-060957e
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-ed96e60
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -70,7 +70,7 @@ jobs:
doc:
runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-060957e
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-ed96e60
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

View File

@@ -40,7 +40,7 @@ defaults:
jobs:
upload:
runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-060957e
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-ed96e60
env:
REMOTE_NAME: ${{ inputs.remote_name }}
CONAN_LOGIN_USERNAME_XRPLF: ${{ secrets.remote_username }}

3
.gitignore vendored
View File

@@ -92,6 +92,9 @@ target/
# Direnv's directory
/.direnv
# Direnv's local, per-developer overrides
/.envrc.local
# clangd cache
/.cache

View File

@@ -60,7 +60,7 @@ repos:
types_or: [c++, c]
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: f4d7745e17a28aad7eed2f4874ca8d1568c11c4c # frozen: v22.1.8
rev: e2b496dc2bd8340c2524cb9a2d2a943cde1bb6df # frozen: v23.1.1
hooks:
- id: clang-format
args: [--style=file]
@@ -82,12 +82,12 @@ repos:
files: ^crates/.*\.rs$
- repo: https://github.com/BlankSpruce/gersemi-pre-commit
rev: e98930bdc210d3387007f9252d8c1694ea7e410f # frozen: 0.27.7
rev: f1c4833f8cf23c6d952673abc73525411a5719e8 # frozen: 0.29.1
hooks:
- id: gersemi
- repo: https://github.com/rbubley/mirrors-prettier
rev: 9337a74165b178ae2c766f60bee7252a0f06f3e8 # frozen: v3.9.5
rev: ef4a397f916211b4a39ccf9d3d9cbb6562157251 # frozen: v3.9.9
hooks:
- id: prettier
args: [--end-of-line=auto]
@@ -95,7 +95,7 @@ repos:
# Scoped to package/: the rest of the repo's Python has pre-existing findings,
# so widening these is its own change.
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 7c55798a78262d14b2074abf623d8a992ebb70d4 # frozen: v0.16.2
rev: a56c0b927e6465d37cae3e97d35d4d18ab2b96cd # frozen: v0.16.9
hooks:
- id: ruff-check
args: [--fix]
@@ -107,14 +107,14 @@ repos:
- id: black
- repo: https://github.com/pre-commit/mirrors-mypy
rev: 41e691678310dfd3833f7ab4e180ddb014310356 # frozen: v2.3.0
rev: 7ff8d35ae36a7d2b968f2f90b4c723e292e594ee # frozen: v2.3.1
hooks:
- id: mypy
args: [--strict]
files: ^package/.*\.py$
- repo: https://github.com/scop/pre-commit-shfmt
rev: 05c1426671b9237fb5e1444dd63aa5731bec0dfb # frozen: v3.13.1-1
rev: 479be5958357ba5ab65ce47172117348516860e9 # frozen: v3.14.1-1
hooks:
- id: shfmt
args: [--write, --indent=4, --case-indent=true]
@@ -133,7 +133,7 @@ repos:
files: \.md$
- repo: https://github.com/streetsidesoftware/cspell-cli
rev: ea11f9efc0bec520073405bc30552da887ba71bc # frozen: v10.0.1
rev: f5c5d72342f35643988a9ffa0705c05bd3ff8383 # frozen: v10.3.0
hooks:
- id: cspell
name: check changed files spelling

View File

@@ -22,6 +22,27 @@ API version 2 is available in `xrpld` version 2.0.0 and later. See [API-VERSION-
This version is supported by all `xrpld` versions. For WebSocket and HTTP JSON-RPC requests, it is currently the default API version used when no `api_version` is specified.
## XRP Ledger server version 3.5.0
Version 3.5.0 is not yet released.
### Additions in 3.5.0
- `subscribe`, `unsubscribe`: Added an optional `mpt_issuances` request field, an array of MPT issuance IDs (hex strings). Subscribers receive a message with `type` `mptTransaction` for each validated transaction whose metadata affects a subscribed issuance; the message has the same fields as the `transactions` stream. MPT issuance subscriptions count toward the per-connection subscription limit. An empty array, a non-array value, or an invalid ID returns `invalidParams`. ([#5671](https://github.com/XRPLF/rippled/pull/5671))
- `ledger_entry`: Add full support for checks, NFT offers, payment channels, and signer lists. ([#6319](https://github.com/XRPLF/rippled/pull/6319))
- `channel_authorize`, `channel_verify`: `amount` now also accepts the transaction `Amount` JSON object for a token payment channel (`currency`, `issuer` and `value` for a trust line token; `mpt_issuance_id` and `value` for an MPT), and the claim authorization is serialized for that token. A string of drops is still used for an XRP channel. An object that names XRP, is negative or is malformed returns `channelAmtMalformed`. On the command line, the amount argument may be that JSON object as a single argument. For a token channel the signed message is the `PaymentChannelClaim` hash prefix, the channel ID and the amount serialized as an `Amount` field value without its field header; the XRP message is unchanged. ([#7935](https://github.com/XRPLF/rippled/pull/7935))
- `PaymentChannelCreate`, `PaymentChannelFund`, `PaymentChannelClaim`: `Amount` (and `Balance` on `PaymentChannelClaim`) now accept a trust line or MPT value in addition to XRP, gated by the `TokenPaychan` amendment. ([#7935](https://github.com/XRPLF/rippled/pull/7935))
- `ledger_entry`, `account_objects`: The `PayChannel` ledger entry now includes optional `TransferRate` and `IssuerNode` fields, present on a channel funded with a trust line or MPT value. ([#7935](https://github.com/XRPLF/rippled/pull/7935))
### Bugfixes in 3.5.0
- `channel_authorize`: The `channel_id` field now returns an `invalidParams` error if the value is not a string. [#7582](https://github.com/XRPLF/rippled/pull/7582)
- `channel_verify`: The `channel_id` and `signature` fields now return an `invalidParams` error if the value is not a string. [#7582](https://github.com/XRPLF/rippled/pull/7582)
### Bugfixes in 3.5.0
- `feature`: The admin-only `vetoed` field now returns `invalidParams` unless its value is a boolean. [#7583](https://github.com/XRPLF/rippled/pull/7583)
## XRP Ledger server version 3.4.0
Version 3.4.0 is not yet released. These changes are available in the 3.4.0 beta releases.

View File

@@ -41,15 +41,19 @@ branch.
git checkout develop
```
For a release candidate, choose the relevant release branch, e.g.
`release/3.2.x`.
For a release or release candidate, check out its [tag](https://github.com/XRPLF/rippled/releases), e.g.:
```bash
git checkout release/3.2.x
git checkout 3.4.0
```
For a stable release, choose one of the [tagged
releases](https://github.com/XRPLF/rippled/releases).
See [RELEASING.md](./RELEASING.md) for how branches and releases are organized.
A build reports `0.0.0-dev` with its short commit hash as build metadata, e.g.
`0.0.0-dev+0123abc`. Only builds of a release, from a tag in CI or a versioned
Conan reference, report a release version. To use another version, set the
`FORCE_XRPLD_VERSION` environment variable when running CMake, e.g.
`FORCE_XRPLD_VERSION=3.4.0`.
### Set Up Conan

View File

@@ -77,7 +77,6 @@ endif()
include(PatchNixBinary)
include(XrplSanity)
include(XrplVersion)
include(XrplSettings)
# this check has to remain in the top-level cmake because of the early return statement
if(packages_only)

View File

@@ -14,9 +14,13 @@ The following branches exist in the main project repository:
- `develop`: The latest set of unreleased features, and the most common
starting point for contributions.
- `release/*` (e.g. `release/3.2.x`): Release branches, one per release line,
holding the latest release candidate, or stable release for that line.
Stable releases are published as [tagged releases](https://github.com/XRPLF/rippled/releases).
- `staging/*` (e.g. `staging/3.4.x`): Staging branches, one per release line,
where fixes for that line are developed.
- `release/*` (e.g. `release/3.4.x`): Release branches, one per release line,
holding the latest public release candidate or release for that line.
Releases are published as [tagged releases](https://github.com/XRPLF/rippled/releases).
See [RELEASING.md](./RELEASING.md) for how these branches are used.
The tip of each branch must be signed. In order for GitHub to sign a
squashed commit that it builds from your pull request, GitHub must know
@@ -145,8 +149,8 @@ tl;dr
In general, pull requests use `develop` as the base branch.
The exceptions are fixes, improvements, and hotfixes for an existing release,
which use that release's branch (e.g. `release/3.2.x`) as the base.
The exceptions are fixes for an existing release line,
which use that line's staging branch (e.g. `staging/3.4.x`) as the base.
If your changes are not quite ready, but you want to make it easily available
for preliminary examination or review, you can create a "Draft" pull request.
@@ -479,8 +483,12 @@ exists, then no other unit test will be executed, apart from `TestSuiteName`.
elsewhere in the codebase.
12. Use clear and self-explanatory names for functions, variables,
structs and classes.
13. Use TitleCase for classes, structs and filenames, camelCase for
function and variable names, lower case for namespaces and folders.
13. Use TitleCase for classes, structs, type aliases and filenames,
camelCase for function and variable names, lower case for namespaces and
folders. The exception is a type alias that generic code looks up by name
(`value_type`, `iterator`, `result_type`, and the rest of the standard
container, hash and clock members), which keeps its snake_case spelling;
`.clang-tidy` lists the names that are allowed.
14. Provide as many comments as you feel that a competent programmer
would need to understand what your code does.
@@ -587,15 +595,16 @@ the suggested commit message, or modify it as needed.
#### Slightly more complicated pull requests
Some pull requests need to be pushed to `develop` as more than one
commit. A PR author may _request_ to merge as separate commits. They
Some pull requests need to be pushed to their base branch (usually `develop`)
as more than one commit.
A PR author may _request_ to merge as separate commits. They
must _justify_ why separate commits are needed, and _specify_ how they
would like the commits to be merged. If you disagree with the author,
discuss it with them directly.
If the process is reasonable, follow it. The simplest option is to do a
fast forward only merge (`--ff-only`) on the command line and push to
`develop`.
fast forward only merge (`--ff-only`) on the command line
and push to the base branch.
Some examples of when separate commits are worthwhile are:
@@ -608,9 +617,10 @@ Some examples of when separate commits are worthwhile are:
Either way, check that:
- The commits are based on the current tip of `develop`.
- The commits are clean: No merge commits (except when reverse
merging), no "[FOLD]" or "fixup!" messages.
- The commits are based on the current tip of the base branch.
- The commits are clean:
No merge commits (except when merging a release, see [RELEASING.md](./RELEASING.md)),
no "[FOLD]" or "fixup!" messages.
- All commits are signed. If the commits are not signed by the author, use
`git commit --amend -S` to sign them yourself.
- At least one (but preferably all) of the commits has the PR number
@@ -622,578 +632,8 @@ use them!**
### Releases
All releases, including release candidates and betas, are handled
differently from typical PRs. Most importantly, never use
the Github UI to merge a release.
Xrpld uses a linear workflow model that can be summarized as:
1. In between releases, developers work against the `develop` branch.
2. Periodically, a maintainer will build and tag a beta version from
`develop`, which is pushed to `release`.
- Betas are usually released every two to three weeks, though that
schedule can vary depending on progress, availability, and other
factors.
3. When the changes in `develop` are considered stable and mature enough
to be ready to release, a release candidate (RC) is built and tagged
from `develop`, and merged to `release`.
- Further development for that release (primarily fixes) then
continues against `release`, while other development continues on
`develop`. Effectively, `release` is forked from `develop`. Changes
to `release` must be reverse merged to `develop`.
4. When the candidate has passed testing and is ready for release, the
final release is merged to `master`.
5. If any issues are found post-release, a hotfix / point release may be
created, which is merged to `master`, and then reverse merged to
`develop`.
#### Betas, and the first release candidate
##### Preparing the `develop` branch
1. Optimally, the `develop` branch will be ready to go, with all
relevant PRs already merged.
2. If there are any PRs pending, merge them **BEFORE** preparing the beta.
1. If only one or two PRs need to be merged, merge those PRs [as
normal](#when-and-how-to-merge-pull-requests), updating the second
one, and waiting for CI to finish in between.
2. If there are several pending PRs, do not use the Github UI,
because the delays waiting for CI in between each merge will be
unnecessarily onerous. (Incidentally, this process can also be
used to merge if the Github UI has issues.) Merge each PR branch
directly to a `release-next` on your local machine and create a single
PR, then push your branch to `develop`.
1. Squash the changes from each PR, one commit each (unless more
are needed), being sure to sign each commit and update the
commit message to include the PR number. You may be able to use
a fast-forward merge for the first PR.
2. Push your branch.
3. Continue to [Making the release](#making-the-release) to update
the version number, etc.
The workflow may look something like:
```
git fetch --multiple upstreams user1 user2 user3 [...]
git checkout -B release-next --no-track upstream/develop
# Only do an ff-only merge if pr-branch1 is either already
# squashed, or needs to be merged with separate commits,
# and has no merge commits.
# Use -S on the ff-only merge if pr-branch1 isn't signed.
git merge [-S] --ff-only user1/pr-branch1
git merge --squash user2/pr-branch2
git commit -S # Use the commit message provided on the PR
git merge --squash user3/pr-branch3
git commit -S # Use the commit message provided on the PR
[...]
# Make sure the commits look right
git log --show-signature "upstream/develop..HEAD"
git push --set-upstream origin
# Continue to "Making the release" to update the version number, so
# everything can be done in one PR.
```
You can also use the [squash-branches] script.
You may also need to manually close the open PRs after the changes are
merged to `develop`. Be sure to include the commit ID.
##### Making the release
This includes, betas, and the first release candidate (RC).
1. If you didn't create one [preparing the `develop`
branch](#preparing-the-develop-branch), Ensure there is no old
`release-next` branch hanging around. Then make a `release-next`
branch that only changes the version number. e.g.
```
git fetch upstreams
git checkout --no-track -B release-next upstream/develop
v="A.B.C-bD"
build=$( find -name BuildInfo.cpp )
sed 's/\(^.*versionString =\).*$/\1 "'${v}'"/' ${build} > version.cpp && mv -vi version.cpp ${build}
git diff
git add ${build}
git commit -S -m "Set version to ${v}"
# You could use your "origin" repo, but some CI tests work better on upstream.
git push upstream-push
git fetch upstreams
git branch --set-upstream-to=upstream/release-next
```
You can also use the [update-version] script. 2. Create a Pull Request for `release-next` with **`develop`** as
the base branch.
1. Use the title "[TRIVIAL] Set version to X.X.X-bX".
2. Instead of the default description template, use the following:
```
## High Level Overview of Change
This PR only changes the version number. It will be merged as
soon as Github CI actions successfully complete.
```
3. Wait for CI to successfully complete, and get someone to approve
the PR. (It is safe to ignore known CI issues.)
4. Push the updated `develop` branch using your `release-next`
branch. **Do not use the Github UI. It's important to preserve
commit IDs.**
```
git push upstream-push release-next:develop
```
5. In the unlikely event that the push fails because someone has merged
something else in the meantime, rebase your branch onto the updated
`develop` branch, push again, and go back to step 3.
6. Ensure that your PR against `develop` is closed. Github should do it
automatically.
7. Once this is done, forward progress on `develop` can continue
(other PRs may be merged).
8. Now create a Pull Request for `release-next` with **`release`** as
the base branch. Instead of the default template, reuse and update
the message from the previous release. Include the following verbiage
somewhere in the description:
```
The base branch is `release`. [All releases (including
betas)](https://github.com/XRPLF/rippled/blob/develop/CONTRIBUTING.md#before-you-start)
go in `release`. This PR branch will be pushed directly to `release` (not
squashed or rebased, and not using the GitHub UI).
```
7. Sign-offs for the three platforms (Linux, Mac, Windows) usually occur
offline, but at least one approval will be needed on the PR.
- If issues are discovered during testing, simply abandon the
release. It's easy to start a new release, it should be easy to
abandon one. **DO NOT REUSE THE VERSION NUMBER.** e.g. If you
abandon 2.4.0-b1, the next attempt will be 2.4.0-b2.
8. Once everything is ready to go, push to `release`.
```
git fetch upstreams
# Just to be safe, do a dry run first:
git push --dry-run upstream-push release-next:release
# If everything looks right, push the branch
git push upstream-push release-next:release
# Check that all of the branches are updated
git fetch upstreams
git log -1 --oneline
# The output should look like:
# 0123456789 (HEAD -> upstream/release-next, upstream/release,
# upstream/develop) Set version to 2.4.0-b1
# Note that upstream/develop may not be on this commit, but
# upstream/release must be.
# Other branches, including some from upstream-push, may also be
# present.
```
9. Tag the release, too.
```
git tag <version number>
git push upstream-push <version number>
```
10. Delete the `release-next` branch on the repo. Use the Github UI or:
```
git push --delete upstream-push release-next
```
11. Finally [create a new release on
Github](https://github.com/XRPLF/rippled/releases).
#### Release candidates after the first
Once the first release candidate is [merged into
release](#making-the-release), then `release` and `develop` _are allowed
to diverge_.
If a bug or issue is discovered in a version that has a release
candidate being tested, any fix and new version will need to be applied
against `release`, then reverse-merged to `develop`. This helps keep git
history as linear as possible.
A `release-next` branch will be created from `release`, and any further
work for that release must be based on `release-next`. Specifically,
PRs must use `release-next` as the base, and those PRs will be merged
directly to `release-next` when approved. Changes should be restricted
to bug fixes, but other changes may be necessary from time to time.
1. Open any PRs for the pending release using `release-next` as the base,
so they can be merged directly in to it. Unlike `develop`, though,
`release-next` can be thrown away and recreated if necessary.
2. Once a new release candidate is ready, create a version commit as in
step 1 [above](#making-the-release) on `release-next`. You can use
the [update-version] script for this, too.
3. Jump to step 8 ("Now create a Pull Request for `release-next` with
**`release`** as the base") from the process
[above](#making-the-release) to merge `release-next` into `release`.
##### Follow up: reverse merge
Once the RC is merged and tagged, it needs to be reverse merged into
`develop` as soon as possible.
1. Create a branch, based on `upstream/develop`.
The branch name is not important, but could include "mergeNNNrcN".
E.g. For release A.B.C-rcD, use `mergeABCrcD`.
```
git fetch upstreams
git checkout --no-track -b mergeABCrcD upstream/develop
```
2. Merge `release` into your branch.
```
# I like the "--edit --log --verbose" parameters, but they are
# not required.
git merge upstream/release
```
3. `BuildInfo.cpp` will have a conflict with the version number.
Resolve it with the version from `develop` - the higher version.
4. Push your branch to your repo (or `upstream` if you have permission),
and open a normal PR against `develop`. The "High level overview" can
simply indicate that this is a merge of the RC. The "Context" should
summarize the changes from the RC. Include the following text
prominently:
```
This PR must be merged manually using a push. Do not use the Github UI.
```
5. Depending on the complexity of the changes, and/or merge conflicts,
the PR may need a thorough review, or just a sign-off that the
merge was done correctly.
6. If `develop` is updated before this PR is merged, do not merge
`develop` back into your branch. Instead rebase preserving merges,
or do the merge again. (See also the `rerere` git config setting.)
```
git rebase --rebase-merges upstream/develop
# OR
git reset --hard upstream/develop
git merge upstream/release
```
7. When the PR is ready, push it to `develop`.
```
git fetch upstreams
# Make sure the commits look right
git log --show-signature "upstream/develop^..HEAD"
git push upstream-push mergeABCrcD:develop
git fetch upstreams
```
Development on `develop` can proceed as normal.
#### Final releases
A final release is any release that is not a beta or RC, such as 2.2.0.
Only code that has already been tested and vetted across all three
platforms should be included in a final release. Most of the time, that
means that the commit immediately preceding the commit setting the
version number will be an RC. Occasionally, there may be last-minute bug
fixes included as well. If so, those bug fixes must have been tested
internally as if they were RCs (at minimum, ensuring unit tests pass,
and the app starts, syncs, and stops cleanly across all three
platforms.)
_If in doubt, make an RC first._
The process for building a final release is very similar to [the process
for building a beta](#making-the-release), except the code will be
moving from `release` to `master` instead of from `develop` to
`release`, and both branches will be pushed at the same time.
1. Ensure there is no old `master-next` branch hanging around.
Then make a `master-next` branch that only changes the version
number. As above, or using the
[update-version] script.
2. Create a Pull Request for `master-next` with **`master`** as
the base branch. Instead of the default template, reuse and update
the message from the previous final release. Include the following verbiage
somewhere in the description:
```
The base branch is `master`. This PR branch will be pushed directly to
`release` and `master` (not squashed or rebased, and not using the
GitHub UI).
```
7. Sign-offs for the three platforms (Linux, Mac, Windows) usually occur
offline, but at least one approval will be needed on the PR.
- If issues are discovered during testing, close the PR, delete
`master-next`, and move development back to `release`, [issuing
more RCs as necessary](#release-candidates-after-the-first)
8. Once everything is ready to go, push to `release` and `master`.
```
git fetch upstreams
# Just to be safe, do dry runs first:
git push --dry-run upstream-push master-next:release
git push --dry-run upstream-push master-next:master
# If everything looks right, push the branch
git push upstream-push master-next:release
git push upstream-push master-next:master
# Check that all of the branches are updated
git fetch upstreams
git log -1 --oneline
# The output should look like:
# 0123456789 (HEAD -> upstream/master-next, upstream/master,
# upstream/release) Set version to A.B.0
# Note that both upstream/release and upstream/master must be on this
# commit.
# Other branches, including some from upstream-push, may also be
# present.
```
9. Tag the release, too.
```
git tag <version number>
git push upstream-push <version number>
```
10. Delete the `master-next` branch on the repo. Use the Github UI or:
```
git push --delete upstream-push master-next
```
11. [Create a new release on
Github](https://github.com/XRPLF/rippled/releases). Be sure that
"Set as the latest release" is checked.
12. Open a PR to update the [API-CHANGELOG](API-CHANGELOG.md) and `API-VERSION-[n].md` with the changes for this release (if any are missing).
13. Finally, [reverse merge the release into `develop`](#follow-up-reverse-merge).
#### Special cases: point releases, hotfixes, etc.
On occasion, a bug or issue is discovered in a version that already
had a final release. Most of the time, development will have started
on the next version, and will usually have changes in `develop`
and often in `release`.
Because git history is kept as linear as possible, any fix and new
version will need to be applied against `master`.
The process for building a hotfix release is very similar to [the
process for building release candidates after the
first](#release-candidates-after-the-first) and [for building a final
release](#final-releases), except the changes will be done against
`master` instead of `release`.
If there is only a single issue for the hotfix, the work can be done in
any branch. When it's ready to merge, jump to step 3 using your branch
instead of `master-next`.
1. Create a `master-next` branch from `master`.
```
git checkout --no-track -b master-next upstream/master
git push upstream-push
git fetch upstreams
```
2. Open any PRs for the pending hotfix using `master-next` as the base,
so they can be merged directly in to it. Unlike `develop`, though,
`master-next` can be thrown away and recreated if necessary.
3. Once the hotfix is ready, create a version commit using the same
steps as above, or use the
[update-version] script.
4. Create a Pull Request for `master-next` with **`master`** as
the base branch. Instead of the default template, reuse and update
the message from the previous final release. Include the following verbiage
somewhere in the description:
```
The base branch is `master`. This PR branch will be pushed directly to
`master` (not squashed or rebased, and not using the GitHub UI).
```
7. Sign-offs for the three platforms (Linux, Mac, Windows) usually occur
offline, but at least one approval will be needed on the PR.
- If issues are discovered during testing, update `master-next` as
needed, but ensure that the changes are properly squashed, and the
version setting commit remains last
8. Once everything is ready to go, push to `master` **only**.
```
git fetch upstreams
# Just to be safe, do a dry run first:
git push --dry-run upstream-push master-next:master
# If everything looks right, push the branch
git push upstream-push master-next:master
# Check that all of the branches are updated
git fetch upstreams
git log -1 --oneline
# The output should look like:
# 0123456789 (HEAD -> upstream/master-next, upstream/master) Set version
# to 2.4.1
# Note that upstream/master must be on this commit. upstream/release and
# upstream/develop should not.
# Other branches, including some from upstream-push, may also be
# present.
```
9. Tag the release, too.
```
git tag <version number>
git push upstream-push <version number>
```
9. Delete the `master-next` branch on the repo.
```
git push --delete upstream-push master-next
```
10. [Create a new release on
Github](https://github.com/XRPLF/rippled/releases). Be sure that
"Set as the latest release" is checked.
Once the hotfix is released, it needs to be reverse merged into
`develop` as soon as possible. It may also need to be merged into
`release` if a release candidate is under development.
1. Create a branch in your own repo, based on `upstream/develop`.
The branch name is not important, but could include "mergeNNN".
E.g. For release 2.2.3, use `merge223`.
```
git fetch upstreams
git checkout --no-track -b merge223 upstream/develop
```
2. Merge master into your branch.
```
# I like the "--edit --log --verbose" parameters, but they are
# not required.
git merge upstream/master
```
3. `BuildInfo.cpp` will have a conflict with the version number.
Resolve it with the version from `develop` - the higher version.
4. Push your branch to your repo, and open a normal PR against
`develop`. The "High level overview" can simply indicate that this
is a merge of the hotfix version. The "Context" should summarize
the changes from the hotfix. Include the following text
prominently:
```
This PR must be merged manually using a --ff-only merge. Do not use the Github UI.
```
5. Depending on the complexity of the hotfix, and/or merge conflicts,
the PR may need a thorough review, or just a sign-off that the
merge was done correctly.
6. If `develop` is updated before this PR is merged, do not merge
`develop` back into your branch. Instead rebase preserving merges,
or do the merge again. (See also the `rerere` git config setting.)
```
git rebase --rebase-merges upstream/develop
# OR
git reset --hard upstream/develop
git merge upstream/master
```
7. When the PR is ready, push it to `develop`.
```
git fetch upstreams
# Make sure the commits look right
git log --show-signature "upstream/develop..HEAD"
git push upstream-push HEAD:develop
```
Development on `develop` can proceed as normal. It is recommended to
create a beta (or RC) immediately to ensure that everything worked as
expected.
##### An even rarer scenario: A hotfix on an old release
Historically, once a final release is tagged and packages are released,
versions older than the latest final release are no longer supported.
However, there is a possibility that a very high severity bug may occur
in a non-amendment blocked version that is still being run by
a significant fraction of users, which would necessitate a hotfix / point
release to that version as well as any later versions.
This scenario would follow the same basic procedure as above,
except that _none_ of `develop`, `release`, or `master`
would be touched during the release process.
In this example, consider if version 2.1.1 needed to be patched.
1. Create two branches in the main (`upstream`) repo.
```
git fetch upstreams
# Create a base branch off the tag
git checkout --no-track -b master-2.1.2 2.1.1
git push upstream-push
# Create a working branch
git checkout --no-track -b master212-next master-2.1.2
git push upstream-push
git fetch upstreams
```
2. Work continues as above, except using `master-2.1.2`as
the base branch for any merging, packaging, etc.
3. After the release is tagged and packages are built, you could
potentially delete both branches, e.g. `master-2.1.2` and
`master212-next`. However, it may be useful to keep `master-2.1.2`
around indefinitely for reference.
4. Assuming that a hotfix is also released for the latest
version in parallel with this one, or if the issue is
already fixed in the latest version, do no do any
reverse merges. However, if it is not, it probably makes
sense to reverse merge `master-2.1.2` into `master`,
release a hotfix for _that_ version, then reverse merge
from `master` to `develop`. (Please don't do this unless absolutely
necessary.)
Releases, release branches, and merging releases back into `develop`
are described in [RELEASING.md](./RELEASING.md).
[contrib]: https://docs.github.com/en/get-started/quickstart/contributing-to-projects
[squash]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/about-pull-request-merges#squash-and-merge-your-commits
@@ -1201,5 +641,3 @@ git fetch upstreams
[xrpld]: https://github.com/XRPLF/rippled
[signing]: https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification
[setup-upstreams]: ./bin/git/setup-upstreams.sh
[squash-branches]: ./bin/git/squash-branches.sh
[update-version]: ./bin/git/update-version.sh

152
RELEASING.md Normal file
View File

@@ -0,0 +1,152 @@
# Branching and Release Management
This document describes how we branch, release, and merge releases back into `develop`.
It does not define version naming
(e.g., what constitutes a major-minor, patch, or beta release).
Examples use `X.Y` for a release line:
`X` and `Y` are placeholders, while the trailing `x` is literal,
e.g., `release/X.Y.x` is `release/3.4.x` for the `3.4` line.
## Branches
| Branch | Purpose |
| :-------------- | :---------------------------------------------------------------------------------------- |
| `develop` | Main development branch. Betas and the first RC of a major-minor release are tagged here. |
| `staging/X.Y.x` | Where fixes for the `X.Y` line are developed and RCs are prepared. |
| `release/X.Y.x` | The last public RC or release of the `X.Y` line. |
A release line is named `X.Y.x`
because one branch serves every patch release of that line (`X.Y.0`, `X.Y.1`, `X.Y.2`, ...).
The `/` groups branches hierarchically,
so tools can filter them and protection rules can target `release/*` and `staging/*`.
## Principles
- **Releases are merged back into `develop`, never cherry-picked or rebased onto it.**
Cherry-picked and rebased commits get new hashes,
so Git can't tell that `develop` already has them.
Future merges then replay them and produce artificial conflicts,
and it's hard to verify that every fix actually reached `develop`.
Merging keeps a single history:
Git knows exactly which release commits `develop` contains,
and no fix is left behind.
- **Branches only move forward.**
`develop`, `staging/X.Y.x`, and `release/X.Y.x` are never rewritten.
- **Cherry-picking only goes from `develop` to a staging branch**,
for fixes that must get into a release after the code freeze
(see [Emergency Fixes From `develop`](#emergency-fixes-from-develop)).
- **Security fixes are prepared privately and published with the release that contains them**,
so vulnerabilities are not disclosed prematurely.
## Release Lifecycle
This diagram shows a major-minor release and its first patch release.
The staging and release branches are drawn as one line.
```text
develop staging/X.Y.x & release/X.Y.x
│
├── Tag: X.Y.0-b1
├── Tag: X.Y.0-bN
├── Tag: X.Y.0-rc1 ───────────────┐ (branches created)
│ │
│ (development continues) ├── Fixes
│ ├── Tag: X.Y.0-rcN
│ ├── Tag: X.Y.0 (final)
◀──── (merge) ────────────────────┤
│ ├── Fixes
│ ├── Tag: X.Y.1-rcN
│ ├── Tag: X.Y.1 (final)
◀──── (merge) ────────────────────┤
│
▼
```
### Betas, First RC & Branching
> [!NOTE]
> This phase applies only to a new major-minor release (e.g., `X.Y.0`).
> Patch releases work on the existing branches of the line.
1. **Betas:** All beta versions (e.g., `X.Y.0-b1`) are built and tagged directly on `develop`.
2. **First RC:** We release the first RC (`X.Y.0-rc1`)
once everything that should be included in the release has been merged.
3. **Branches:** `staging/X.Y.x` and `release/X.Y.x` are created from `develop`
at the commit tagged `X.Y.0-rc1`.
The first RC also kicks off the QE process.
4. **Code freeze:** No new features or unrelated changes are pulled from `develop`
into `staging/X.Y.x` or `release/X.Y.x`.
Only critical stabilization fixes go into the line.
5. **No large changes on `develop`:** Until `X.Y.0` is [merged back](#merging-back-into-develop),
large changes (e.g., big refactors, moving or renaming many files, mass reformatting)
are not merged into `develop`,
so that fixes on the line and the merge back don't run into conflicts.
### Release Candidates
1. Fixes are developed against `staging/X.Y.x`.
2. When ready, a new RC is created on `staging/X.Y.x`,
and `release/X.Y.x` is fast-forwarded to it.
RCs that contain unpublished security fixes are not published,
and don't touch the public branches.
RCs are not merged back into `develop`:
`X.Y.0-rc1` is tagged on `develop` itself,
and all later changes reach `develop` with the [final release](#final-release).
### Final Release
Security fixes become public as soon as they reach the public repo,
so these steps happen only once the release is ready to be published,
one right after the other.
1. Unpublished security fixes, if any, are merged into `staging/X.Y.x`.
2. `release/X.Y.x` is fast-forwarded to `staging/X.Y.x`,
and the release is tagged on it.
3. The release is immediately [merged back into `develop`](#merging-back-into-develop).
For a major-minor release, this lifts the freeze on large changes in `develop`.
### Merging Back Into `develop`
The merge back is a regular PR into `develop`
whose branch contains a real merge commit of the release tag:
1. Create a branch from `develop`, run `git merge --no-ff <tag>`, and resolve any conflicts.
2. Once the PR is approved, `develop` is fast-forwarded to the PR branch,
so the merge commit lands as it is.
Never squash or rebase it.
Never add it to the merge queue either: the queue squashes PRs, which would drop the merge commit.
3. If `develop` moves while the PR is open, redo the merge on top of the new `develop`.
After the merge, `git log develop..<tag>` must be empty.
## Special Cases
### Emergency Fixes From `develop`
If a commit was merged to `develop`
and needs to be included in a release after the code freeze:
1. Create a PR that cherry-picks the commit onto `staging/X.Y.x`.
2. Leave `develop` as it is, with no reverts.
3. Follow the [release candidates](#release-candidates) process as usual.
When the release is later merged back into `develop`,
both sides already contain the same change,
so the merge usually resolves it cleanly or with a trivial conflict.
From Git's perspective, the cherry-picked commit then becomes part of `develop` too.
### Several Supported Lines
When a fix must ship in more than one supported line (e.g., `X.Y` and `X.(Y+1)`),
the lines are merged upwards rather than cherry-picked between:
1. The fix goes into the oldest line first.
2. After that line's release,
its `release/X.Y.x` is merged into the staging branch of the next newer line,
and so on up to the newest line.
3. The newest line is merged back into `develop` as usual.
This way every newer line, and eventually `develop`, contains the history of the older lines.

View File

@@ -0,0 +1,65 @@
#!/usr/bin/env bash
# Fail if a binary of a build-context Conan package loads anything from the Nix
# store other than glibc, or cannot resolve a library at all.
#
# Only binaries linked by the Nix toolchain are checked, i.e. those recording a
# store path as their interpreter or RUNPATH. Prebuilt upstream binaries (such
# as the ones the cmake package ships) use the system loader instead.
#
# Build-context packages provide the tools that run during the build (protoc,
# grpc_cpp_plugin, ...). Their package ID does not change when a Nix toolchain
# update moves the GCC runtime to a new store path, so a cached binary has to
# get by with the pinned glibc alone. See docs/build/nix.md.
#
# Usage: bin/check-build-context-runtime.sh <graph.json>
# <graph.json> is the output of `conan install --format=json`.
set -euo pipefail
if [ "$#" -ne 1 ]; then
echo "usage: $0 <graph.json>" >&2
exit 2
fi
if [ "$(uname -s)" != "Linux" ]; then
echo "$0: Linux only" >&2
exit 2
fi
folders="$(jq -r '.graph.nodes[] | select(.context == "build" and .package_folder) | .package_folder' "$1" | sort -u)"
checked=0
failed=0
while IFS= read -r file; do
case "$(file -b "${file}")" in
ELF*) ;;
*) continue ;;
esac
[[ "$(readelf -ldW "${file}")" == */nix/store/* ]] || continue
checked=$((checked + 1))
# `ldd` lists the interpreter and every library as the loader resolves them.
if deps="$(ldd "${file}" 2>&1)"; then
bad="$(printf '%s\n' "${deps}" |
grep -E 'not found|/nix/store/' |
grep -vE '/nix/store/[^/]+-glibc-[^/]+/' || true)"
else
case "${deps}" in
*"not a dynamic executable"*) continue ;;
esac
bad="${deps}"
fi
if [ -n "${bad}" ]; then
failed=$((failed + 1))
echo "::error file=${file}::loads a library from the Nix store other than glibc"
echo "${file}"
echo "${bad}" | sed 's/^/ /'
fi
done < <(
# shellcheck disable=SC2086 # one folder per line, no spaces in Conan paths
[ -z "${folders}" ] || find ${folders} -type f \( -perm -u+x -o -name '*.so*' \)
)
echo "Build-context packages: checked ${checked} binaries, ${failed} failed."
[ "${failed}" -eq 0 ]

View File

@@ -20,19 +20,32 @@
# development setups, but not in the macOS CI environment. They are checked
# everywhere except when running in CI on macOS.
#
# Tools that Nix also exposes under a version-suffixed name (`clang-tidy-22`,
# `g++-15`, ...) are probed under both names: a suffixed name can break while
# the plain one still works (see mkVersionedToolLinks in nix/packages.nix).
# Tools that Nix also exposes under a version-suffixed name
# (`clang-tidy-<v>`, `g++-<v>`, ...) are probed under both names:
# a suffixed name can break while the plain one still works
# (see mkVersionedToolLinks in nix/packages.nix).
# The suffix is the major version of the plain `clang` / `gcc` on PATH.
#
# Tools scoped to a single dev shell rather than to commonPackages are checked
# only in that shell, keyed off XRPL_DEVSHELL.
#
# Environment variables:
# CI if set, skip the tools above when on macOS.
# CHECK_TOOLS_SKIP_CLONE if set, skip the git-over-HTTPS connectivity check.
# XRPL_DEVSHELL active dev shell; selects shell-specific tools.
set -uo pipefail
# Version suffixes of the Nix tool links, tracking nix/packages.nix.
gcc_version=15
llvm_version=22
# major_version <compiler>
# Major version of a compiler on PATH, or "unknown" when it isn't there.
major_version() {
local version
version="$("$1" -dumpversion 2>/dev/null)" || version=""
version="${version%%.*}"
printf '%s' "${version:-unknown}"
}
llvm_version="$(major_version clang)"
missing=()
checked=0
@@ -108,6 +121,7 @@ if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then
check ClangBuildAnalyzer
check curl
check file
check jq
check less
check make
# net-tools netstat reports "net-tools X.Y"; macOS ships BSD netstat with no
@@ -163,11 +177,20 @@ if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then
check rustfmt
fi
# Lean4 is in the formal-verification shell only, not in commonPackages.
if [ "${XRPL_DEVSHELL:-}" = "formal-verification" ]; then
echo
echo "Formal verification toolchain:"
check lean
check lake
fi
# GCC is the default compiler on Linux. macOS uses the system Apple Clang
# instead, so GCC/g++/gcov are not expected there.
if [ "${os}" = "linux" ]; then
echo
echo "GCC toolchain:"
gcc_version="$(major_version gcc)"
check gcc
check "gcc-${gcc_version}"
check g++

View File

@@ -1,56 +0,0 @@
#!/bin/bash
if [[ $# -ne 3 || "$1" == "--help" || "$1" = "-h" ]]; then
name=$(basename $0)
cat <<-USAGE
Usage: $name workbranch base/branch version
* workbranch will be created locally from base/branch. If it exists,
it will be reused, so make sure you don't overwrite any work.
* base/branch may be specified as user:branch to allow easy copying
from Github PRs.
USAGE
exit 0
fi
work="$1"
shift
base=$(echo "$1" | sed "s/:/\//")
shift
version=$1
shift
set -e
git fetch upstreams
git checkout -B "${work}" --no-track "${base}"
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}
git diff
git add ${build}
git commit -S -m "Set version to ${version}"
git log --oneline --first-parent ${base}^..
cat <<PUSH
-------------------------------------------------------------------
This script will not push. Verify everything is correct, then push
to your repo, and create a PR as described in CONTRIBUTING.md.
-------------------------------------------------------------------
PUSH

View File

@@ -23,7 +23,7 @@ apt-get clean
rm -rf /var/lib/apt/lists/*
EOF
ARG PRE_COMMIT_VERSION=4.6.0
ARG PRE_COMMIT_VERSION=4.6.2
RUN pip install --no-cache --break-system-packages \
pre-commit==${PRE_COMMIT_VERSION}

View File

@@ -26,8 +26,6 @@ import sys
import tempfile
from pathlib import Path
CLANG_TIDY_VERSION = 22
# Extensions run-clang-tidy can analyse: `.cpp` translation units and, thanks to
# the `verify_headers` build option, `.h`/`.hpp` headers (each has its own
# compile_commands.json entry). `.ipp` fragments have no entry and are skipped.
@@ -39,8 +37,21 @@ TIDY_EXTENSIONS = {".cpp", ".h", ".hpp"}
FILEPATH_RE = re.compile(r"^(\s*(?:-\s+)?FilePath:\s*)'((?:[^']|'')*)'\s*$")
def find_tool(name: str) -> str | None:
for candidate in (f"{name}-{CLANG_TIDY_VERSION}", name):
def clang_tidy_major() -> str | None:
"""Major version of the `clang-tidy` on PATH, which run-clang-tidy invokes."""
if not (clang_tidy := shutil.which("clang-tidy")):
return None
output = subprocess.run(
[clang_tidy, "--version"], capture_output=True, text=True
).stdout
m = re.search(r"LLVM version (\d+)", output)
return m.group(1) if m else None
def find_tool(name: str, version: str | None) -> str | None:
"""Prefer `<name>-<version>`, so a host tool of another version can't win."""
candidates = ([f"{name}-{version}"] if version else []) + [name]
for candidate in candidates:
if path := shutil.which(candidate):
return path
return None
@@ -103,8 +114,9 @@ def main():
if not files:
return 0
run_clang_tidy = find_tool("run-clang-tidy")
clang_apply_replacements = find_tool("clang-apply-replacements")
version = clang_tidy_major()
run_clang_tidy = find_tool("run-clang-tidy", version)
clang_apply_replacements = find_tool("clang-apply-replacements", version)
missing = [
name
for name, path in (
@@ -114,9 +126,10 @@ def main():
if not path
]
if missing:
tried = f" (tried the '-{version}' suffix too)" if version else ""
print(
f"clang-tidy check failed: TIDY is enabled but {' and '.join(missing)} "
f"was not found in PATH (tried the '-{CLANG_TIDY_VERSION}' suffix too).",
f"was not found in PATH{tried}.",
file=sys.stderr,
)
return 1

View File

@@ -1,28 +0,0 @@
include_guard()
set(GIT_BUILD_BRANCH "")
set(GIT_COMMIT_HASH "")
find_package(Git)
if(NOT Git_FOUND)
message(WARNING "Git not found. Git branch and commit hash will be empty.")
return()
endif()
set(GIT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/.git)
execute_process(
COMMAND
${GIT_EXECUTABLE} --git-dir=${GIT_DIRECTORY} rev-parse --abbrev-ref HEAD
OUTPUT_STRIP_TRAILING_WHITESPACE
OUTPUT_VARIABLE GIT_BUILD_BRANCH
)
execute_process(
COMMAND ${GIT_EXECUTABLE} --git-dir=${GIT_DIRECTORY} rev-parse HEAD
OUTPUT_STRIP_TRAILING_WHITESPACE
OUTPUT_VARIABLE GIT_COMMIT_HASH
)
message(STATUS "Git branch: ${GIT_BUILD_BRANCH}")
message(STATUS "Git commit hash: ${GIT_COMMIT_HASH}")

View File

@@ -81,7 +81,7 @@ include(target_link_modules)
add_module(xrpl beast)
target_link_libraries(xrpl.libxrpl.beast PUBLIC xrpl.imports.main)
include(GitInfo)
include(XrplVersion)
add_module(xrpl git)
target_compile_definitions(
xrpl.libxrpl.git
@@ -111,6 +111,11 @@ target_link_libraries(
xrpl.libxrpl.protocol
PUBLIC xrpl.libxrpl.crypto xrpl.libxrpl.git xrpl.libxrpl.json
)
# Only on BuildInfo.cpp, so a new version does not rebuild the whole module.
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/src/libxrpl/protocol/BuildInfo.cpp
PROPERTIES COMPILE_DEFINITIONS XRPLD_VERSION="${XRPLD_VERSION}"
)
# Level 05
add_module(xrpl protocol_autogen)
@@ -287,6 +292,14 @@ if(xrpld)
)
target_sources(xrpld PRIVATE ${sources})
rpcspec_generate_instantiations(
OUT_VAR rpcspec_instantiations
VALUE_TYPE "::json::Value"
VIEW_HEADER "xrpld/rpc/detail/JsonObjectView.hpp"
HANDLERS ledger
)
target_sources(xrpld PRIVATE ${rpcspec_instantiations})
if(tests)
file(
GLOB_RECURSE sources

View File

@@ -77,19 +77,24 @@ if(is_clang)
message(STATUS " Ignorelist: ${ignorelist_path}")
endif()
# Define SANITIZERS macro for BuildInfo.cpp
# Define the SANITIZERS macro for BuildInfo.cpp, plus one of XRPL_ASAN,
# XRPL_TSAN and XRPL_UBSAN per active sanitizer, so that code can test for a
# specific one with #ifdef instead of parsing the dot-joined SANITIZERS string.
set(sanitizers_list)
if(SANITIZERS MATCHES "address")
set(enable_asan ON)
list(APPEND sanitizers_list "ASAN")
target_compile_definitions(common INTERFACE XRPL_ASAN)
endif()
if(SANITIZERS MATCHES "thread")
set(enable_tsan ON)
list(APPEND sanitizers_list "TSAN")
target_compile_definitions(common INTERFACE XRPL_TSAN)
endif()
if(SANITIZERS MATCHES "undefinedbehavior")
set(enable_ubsan ON)
list(APPEND sanitizers_list "UBSAN")
target_compile_definitions(common INTERFACE XRPL_UBSAN)
endif()
if(sanitizers_list)

View File

@@ -1,15 +1,75 @@
#[===================================================================[
read version from source
#]===================================================================]
find_package(Git)
file(STRINGS src/libxrpl/protocol/BuildInfo.cpp BUILD_INFO)
foreach(line_ ${BUILD_INFO})
if(line_ MATCHES "versionString[ ]*=[ ]*\"(.+)\"")
set(xrpld_version ${CMAKE_MATCH_1})
endif()
endforeach()
if(xrpld_version)
message(STATUS "xrpld version: ${xrpld_version}")
else()
message(FATAL_ERROR "unable to determine xrpld version")
set(GIT_BUILD_BRANCH "")
set(GIT_COMMIT_HASH "")
if(DEFINED ENV{GITHUB_BRANCH_NAME})
set(GIT_BUILD_BRANCH $ENV{GITHUB_BRANCH_NAME})
set(GIT_COMMIT_HASH $ENV{GITHUB_HEAD_SHA})
elseif(Git_FOUND AND EXISTS "${CMAKE_CURRENT_LIST_DIR}/../.git")
execute_process(
COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/..
OUTPUT_VARIABLE GIT_BUILD_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ERROR_IS_FATAL ANY
)
execute_process(
COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/..
OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ERROR_IS_FATAL ANY
)
endif()
message(STATUS "Git branch: ${GIT_BUILD_BRANCH}")
message(STATUS "Git commit hash: ${GIT_COMMIT_HASH}")
if(
DEFINED ENV{FORCE_XRPLD_VERSION}
AND NOT "$ENV{FORCE_XRPLD_VERSION}" STREQUAL ""
)
message(
STATUS
"Using explicitly provided '$ENV{FORCE_XRPLD_VERSION}' as xrpld version"
)
set(XRPLD_VERSION "$ENV{FORCE_XRPLD_VERSION}")
# The rules beast::SemanticVersion::parse applies, so that an invalid version
# fails here rather than when xrpld starts. It reads each number as an int.
set(SEMVER_NUMBER "(0|[1-9][0-9]*)")
set(SEMVER_PRE_RELEASE "[A-Za-z1-9-][A-Za-z0-9-]*")
set(SEMVER_METADATA "[A-Za-z0-9-]+")
set(SEMVER_NUMBER_MAX 2147483647)
if(
NOT XRPLD_VERSION
MATCHES
"^${SEMVER_NUMBER}\\.${SEMVER_NUMBER}\\.${SEMVER_NUMBER}(-${SEMVER_PRE_RELEASE}(\\.${SEMVER_PRE_RELEASE})*)?(\\+${SEMVER_METADATA}(\\.${SEMVER_METADATA})*)?$"
OR CMAKE_MATCH_1 GREATER SEMVER_NUMBER_MAX
OR CMAKE_MATCH_2 GREATER SEMVER_NUMBER_MAX
OR CMAKE_MATCH_3 GREATER SEMVER_NUMBER_MAX
)
message(
FATAL_ERROR
"FORCE_XRPLD_VERSION '${XRPLD_VERSION}' is not a semantic version xrpld accepts, see https://semver.org"
)
endif()
else()
message(STATUS "Using '0.0.0-dev+<git short rev>' as xrpld version")
if(GIT_COMMIT_HASH STREQUAL "")
message(
FATAL_ERROR
"Unable to determine xrpld version without git, set FORCE_XRPLD_VERSION"
)
endif()
string(SUBSTRING ${GIT_COMMIT_HASH} 0 7 GIT_COMMIT_HASH_SHORT)
set(XRPLD_VERSION "0.0.0-dev+${GIT_COMMIT_HASH_SHORT}")
endif()
message(STATUS "Build version: ${XRPLD_VERSION}")

View File

@@ -59,7 +59,7 @@ def create_transaction_parser():
# the members that differ from these.
SETTING_DEFAULTS = {
"delegable": "Delegation::NotDelegable",
"amendment": "uint256{}",
"amendment": "UInt256{}",
"privileges": "Privilege::NoPriv",
}

View File

@@ -209,7 +209,7 @@ ${field['typeData']['setter_type']} ${field['paramName']}${',' if i < len(requir
* @return The constructed ledger entry wrapper.
*/
${name}
build(uint256 const& index)
build(UInt256 const& index)
{
return ${name}{std::make_shared<SLE>(std::move(object_), index)};
}

View File

@@ -31,7 +31,7 @@ namespace xrpl::ledger_entries {
// builder's STObject and the wrapper's SLE.
TEST(${name}Tests, BuilderSettersRoundTrip)
{
uint256 const index{1u};
UInt256 const index{1u};
% for field in fields:
auto const ${field["paramName"]}Value = ${canonical_expr(field)};
@@ -85,7 +85,7 @@ TEST(${name}Tests, BuilderSettersRoundTrip)
// from that SLE, build a new wrapper, and verify all fields (and validate()).
TEST(${name}Tests, BuilderFromSleRoundTrip)
{
uint256 const index{2u};
UInt256 const index{2u};
% for field in fields:
auto const ${field["paramName"]}Value = ${canonical_expr(field)};
@@ -146,7 +146,7 @@ TEST(${name}Tests, BuilderFromSleRoundTrip)
// 3) Verify wrapper throws when constructed from wrong ledger entry type.
TEST(${name}Tests, WrapperThrowsOnWrongEntryType)
{
uint256 const index{3u};
UInt256 const index{3u};
// Build a valid ledger entry of a different type
// Ticket requires: Account, OwnerNode, TicketSequence, PreviousTxnID, PreviousTxnLgrSeq
@@ -177,7 +177,7 @@ TEST(${name}Tests, WrapperThrowsOnWrongEntryType)
// 4) Verify builder throws when constructed from wrong ledger entry type.
TEST(${name}Tests, BuilderThrowsOnWrongEntryType)
{
uint256 const index{4u};
UInt256 const index{4u};
// Build a valid ledger entry of a different type
% if wrong_le_include == "Ticket":
@@ -207,7 +207,7 @@ TEST(${name}Tests, BuilderThrowsOnWrongEntryType)
// 5) Build with only required fields and verify optional fields return nullopt.
TEST(${name}Tests, OptionalFieldsReturnNullopt)
{
uint256 const index{3u};
UInt256 const index{3u};
% for field in required_fields:
auto const ${field["paramName"]}Value = ${canonical_expr(field)};

View File

@@ -3,7 +3,7 @@
"requires": [
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1782392402.122708",
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1782392402.420688",
"xrpl-rpc-spec/0.1.19#870b2d3abcfbbf13b61c2d3c69495060%1790348286.187549",
"xrpl-rpc-spec/0.1.20#6daa13eeb4e6c92b82ea6d78866e1da8%1790720024.368048",
"sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1782392403.185447",
"soci/4.0.3#e726491a03468795453f7c83fc924a96%1782392402.679521",
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1782307151.633168",
@@ -20,7 +20,7 @@
"libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1782392403.066892",
"jemalloc/5.3.1#1fc58d55316041f10fbc1e8a2eae632a%1776700028.228",
"gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1782392402.791979",
"grpc/1.81.1#b87796a4269034856cbc1a2522db16eb%1788275071.530512",
"grpc/1.81.1#aaa93ab6cda2f2baa6a84490582c8adf%1791284951.826256",
"fast_float/8.2.10#f6f28d6bb22112078e7dbda611caf681%1785888854.601666",
"ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1782307148.15562",
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1782392402.538492",
@@ -34,11 +34,15 @@
"build_requires": [
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1782392402.122708",
"strawberryperl/5.32.1.1#8d114504d172cfea8ea1662d09b6333e%1782395692.540639",
"re2/20251105#8579cfd0bda4daf0683f9e3898f964b4%1782392402.431897",
"protobuf/6.33.5#ff253ead763bd8d9904a52979cd21e81%1782392410.233933",
"openssl/3.6.3#f806de8933e3bf6f01016c6a888cee2e%1783945160.863288",
"nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1782395690.33162",
"msys2/cci.latest#d22fe7b2808f5fd34d0a7923ace9c54f%1770657326.649",
"m4/1.4.19#1727f439cf74e83826ec96d0b4904eee%1784541921.659",
"grpc/1.81.1#aaa93ab6cda2f2baa6a84490582c8adf%1791284951.826256",
"cmake/4.3.3#840cf00ea09777e05c2050a50a82c722%1782392418.696091",
"c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1782392402.681654",
"b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1782392402.624226",
"automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56",
"autoconf/2.71#51077f068e61700d65bb05541ea1e4b0%1731054366.86",

View File

@@ -3,5 +3,13 @@
core:non_interactive=True
core.download:parallel={{ os.cpu_count() }}
core.upload:parallel={{ os.cpu_count() }}
tools.files.download:retry=5
# Fall back to Conan Center's source backups when a recipe's upstream URL is down
# (e.g. the GNU FTP mirrors), see
# https://github.com/conan-io/conan-center-index/issues/28147#issuecomment-3183544772
# The backups are only tried once every upstream URL has used up its retries,
# so keep the retries low.
core.sources:download_urls=["origin", "https://c3i.jfrog.io/artifactory/conan-center-backup-sources"]
tools.files.download:retry=1
tools.files.download:retry_wait=10
# Fail fast on unreachable hosts (default connect timeout is 30s), keep the 60s read timeout.
core.net.http:timeout=(5, 60)

View File

@@ -29,9 +29,9 @@ os.version={{ min_macos_version }}
[conf]
{# The Boost recipe builds with b2, which doesn't use Conan's toolchain files. #}
{# Instead it hand-rolls the compiler for user-config.jam, #}
{# and its fallback probes a version-suffixed binary (e.g. `g++-15`) before plain `g++`. #}
{# Inside the Nix shell the wrapper only provides `g++`/`gcc` (no `-15` suffix), #}
{# so on a host that also has a system `g++-15` the probe escapes Nix #}
{# and its fallback probes a version-suffixed binary (e.g. `g++-<major>`) before plain `g++`. #}
{# Inside the Nix shell the wrapper only provides `g++`/`gcc` (no `-<major>` suffix), #}
{# so on a host that also has a system `g++-<major>` the probe escapes Nix #}
{# and picks the system compiler, which is mismatched with the Nix libraries #}
{# and breaks the build (e.g. Boost.Stacktrace link checks fail). #}
{# Pinning the executables here short-circuits that probe so Boost (and the rest of the toolchain) #}
@@ -49,6 +49,17 @@ tools.build:compiler_executables={'c':'{{ cc_exe }}','cpp':'{{ cxx_exe }}'}
user.package:cppstd_version=23
tools.info.package_id:confs+=["user.package:cppstd_version"]
{% if os == "Linux" and context == "build" %}
{# Build-context executables (protoc, grpc_cpp_plugin, build tools) run during the build #}
{# and would otherwise load libstdc++/libgcc from a Nix store path #}
{# that might change with a Nix toolchain update. #}
{# --as-needed drops the ones they link but don't use, #}
{# such as libatomic for grpc_cpp_plugin on arm64. #}
{% set static_runtime_flags = ["-static-libstdc++", "-static-libgcc", "-Wl,--as-needed"] %}
tools.build:exelinkflags+={{ static_runtime_flags }}
tools.info.package_id:confs+=["tools.build:exelinkflags"]
{% endif %}
{% if os == "Macos" %}
[buildenv]
{# os.version adds -mmacosx-version-min to compiler command lines, #}
@@ -58,3 +69,13 @@ tools.info.package_id:confs+=["user.package:cppstd_version"]
{# Scoped to boost/* since it is the only gap. #}
boost/*:MACOSX_DEPLOYMENT_TARGET={{ min_macos_version }}
{% endif %}
{% if os == "Linux" and context == "build" %}
{# b2 links itself with its own script, which ignores exelinkflags #}
{# and only takes CXXFLAGS when use_cxx_env is set. #}
[options]
b2/*:use_cxx_env=True
[buildenv]
b2/*:CXXFLAGS={{ static_runtime_flags | join(" ") }}
{% endif %}

View File

@@ -5,6 +5,9 @@ include(default)
{% if not sanitizers %}
{# Sanitizers not configured; no additional settings needed #}
{% elif context == "build" %}
{# Build-context packages are tools we run, not code we test, #}
{# so don't instrument them #}
{% else %}
{% if compiler == "msvc" %}

View File

@@ -1,9 +1,13 @@
import os
import re
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
from conan.tools.env import Environment
from conan import ConanFile
DEV_VERSION = "0.0.0-dev"
class Xrpl(ConanFile):
name = "xrpl"
@@ -36,7 +40,7 @@ class Xrpl(ConanFile):
"nudb/2.0.9",
"openssl/3.6.3",
"soci/4.0.3",
"xrpl-rpc-spec/0.1.19",
"xrpl-rpc-spec/0.1.20",
"zlib/1.3.2",
]
@@ -45,7 +49,8 @@ class Xrpl(ConanFile):
]
tool_requires = [
"protobuf/6.33.5",
"grpc/<host_version>",
"protobuf/<host_version>",
]
default_options = {
@@ -119,14 +124,12 @@ class Xrpl(ConanFile):
"xxhash/*:shared": False,
}
# default_options only reach the host context;
# give tool_requires (and their dependencies) the same dependency options.
default_build_options = {k: v for k, v in default_options.items() if "/" in k}
def set_version(self):
if self.version is None:
path = f"{self.recipe_folder}/src/libxrpl/protocol/BuildInfo.cpp"
regex = r"versionString\s?=\s?\"(.*)\""
with open(path, encoding="utf-8") as file:
matches = (re.search(regex, line) for line in file)
match = next(m for m in matches if m)
self.version = match.group(1)
self.version = self.version or DEV_VERSION
def configure(self):
if self.settings.compiler == "apple-clang":
@@ -169,6 +172,17 @@ class Xrpl(ConanFile):
generators = "CMakeDeps"
def generate(self):
# The sources in the Conan cache have no git history, so the version
# comes from the reference, unless it is not one, like 'develop'.
if not os.path.exists(os.path.join(self.source_folder, ".git")):
version = str(self.version)
env = Environment()
env.define(
"FORCE_XRPLD_VERSION",
version if re.match(r"\d+\.\d+\.\d+", version) else DEV_VERSION,
)
env.vars(self).save_script("xrpld_version")
tc = CMakeToolchain(self)
tc.variables["tests"] = self.options.tests
tc.variables["benchmark"] = self.options.benchmark

View File

@@ -4,7 +4,7 @@
the `xrpld` DEB package installed on Ubuntu 26.04, running as the `xrpld` user.
Each release is tagged with its version, `xrplf/xrpld:<version>`, and
`xrplf/xrpld:develop` follows the `develop` branch.
See [`package/README.md`](../package/README.md#docker-image) for how it is built
See [`package/README.md`](../package/README.md#docker-images) for how it is built
and tagged.
```bash

View File

@@ -10,14 +10,15 @@ This document explains how to set one up.
support it — see [compiler support for C++23][cpp23-support].
The versions currently tested in CI are:
| Compiler | Version |
| ----------- | ------------------ |
| GCC | 15.2 |
| Clang | 22 |
| Apple Clang | 21 |
| MSVC | Visual Studio 2026 |
| Compiler | Version |
| ----------- | ------------------------------- |
| GCC | `gccVersion` in [packages.nix] |
| Clang | `llvmVersion` in [packages.nix] |
| Apple Clang | 21 |
| MSVC | Visual Studio 2026 |
LLVM tools (`clang-tidy` and `clang-format`) are also pinned to version 22.
LLVM tools (`clang-tidy` and `clang-format`)
come from the same LLVM release as Clang.
### Older compilers
@@ -156,3 +157,4 @@ version out of the box — run it via `run-clang-tidy`. No separate installation
is needed.
[cpp23-support]: https://en.cppreference.com/w/cpp/compiler_support/23
[packages.nix]: ../../nix/packages.nix

20
docs/build/nix.md vendored
View File

@@ -194,10 +194,22 @@ bin/check-nix-store-refs.sh ~/.conan2-nix
```
It works on Linux too, but asserts something narrower there: the toolchain always
writes the store into `PT_INTERP` and `RUNPATH`, and CI builds inside an image
whose store is fixed for its lifetime, so that is fine. Only the binaries
[`PatchNixBinary.cmake`](../../cmake/PatchNixBinary.cmake) retargets to the
system loader have to be clean, and those are what CI checks:
writes the store into `PT_INTERP` and `RUNPATH`. That is fine for the pinned
glibc, whose path does not move, but not for the GCC runtime, which moves with
every GCC update. So [`conan/profiles/default`](../../conan/profiles/default)
links build-context packages, whose executables run during the build, with
`-static-libstdc++ -static-libgcc -Wl,--as-needed`, and
[`conan/profiles/sanitizers`](../../conan/profiles/sanitizers) does not
instrument them. CI checks that they load nothing from the store but glibc, from
the graph `conan install --format=json` writes:
```bash
bin/check-build-context-runtime.sh graph.json
```
Only the binaries [`PatchNixBinary.cmake`](../../cmake/PatchNixBinary.cmake)
retargets to the system loader have to be fully clean, and those are what CI
checks:
```bash
bin/check-nix-store-refs.sh build/xrpld

12
flake.lock generated
View File

@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1781173989,
"narHash": "sha256-fnzKKPvS+oieI/pTzotA5tkoM47EB1NpaBcgk4R97hE=",
"lastModified": 1791130267,
"narHash": "sha256-1sjwcQMcgAbmiip/VivBSiK8p2bTkQGOvCuO7vnwfx4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "8c91a71d13451abc40eb9dae8910f972f979852f",
"rev": "9013764fcc0ea99fa16cf7aa7decf8a5c3889dd2",
"type": "github"
},
"original": {
@@ -47,11 +47,11 @@
]
},
"locked": {
"lastModified": 1784611586,
"narHash": "sha256-OfqgY+0hp/zseZB7uyH0U8kIDPS4scZZCyAurEplvG0=",
"lastModified": 1791189933,
"narHash": "sha256-Y8eN7ki0Urx4Ojf4w1xSpWg8uk/3lJqK+E0Oth77rH0=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "14f58845249f3552a89b07772626b8d3c632fa86",
"rev": "e60029353d0c48d216bc4b065168ccd4079c166f",
"type": "github"
},
"original": {

View File

@@ -0,0 +1,11 @@
# basics' container adapters (TaggedCache, partitioned_unordered_map,
# base_uint) model std concepts, which mandate
# snake_case member type names.
#
# clang-tidy replaces rather than merges this option, so the list is the
# top-level one restated plus the 6 name(s) needed only here:
# allocator_type const_pointer const_reverse_iterator hasher key_equal reverse_iterator
InheritParentConfig: true
CheckOptions:
readability-identifier-naming.TypeAliasIgnoredRegexp: "^(allocator_type|const_iterator|const_pointer|const_reference|const_reverse_iterator|difference_type|duration|hasher|iterator|iterator_category|key_equal|key_type|mapped_type|period|pointer|reference|rep|result_type|reverse_iterator|size_type|time_point|value_type)$"
readability-identifier-naming.TypedefIgnoredRegexp: "^(allocator_type|const_iterator|const_pointer|const_reference|const_reverse_iterator|difference_type|duration|hasher|iterator|iterator_category|key_equal|key_type|mapped_type|period|pointer|reference|rep|result_type|reverse_iterator|size_type|time_point|value_type)$"

View File

@@ -618,13 +618,16 @@ SharedWeakUnion<T>::convertToWeak()
unsafeSetRawPtr(nullptr);
return true; // Should never happen
// LCOV_EXCL_STOP
case PartialDestroy:
// This is a weird case. We just converted the last strong
// pointer to a weak pointer.
case PartialDestroy: {
// We just converted the last strong pointer to a weak pointer.
// The weak ref we now hold keeps the object from being fully
// destroyed, so `p` stays valid; only the copy passed to
// `partialDestructorFinished` is nulled.
p->partialDestructor();
partialDestructorFinished(&p);
// p is null and may no longer be used
auto finished = p;
partialDestructorFinished(&finished);
break;
}
}
unsafeSetRawPtr(p, RefStrength::Weak);
return true;

View File

@@ -77,21 +77,13 @@ struct IntrusiveRefCounts
std::size_t
useCount() const noexcept;
// This function MUST be called after a partial destructor finishes running.
// Calling this function may cause other threads to delete the object
// pointed to by `o`, so `o` should never be used after calling this
// function. The parameter will be set to a `nullptr` after calling this
// function to emphasize that it should not be used.
// Note: This is intentionally NOT called at the end of `partialDestructor`.
// The reason for this is if new classes are written to support this smart
// pointer class, they need to write their own `partialDestructor` function
// and ensure `partialDestructorFinished` is called at the end. Putting this
// call inside the smart pointer class itself is expected to be less error
// prone.
// Note: The "two-star" programming is intentional. It emphasizes that `o`
// may be deleted and the unergonomic API is meant to signal the special
// nature of this function call to callers.
// Note: This is a template to support incompletely defined classes.
// MUST be called after `partialDestructor` returns. Another thread may
// then delete the object, so `*o` is nulled and must not be used after
// (unless the caller holds its own weak ref, e.g.
// SharedWeakUnion::convertToWeak). Called by the smart pointers, not
// `partialDestructor`, so custom partial destructors can't forget it.
// The two-star API signals that `*o` may be deleted. Templated to
// support incomplete types.
template <class T>
friend void
partialDestructorFinished(T** o);
@@ -334,15 +326,11 @@ IntrusiveRefCounts::addWeakReleaseStrongRef() const
ReleaseStrongRefAction action = NoOp;
if (prevVal.strong == 1)
{
if (prevVal.weak == 0)
{
action = NoOp;
}
else
{
nextIntVal |= kPartialDestroyStartedMask;
action = PartialDestroy;
}
// The weak ref added here keeps the weak count non-zero, so
// releasing the last strong ref always starts a partial destroy,
// regardless of the previous weak count.
nextIntVal |= kPartialDestroyStartedMask;
action = PartialDestroy;
}
if (refCounts_.compare_exchange_weak(prevIntVal, nextIntVal, std::memory_order_acq_rel))
{
@@ -358,24 +346,26 @@ IntrusiveRefCounts::addWeakReleaseStrongRef() const
inline ReleaseWeakRefAction
IntrusiveRefCounts::releaseWeakRef() const
{
auto prevIntVal = refCounts_.fetch_sub(kWeakDelta, std::memory_order_acq_rel);
RefCountPair prev = prevIntVal;
auto const prevIntVal = refCounts_.fetch_sub(kWeakDelta, std::memory_order_acq_rel);
RefCountPair const prev = prevIntVal;
if (prev.weak == 1 && prev.strong == 0)
{
// `wait` blocks while the value equals its argument, so it must be
// given the value as it is after the decrement above.
auto curIntVal = prevIntVal - kWeakDelta;
if (prev.partialDestroyStartedBit == 0u)
{
// This case should only be hit if the partialDestroyStartedBit is
// set non-atomically (and even then very rarely). The code is kept
// in case we need to set the flag non-atomically for perf reasons.
refCounts_.wait(prevIntVal, std::memory_order_acquire);
prevIntVal = refCounts_.load(std::memory_order_acquire);
prev = RefCountPair{prevIntVal};
refCounts_.wait(curIntVal, std::memory_order_acquire);
curIntVal = refCounts_.load(std::memory_order_acquire);
}
if (prev.partialDestroyFinishedBit == 0u)
if (RefCountPair{curIntVal}.partialDestroyFinishedBit == 0u)
{
// partial destroy MUST finish before running a full destroy (when
// using weak pointers)
refCounts_.wait(prevIntVal - kWeakDelta, std::memory_order_acquire);
refCounts_.wait(curIntVal, std::memory_order_acquire);
}
return ReleaseWeakRefAction::Destroy;
}

View File

@@ -5,6 +5,6 @@
namespace xrpl {
using KeyCache = TaggedCache<uint256, int, true>;
using KeyCache = TaggedCache<UInt256, int, true>;
} // namespace xrpl

View File

@@ -110,10 +110,10 @@ static_assert(
*
* However, it does not have sufficient precision to represent the full integer
* range of int64_t values (-2^63 to 2^63-1), which are needed for XRP and MPT
* values. The implementation of SingleAssetVault, and LendingProtocol need to
* represent those integer values accurately and precisely, both for the
* STNumber field type, and for internal calculations. That necessitated the
* "large" scale.
* values. The implementation of SingleAssetVault, LendingProtocol, and
* MPTokensV2 need to represent those integer values accurately and precisely,
* both for the 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
* by an STAmount - IOUs, XRP, and MPTs. It has a min value of 10^18, and a max
@@ -134,8 +134,8 @@ struct MantissaRange final
// NOLINTBEGIN(readability-enum-initial-value)
// The values don't matter, except for Large
enum class MantissaScale {
// Small can be removed when either featureSingleAssetVault or featureLendingProtocol are
// retired
// Small can be removed when any of featureSingleAssetVault, featureLendingProtocol, or
// featureMPTokensV2 are retired
Small,
// LargeLegacy can be removed when fixCleanup3_2_0 is retired
LargeLegacy,
@@ -311,10 +311,10 @@ concept Integral64 = std::is_same_v<T, std::int64_t> || std::is_same_v<T, std::u
*
* The mantissa range may be changed at runtime via setMantissaScale(). The
* default mantissa range is "large". The range is updated whenever transaction
* processing begins, based on whether SingleAssetVault or LendingProtocol are
* enabled. If either is enabled, the mantissa range is set to "large". If not,
* it is set to "small", preserving backward compatibility and correct
* "amendment-gating".
* processing begins, based on whether SingleAssetVault, LendingProtocol, or
* MPTokensV2 are enabled. If any is enabled, the mantissa range is set to
* "large". If not, it is set to "small", preserving backward compatibility and
* correct "amendment-gating".
*
* It is extremely unlikely that any more calls to setMantissaScale() will be
* needed outside of unit tests.
@@ -344,16 +344,16 @@ concept Integral64 = std::is_same_v<T, std::int64_t> || std::is_same_v<T, std::u
* set/getMantissaScale() functions may be most appropriate. However, if the
* test has anything to do with transaction processing, it should enable or
* disable the amendments that control the mantissa range choice
* (SingleAssetVault and LendingProtocol), and/or check if either of those
* amendments are enabled to determine which result to expect.
* (SingleAssetVault, LendingProtocol, and MPTokensV2), and/or check if any of
* those amendments are enabled to determine which result to expect.
*/
class Number final
{
using rep = std::int64_t;
using internalrep = MantissaRange::rep;
using InternalRep = MantissaRange::rep;
bool negative_{false};
internalrep mantissa_{0};
InternalRep mantissa_{0};
int exponent_{std::numeric_limits<int>::lowest()};
public:
@@ -361,10 +361,10 @@ public:
static constexpr int kMinExponent = -32768;
static constexpr int kMaxExponent = 32768;
static constexpr internalrep kMaxRep = std::numeric_limits<rep>::max();
static constexpr InternalRep kMaxRep = std::numeric_limits<rep>::max();
static_assert(kMaxRep == 9'223'372'036'854'775'807);
static_assert(-kMaxRep == std::numeric_limits<rep>::min() + 1);
static constexpr internalrep kMaxRepUp = ((kMaxRep / 10) + 1) * 10;
static constexpr InternalRep kMaxRepUp = ((kMaxRep / 10) + 1) * 10;
static_assert(kMaxRepUp == 9'223'372'036'854'775'810ULL);
// May need to make unchecked private
@@ -388,15 +388,15 @@ public:
explicit Number(rep mantissa, int exponent);
explicit constexpr Number(
bool negative,
internalrep mantissa,
InternalRep mantissa,
int exponent,
Unchecked) noexcept;
// Assume unsigned values are... unsigned. i.e. positive
explicit constexpr Number(internalrep mantissa, int exponent, Unchecked) noexcept;
explicit constexpr Number(InternalRep mantissa, int exponent, Unchecked) noexcept;
// Only unit tests are expected to use this ctor
explicit Number(bool negative, internalrep mantissa, int exponent, Normalized);
explicit Number(bool negative, InternalRep mantissa, int exponent, Normalized);
// Assume unsigned values are... unsigned. i.e. positive
explicit Number(internalrep mantissa, int exponent, Normalized);
explicit Number(InternalRep mantissa, int exponent, Normalized);
[[nodiscard]] constexpr rep
mantissa() const noexcept;
@@ -558,13 +558,13 @@ public:
static void
setMantissaScale(MantissaRange::MantissaScale scale);
static internalrep
static InternalRep
minMantissa()
{
return kRange.get().min;
}
static internalrep
static InternalRep
maxMantissa()
{
return kRange.get().max;
@@ -591,7 +591,7 @@ public:
// is negative, returns the positive value. This takes a little extra work
// because converting std::numeric_limits<std::int64_t>::min() flirts with
// UB, and can vary across compilers.
static internalrep
static InternalRep
externalToInternal(rep mantissa);
private:
@@ -625,8 +625,8 @@ private:
bool& negative,
T& mantissa,
int& exponent,
internalrep const& minMantissa,
internalrep const& maxMantissa,
InternalRep const& minMantissa,
InternalRep const& maxMantissa,
MantissaRange::CuspRoundingFix cuspRoundingFix);
template <class T>
@@ -650,25 +650,25 @@ private:
shiftExponent(int exponentDelta) const;
};
constexpr Number::Number(bool negative, internalrep mantissa, int exponent, Unchecked) noexcept
constexpr Number::Number(bool negative, InternalRep mantissa, int exponent, Unchecked) noexcept
: negative_(negative), mantissa_{mantissa}, exponent_{exponent}
{
}
constexpr Number::Number(internalrep mantissa, int exponent, Unchecked) noexcept
constexpr Number::Number(InternalRep mantissa, int exponent, Unchecked) noexcept
: Number(false, mantissa, exponent, Unchecked{})
{
}
static constexpr Number kNumZero{};
inline Number::Number(bool negative, internalrep mantissa, int exponent, Normalized)
inline Number::Number(bool negative, InternalRep mantissa, int exponent, Normalized)
: Number(negative, mantissa, exponent, Unchecked{})
{
normalize(kRange);
}
inline Number::Number(internalrep mantissa, int exponent, Normalized)
inline Number::Number(InternalRep mantissa, int exponent, Normalized)
: Number(false, mantissa, exponent, Normalized{})
{
}
@@ -853,7 +853,7 @@ Number::normalizeToRange() const
static_assert((kMAX + 1) / 10 == kMIN);
bool negative = negative_;
internalrep mantissa = mantissa_;
InternalRep mantissa = mantissa_;
int exponent = exponent_;
if constexpr (std::is_unsigned_v<T>)

View File

@@ -21,11 +21,11 @@ The module xrpl/basics should contain no dependencies on other modules.
- `std::set`
- For sorted containers.
- `xrpl::hash_set`
- `xrpl::HashSet`
- Where inserts and contains need to be O(1).
- For "small" sets, `std::set` might be faster and smaller.
- `xrpl::hardened_hash_set`
- `xrpl::HardenedHashSet`
- For data sets where the key could be manipulated by an attacker
in an attempt to mount an algorithmic complexity attack: see
http://en.wikipedia.org/wiki/Algorithmic_complexity_attack
@@ -33,5 +33,5 @@ The module xrpl/basics should contain no dependencies on other modules.
The following container is deprecated
- `std::unordered_set`
- Use `xrpl::hash_set` instead, which uses a better hashing algorithm.
- Or use `xrpl::hardened_hash_set` to prevent algorithmic complexity attacks.
- Use `xrpl::HashSet` instead, which uses a better hashing algorithm.
- Or use `xrpl::HardenedHashSet` to prevent algorithmic complexity attacks.

View File

@@ -14,20 +14,20 @@ namespace xrpl {
class SHAMapHash
{
uint256 hash_;
UInt256 hash_;
public:
SHAMapHash() = default;
explicit SHAMapHash(uint256 const& hash) : hash_(hash)
explicit SHAMapHash(UInt256 const& hash) : hash_(hash)
{
}
[[nodiscard]] uint256 const&
[[nodiscard]] UInt256 const&
asUInt256() const
{
return hash_;
}
uint256&
UInt256&
asUInt256()
{
return hash_;

View File

@@ -59,34 +59,34 @@ template <
class T,
bool IsKeyCache = false,
class SharedWeakUnionPointerType = SharedWeakCachePointer<T>,
class SharedPointerType = std::shared_ptr<T>,
class SharedPointer = std::shared_ptr<T>,
class Hash = HardenedHash<>,
class KeyEqual = std::equal_to<Key>,
class Mutex = std::recursive_mutex>
class TaggedCache
{
public:
using mutex_type = Mutex;
using MutexType = Mutex;
using key_type = Key;
using mapped_type = T;
using clock_type = beast::AbstractClock<std::chrono::steady_clock>;
using shared_weak_combo_pointer_type = SharedWeakUnionPointerType;
using shared_pointer_type = SharedPointerType;
using ClockType = beast::AbstractClock<std::chrono::steady_clock>;
using SharedWeakComboPointerType = SharedWeakUnionPointerType;
using SharedPointerType = SharedPointer;
public:
TaggedCache(
std::string const& name,
int size,
clock_type::duration expiration,
clock_type& clock,
ClockType::duration expiration,
ClockType& clock,
beast::Journal journal,
beast::insight::Collector::ptr const& collector = beast::insight::NullCollector::make());
beast::insight::Collector::Ptr const& collector = beast::insight::NullCollector::make());
public:
/**
* Return the clock associated with the cache.
*/
clock_type&
ClockType&
clock();
/**
@@ -239,7 +239,7 @@ public:
bool
retrieve(key_type const& key, T& data);
mutex_type&
MutexType&
peekMutex();
std::vector<key_type>
@@ -265,7 +265,7 @@ public:
private:
SharedPointerType
initialFetch(key_type const& key, std::scoped_lock<mutex_type> const& l);
initialFetch(key_type const& key, std::scoped_lock<MutexType> const& l);
void
collectMetrics();
@@ -277,7 +277,7 @@ private:
Stats(
std::string const& prefix,
Handler const& handler,
beast::insight::Collector::ptr const& collector)
beast::insight::Collector::Ptr const& collector)
: hook(collector->makeHook(handler))
, size(collector->makeGauge(prefix, "size"))
, hitRate(collector->makeGauge(prefix, "hit_rate"))
@@ -296,14 +296,14 @@ private:
class KeyOnlyEntry
{
public:
clock_type::time_point lastAccess;
ClockType::time_point lastAccess;
explicit KeyOnlyEntry(clock_type::time_point const& lastAccess) : lastAccess(lastAccess)
explicit KeyOnlyEntry(ClockType::time_point const& lastAccess) : lastAccess(lastAccess)
{
}
void
touch(clock_type::time_point const& now)
touch(ClockType::time_point const& now)
{
lastAccess = now;
}
@@ -312,10 +312,10 @@ private:
class ValueEntry
{
public:
shared_weak_combo_pointer_type ptr;
clock_type::time_point lastAccess;
SharedWeakComboPointerType ptr;
ClockType::time_point lastAccess;
ValueEntry(clock_type::time_point const& lastAccess, shared_pointer_type const& ptr)
ValueEntry(ClockType::time_point const& lastAccess, SharedPointerType const& ptr)
: ptr(ptr), lastAccess(lastAccess)
{
}
@@ -343,7 +343,7 @@ private:
return ptr.lock();
}
void
touch(clock_type::time_point const& now)
touch(ClockType::time_point const& now)
{
lastAccess = now;
}
@@ -351,35 +351,35 @@ private:
using Entry = std::conditional_t<IsKeyCache, KeyOnlyEntry, ValueEntry>;
using KeyOnlyCacheType = hardened_partitioned_hash_map<key_type, KeyOnlyEntry, Hash, KeyEqual>;
using KeyOnlyCacheType = HardenedPartitionedHashMap<key_type, KeyOnlyEntry, Hash, KeyEqual>;
using KeyValueCacheType = hardened_partitioned_hash_map<key_type, ValueEntry, Hash, KeyEqual>;
using KeyValueCacheType = HardenedPartitionedHashMap<key_type, ValueEntry, Hash, KeyEqual>;
using cache_type = hardened_partitioned_hash_map<key_type, Entry, Hash, KeyEqual>;
using CacheType = HardenedPartitionedHashMap<key_type, Entry, Hash, KeyEqual>;
[[nodiscard]] std::thread
sweepHelper(
clock_type::time_point const& whenExpire,
[[maybe_unused]] clock_type::time_point const& now,
KeyValueCacheType::map_type& partition,
ClockType::time_point const& whenExpire,
[[maybe_unused]] ClockType::time_point const& now,
KeyValueCacheType::MapType& partition,
SweptPointersVector& stuffToSweep,
std::atomic<int>& allRemovals,
std::scoped_lock<std::recursive_mutex> const&);
[[nodiscard]] std::thread
sweepHelper(
clock_type::time_point const& whenExpire,
clock_type::time_point const& now,
KeyOnlyCacheType::map_type& partition,
ClockType::time_point const& whenExpire,
ClockType::time_point const& now,
KeyOnlyCacheType::MapType& partition,
SweptPointersVector&,
std::atomic<int>& allRemovals,
std::scoped_lock<std::recursive_mutex> const&);
beast::Journal journal_;
clock_type& clock_;
ClockType& clock_;
Stats stats_;
mutex_type mutable mutex_;
MutexType mutable mutex_;
// Used for logging
std::string name_;
@@ -388,11 +388,11 @@ private:
int const targetSize_;
// Desired maximum cache age
clock_type::duration const targetAge_;
ClockType::duration const targetAge_;
// Number of items cached
int cacheCount_{0};
cache_type cache_; // Hold strong reference to recent objects
CacheType cache_; // Hold strong reference to recent objects
std::uint64_t hits_{0};
std::uint64_t misses_{0};
};

View File

@@ -54,10 +54,10 @@ inline TaggedCache<
TaggedCache(
std::string const& name,
int size,
clock_type::duration expiration,
clock_type& clock,
ClockType::duration expiration,
ClockType& clock,
beast::Journal journal,
beast::insight::Collector::ptr const& collector)
beast::insight::Collector::Ptr const& collector)
: journal_(journal)
, clock_(clock)
, stats_(
@@ -81,7 +81,7 @@ template <
class Mutex>
inline auto
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
clock() -> clock_type&
clock() -> ClockType&
{
return clock_;
}
@@ -237,8 +237,8 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
// is destroyed but still within the main cache lock.
std::vector<SweptPointersVector> allStuffToSweep(cache_.partitions());
clock_type::time_point const now(clock_.now());
clock_type::time_point whenExpire;
ClockType::time_point const now(clock_.now());
ClockType::time_point whenExpire;
auto const start = std::chrono::steady_clock::now();
{
@@ -252,7 +252,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
{
whenExpire = now - (targetAge_ * targetSize_ / cache_.size());
clock_type::duration const minimumAge(std::chrono::seconds(1));
ClockType::duration const minimumAge(std::chrono::seconds(1));
if (whenExpire > (now - minimumAge))
whenExpire = now - minimumAge;
@@ -487,7 +487,7 @@ inline SharedPointerType
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
fetch(key_type const& key)
{
std::scoped_lock<mutex_type> const l(mutex_);
std::scoped_lock<MutexType> const l(mutex_);
auto ret = initialFetch(key, l);
if (!ret)
++misses_;
@@ -541,7 +541,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
requires IsKeyCache
{
std::scoped_lock const lock(mutex_);
clock_type::time_point const now(clock_.now());
ClockType::time_point const now(clock_.now());
auto [it, inserted] = cache_.emplace(
std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(now));
if (!inserted)
@@ -583,7 +583,7 @@ template <
class Mutex>
inline auto
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
peekMutex() -> mutex_type&
peekMutex() -> MutexType&
{
return mutex_;
}
@@ -711,7 +711,7 @@ template <
class Mutex>
inline SharedPointerType
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
initialFetch(key_type const& key, std::scoped_lock<mutex_type> const& l)
initialFetch(key_type const& key, std::scoped_lock<MutexType> const& l)
{
auto cit = cache_.find(key);
if (cit == cache_.end())
@@ -776,9 +776,9 @@ template <
inline std::thread
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
sweepHelper(
clock_type::time_point const& whenExpire,
[[maybe_unused]] clock_type::time_point const& now,
KeyValueCacheType::map_type& partition,
ClockType::time_point const& whenExpire,
[[maybe_unused]] ClockType::time_point const& now,
KeyValueCacheType::MapType& partition,
SweptPointersVector& stuffToSweep,
std::atomic<int>& allRemovals,
std::scoped_lock<std::recursive_mutex> const&)
@@ -856,9 +856,9 @@ template <
inline std::thread
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
sweepHelper(
clock_type::time_point const& whenExpire,
clock_type::time_point const& now,
KeyOnlyCacheType::map_type& partition,
ClockType::time_point const& whenExpire,
ClockType::time_point const& now,
KeyOnlyCacheType::MapType& partition,
SweptPointersVector&,
std::atomic<int>& allRemovals,
std::scoped_lock<std::recursive_mutex> const&)

View File

@@ -33,7 +33,7 @@ template <
class Hash = beast::Uhash<>,
class Pred = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, Value>>>
using hash_map = std::unordered_map<Key, Value, Hash, Pred, Allocator>;
using HashMap = std::unordered_map<Key, Value, Hash, Pred, Allocator>;
template <
class Key,
@@ -41,62 +41,62 @@ template <
class Hash = beast::Uhash<>,
class Pred = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, Value>>>
using hash_multimap = std::unordered_multimap<Key, Value, Hash, Pred, Allocator>;
using HashMultimap = std::unordered_multimap<Key, Value, Hash, Pred, Allocator>;
template <
class Value,
class Hash = beast::Uhash<>,
class Pred = std::equal_to<Value>,
class Allocator = std::allocator<Value>>
using hash_set = std::unordered_set<Value, Hash, Pred, Allocator>;
using HashSet = std::unordered_set<Value, Hash, Pred, Allocator>;
template <
class Value,
class Hash = beast::Uhash<>,
class Pred = std::equal_to<Value>,
class Allocator = std::allocator<Value>>
using hash_multiset = std::unordered_multiset<Value, Hash, Pred, Allocator>;
using HashMultiset = std::unordered_multiset<Value, Hash, Pred, Allocator>;
// hardened_hash containers
using strong_hash = beast::Xxhasher;
using StrongHash = beast::Xxhasher;
template <
class Key,
class Value,
class Hash = HardenedHash<strong_hash>,
class Hash = HardenedHash<StrongHash>,
class Pred = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, Value>>>
using hardened_hash_map = std::unordered_map<Key, Value, Hash, Pred, Allocator>;
using HardenedHashMap = std::unordered_map<Key, Value, Hash, Pred, Allocator>;
template <
class Key,
class Value,
class Hash = HardenedHash<strong_hash>,
class Hash = HardenedHash<StrongHash>,
class Pred = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, Value>>>
using hardened_partitioned_hash_map = PartitionedUnorderedMap<Key, Value, Hash, Pred, Allocator>;
using HardenedPartitionedHashMap = PartitionedUnorderedMap<Key, Value, Hash, Pred, Allocator>;
template <
class Key,
class Value,
class Hash = HardenedHash<strong_hash>,
class Hash = HardenedHash<StrongHash>,
class Pred = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, Value>>>
using hardened_hash_multimap = std::unordered_multimap<Key, Value, Hash, Pred, Allocator>;
using HardenedHashMultimap = std::unordered_multimap<Key, Value, Hash, Pred, Allocator>;
template <
class Value,
class Hash = HardenedHash<strong_hash>,
class Hash = HardenedHash<StrongHash>,
class Pred = std::equal_to<Value>,
class Allocator = std::allocator<Value>>
using hardened_hash_set = std::unordered_set<Value, Hash, Pred, Allocator>;
using HardenedHashSet = std::unordered_set<Value, Hash, Pred, Allocator>;
template <
class Value,
class Hash = HardenedHash<strong_hash>,
class Hash = HardenedHash<StrongHash>,
class Pred = std::equal_to<Value>,
class Allocator = std::allocator<Value>>
using hardened_hash_multiset = std::unordered_multiset<Value, Hash, Pred, Allocator>;
using HardenedHashMultiset = std::unordered_multiset<Value, Hash, Pred, Allocator>;
} // namespace xrpl

View File

@@ -111,7 +111,7 @@ public:
using const_iterator = const_pointer;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using tag_type = Tag;
using TagType = Tag;
pointer
data()
@@ -575,10 +575,16 @@ public:
}
};
using uint128 = BaseUInt<128>;
using uint160 = BaseUInt<160>;
using uint256 = BaseUInt<256>;
using uint192 = BaseUInt<192>;
using UInt128 = BaseUInt<128>;
using UInt160 = BaseUInt<160>;
using UInt256 = BaseUInt<256>;
using UInt192 = BaseUInt<192>;
// TODO [#8340]: Legacy names still used by external consumers of libxrpl (e.g. rpc-spec).
// Do not use in new code; remove once those consumers have migrated.
using uint160 = UInt160; // NOLINT(readability-identifier-naming)
using uint256 = UInt256; // NOLINT(readability-identifier-naming)
using uint192 = UInt192; // NOLINT(readability-identifier-naming)
template <std::size_t Bits, class Tag>
[[nodiscard]] constexpr std::strong_ordering
@@ -670,7 +676,7 @@ operator<<(std::ostream& out, BaseUInt<Bits, Tag> const& u)
template <>
inline std::size_t
extract(uint256 const& key)
extract(UInt256 const& key)
{
std::size_t result = 0;
// Use memcpy to avoid unaligned UB
@@ -680,10 +686,10 @@ extract(uint256 const& key)
}
#ifndef __INTELLISENSE__
static_assert(sizeof(uint128) == 128 / 8, "There should be no padding bytes");
static_assert(sizeof(uint160) == 160 / 8, "There should be no padding bytes");
static_assert(sizeof(uint192) == 192 / 8, "There should be no padding bytes");
static_assert(sizeof(uint256) == 256 / 8, "There should be no padding bytes");
static_assert(sizeof(UInt128) == 128 / 8, "There should be no padding bytes");
static_assert(sizeof(UInt160) == 160 / 8, "There should be no padding bytes");
static_assert(sizeof(UInt192) == 192 / 8, "There should be no padding bytes");
static_assert(sizeof(UInt256) == 256 / 8, "There should be no padding bytes");
#endif
} // namespace xrpl

View File

@@ -16,10 +16,10 @@ namespace xrpl {
// A few handy aliases
using days =
using Days =
std::chrono::duration<int, std::ratio_multiply<std::chrono::hours::period, std::ratio<24>>>;
using weeks = std::chrono::duration<int, std::ratio_multiply<days::period, std::ratio<7>>>;
using Weeks = std::chrono::duration<int, std::ratio_multiply<Days::period, std::ratio<7>>>;
/**
* Clock for measuring the network time.

View File

@@ -11,10 +11,10 @@ namespace xrpl {
namespace detail {
using seed_pair = std::pair<std::uint64_t, std::uint64_t>;
using SeedPair = std::pair<std::uint64_t, std::uint64_t>;
template <bool = true>
seed_pair
SeedPair
makeSeedPair() noexcept
{
struct StateT
@@ -71,7 +71,7 @@ template <class HashAlgorithm = beast::Xxhasher>
class HardenedHash
{
private:
detail::seed_pair seeds_{detail::makeSeedPair<>()};
detail::SeedPair seeds_{detail::makeSeedPair<>()};
public:
using result_type = HashAlgorithm::result_type;

View File

@@ -17,7 +17,7 @@
namespace xrpl {
template <typename Key>
static std::size_t
std::size_t
extract(Key const& key)
{
return key;
@@ -53,19 +53,19 @@ public:
using const_reference = value_type const&;
using pointer = value_type*;
using const_pointer = value_type const*;
using map_type = std::unordered_map<key_type, mapped_type, hasher, key_equal, allocator_type>;
using partition_map_type = std::vector<map_type>;
using MapType = std::unordered_map<key_type, mapped_type, hasher, key_equal, allocator_type>;
using PartitionMapType = std::vector<MapType>;
struct Iterator
{
using iterator_category = std::forward_iterator_tag;
partition_map_type* map{nullptr};
partition_map_type::iterator ait{};
map_type::iterator mit;
PartitionMapType* map{nullptr};
PartitionMapType::iterator ait{};
MapType::iterator mit;
Iterator() = default;
Iterator(partition_map_type* m) : map(m)
Iterator(PartitionMapType* m) : map(m)
{
}
@@ -122,13 +122,13 @@ public:
{
using iterator_category = std::forward_iterator_tag;
partition_map_type* map{nullptr};
partition_map_type::iterator ait{};
map_type::iterator mit;
PartitionMapType* map{nullptr};
PartitionMapType::iterator ait{};
MapType::iterator mit;
ConstIterator() = default;
ConstIterator(partition_map_type* m) : map(m)
ConstIterator(PartitionMapType* m) : map(m)
{
}
@@ -234,7 +234,7 @@ public:
return partitions_;
}
partition_map_type&
PartitionMapType&
map()
{
return map_;
@@ -377,7 +377,7 @@ public:
}
private:
mutable partition_map_type map_{};
mutable PartitionMapType map_{};
};
} // namespace xrpl

View File

@@ -14,13 +14,13 @@ namespace xrpl {
#ifndef __INTELLISENSE__
static_assert(
// NOLINTNEXTLINE(misc-redundant-expression)
std::is_integral_v<beast::xor_shift_engine::result_type> &&
std::is_unsigned_v<beast::xor_shift_engine::result_type>,
std::is_integral_v<beast::XorShiftEngine::result_type> &&
std::is_unsigned_v<beast::XorShiftEngine::result_type>,
"The XRPL default PRNG engine must return an unsigned integral type.");
static_assert(
// NOLINTNEXTLINE(misc-redundant-expression)
std::numeric_limits<beast::xor_shift_engine::result_type>::max() >=
std::numeric_limits<beast::XorShiftEngine::result_type>::max() >=
std::numeric_limits<std::uint64_t>::max(),
"The XRPL default PRNG engine return must be at least 64 bits wide.");
#endif
@@ -30,7 +30,7 @@ namespace detail {
// Determines if a type can be called like an Engine
// NOLINTNEXTLINE(readability-redundant-typename): typename required by MSVC
template <class Engine, class Result = typename Engine::result_type>
using is_engine = std::is_invocable_r<Result, Engine>;
using IsEngine = std::is_invocable_r<Result, Engine>;
} // namespace detail
/**
@@ -44,28 +44,28 @@ using is_engine = std::is_invocable_r<Result, Engine>;
* Each thread gets its own instance of the engine which
* will be randomly seeded.
*/
inline beast::xor_shift_engine&
inline beast::XorShiftEngine&
defaultPrng()
{
// This is used to seed the thread-specific PRNGs on demand
static beast::xor_shift_engine kSeeder = [] {
static beast::XorShiftEngine kSeeder = [] {
std::random_device rng;
std::uniform_int_distribution<std::uint64_t> distribution{1};
return beast::xor_shift_engine(distribution(rng));
return beast::XorShiftEngine(distribution(rng));
}();
// This protects the seeder
static std::mutex kM;
// The thread-specific PRNGs:
thread_local beast::xor_shift_engine kEngine = [] {
thread_local beast::XorShiftEngine kEngine = [] {
std::uint64_t seed = 0;
{
std::scoped_lock const lk(kM);
std::uniform_int_distribution<std::uint64_t> distribution{1};
seed = distribution(kSeeder);
}
return beast::xor_shift_engine{seed};
return beast::XorShiftEngine{seed};
}();
return kEngine;
@@ -95,7 +95,7 @@ defaultPrng()
template <class Engine, class Integral>
Integral
randInt(Engine& engine, Integral min, Integral max)
requires(std::is_integral_v<Integral> && detail::is_engine<Engine>::value)
requires(std::is_integral_v<Integral> && detail::IsEngine<Engine>::value)
{
XRPL_ASSERT(max > min, "xrpl::randInt : max over min inputs");
@@ -116,7 +116,7 @@ randInt(Integral min, Integral max)
template <class Engine, class Integral>
Integral
randInt(Engine& engine, Integral max)
requires(std::is_integral_v<Integral> && detail::is_engine<Engine>::value)
requires(std::is_integral_v<Integral> && detail::IsEngine<Engine>::value)
{
return randInt(engine, Integral(0), max);
}
@@ -132,7 +132,7 @@ randInt(Integral max)
template <class Integral, class Engine>
Integral
randInt(Engine& engine)
requires(std::is_integral_v<Integral> && detail::is_engine<Engine>::value)
requires(std::is_integral_v<Integral> && detail::IsEngine<Engine>::value)
{
return randInt(engine, std::numeric_limits<Integral>::max());
}
@@ -155,7 +155,7 @@ Byte
randByte(Engine& engine)
requires(
(std::is_same_v<Byte, unsigned char> || std::is_same_v<Byte, std::uint8_t>) &&
detail::is_engine<Engine>::value)
detail::IsEngine<Engine>::value)
{
return static_cast<Byte>(randInt<Engine, std::uint32_t>(
engine, std::numeric_limits<Byte>::min(), std::numeric_limits<Byte>::max()));

View File

@@ -40,7 +40,7 @@ private:
public:
using value_type = Int;
using tag_type = Tag;
using TagType = Tag;
TaggedInteger() = default;

View File

@@ -0,0 +1,10 @@
# beast's containers, clocks and Journal streambuf model std concepts, which mandate
# snake_case member type names.
#
# clang-tidy replaces rather than merges this option, so the list is the
# top-level one restated plus the 20 name(s) needed only here:
# allocator_type argument_type char_type const_local_iterator const_pointer const_reverse_iterator first_argument_type hasher int_type key_compare key_equal local_iterator native_handle_type off_type pos_type reverse_iterator second_argument_type traits_type type value_compare
InheritParentConfig: true
CheckOptions:
readability-identifier-naming.TypeAliasIgnoredRegexp: "^(allocator_type|argument_type|char_type|const_iterator|const_local_iterator|const_pointer|const_reference|const_reverse_iterator|difference_type|duration|first_argument_type|hasher|int_type|iterator|iterator_category|key_compare|key_equal|key_type|local_iterator|mapped_type|native_handle_type|off_type|period|pointer|pos_type|reference|rep|result_type|reverse_iterator|second_argument_type|size_type|time_point|traits_type|type|value_compare|value_type)$"
readability-identifier-naming.TypedefIgnoredRegexp: "^(allocator_type|argument_type|char_type|const_iterator|const_local_iterator|const_pointer|const_reference|const_reverse_iterator|difference_type|duration|first_argument_type|hasher|int_type|iterator|iterator_category|key_compare|key_equal|key_type|local_iterator|mapped_type|native_handle_type|off_type|period|pointer|pos_type|reference|rep|result_type|reverse_iterator|second_argument_type|size_type|time_point|traits_type|type|value_compare|value_type)$"

View File

@@ -9,7 +9,7 @@ namespace beast {
* an instance of the class can be dependency injected, facilitating
* unit tests where time may be controlled.
*
* An abstract_clock inherits all the nested types of the Clock
* An AbstractClock inherits all the nested types of the Clock
* template parameter.
*
* Example:
@@ -18,9 +18,9 @@ namespace beast {
*
* struct Implementation
* {
* using clock_type = abstract_clock <std::chrono::steady_clock>;
* clock_type& clock_;
* explicit Implementation (clock_type& clock)
* using ClockType = AbstractClock<std::chrono::steady_clock>;
* ClockType& clock_;
* explicit Implementation(ClockType& clock)
* : clock_(clock)
* {
* }
@@ -39,7 +39,7 @@ public:
using period = Clock::period;
using duration = Clock::duration;
using time_point = Clock::time_point;
using clock_type = Clock;
using ClockType = Clock;
static bool const is_steady = Clock::is_steady; // NOLINT(readability-identifier-naming)

View File

@@ -15,6 +15,6 @@ template <
class Clock = std::chrono::steady_clock,
class Compare = std::less<Key>,
class Allocator = std::allocator<std::pair<Key const, T>>>
using aged_map = detail::AgedOrderedContainer<false, true, Key, T, Clock, Compare, Allocator>;
using AgedMap = detail::AgedOrderedContainer<false, true, Key, T, Clock, Compare, Allocator>;
} // namespace beast

View File

@@ -15,6 +15,6 @@ template <
class Clock = std::chrono::steady_clock,
class Compare = std::less<Key>,
class Allocator = std::allocator<std::pair<Key const, T>>>
using aged_multimap = detail::AgedOrderedContainer<true, true, Key, T, Clock, Compare, Allocator>;
using AgedMultimap = detail::AgedOrderedContainer<true, true, Key, T, Clock, Compare, Allocator>;
} // namespace beast

View File

@@ -13,7 +13,7 @@ template <
class Clock = std::chrono::steady_clock,
class Compare = std::less<Key>,
class Allocator = std::allocator<Key>>
using aged_multiset =
using AgedMultiset =
detail::AgedOrderedContainer<true, false, Key, void, Clock, Compare, Allocator>;
} // namespace beast

View File

@@ -13,6 +13,6 @@ template <
class Clock = std::chrono::steady_clock,
class Compare = std::less<Key>,
class Allocator = std::allocator<Key>>
using aged_set = detail::AgedOrderedContainer<false, false, Key, void, Clock, Compare, Allocator>;
using AgedSet = detail::AgedOrderedContainer<false, false, Key, void, Clock, Compare, Allocator>;
} // namespace beast

View File

@@ -16,7 +16,7 @@ template <
class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T>>>
using aged_unordered_map =
using AgedUnorderedMap =
detail::AgedUnorderedContainer<false, true, Key, T, Clock, Hash, KeyEqual, Allocator>;
} // namespace beast

View File

@@ -16,7 +16,7 @@ template <
class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T>>>
using aged_unordered_multimap =
using AgedUnorderedMultimap =
detail::AgedUnorderedContainer<true, true, Key, T, Clock, Hash, KeyEqual, Allocator>;
} // namespace beast

View File

@@ -14,7 +14,7 @@ template <
class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator<Key>>
using aged_unordered_multiset =
using AgedUnorderedMultiset =
detail::AgedUnorderedContainer<true, false, Key, void, Clock, Hash, KeyEqual, Allocator>;
} // namespace beast

View File

@@ -14,7 +14,7 @@ template <
class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator<Key>>
using aged_unordered_set =
using AgedUnorderedSet =
detail::AgedUnorderedContainer<false, false, Key, void, Clock, Hash, KeyEqual, Allocator>;
} // namespace beast

View File

@@ -4,12 +4,7 @@
#include <type_traits>
#include <utility>
namespace beast {
template <bool, bool, class, class, class, class, class>
class aged_ordered_container;
namespace detail {
namespace beast::detail {
// If Iterator is SCARY then this iterator will be as well.
template <bool IsConst, class Iterator>
@@ -144,6 +139,4 @@ private:
Iterator iter_;
};
} // namespace detail
} // namespace beast
} // namespace beast::detail

View File

@@ -54,7 +54,7 @@ struct IsBoostReverseIterator<boost::intrusive::reverse_iterator<It>> : std::tru
* whose items expire after a certain amount of time. The chronological
* iterators allow for fully customizable expiration strategies.
*
* @see aged_set, aged_multiset, aged_map, aged_multimap
* @see AgedSet, AgedMultiset, AgedMap, AgedMultimap
*/
template <
bool IsMulti,
@@ -67,9 +67,9 @@ template <
class AgedOrderedContainer
{
public:
using clock_type = AbstractClock<Clock>;
using time_point = clock_type::time_point;
using duration = clock_type::duration;
using ClockType = AbstractClock<Clock>;
using time_point = ClockType::time_point;
using duration = ClockType::duration;
using key_type = Key;
using mapped_type = T;
using value_type = std::conditional_t<IsMap, std::pair<Key const, T>, Key>;
@@ -77,9 +77,9 @@ public:
using difference_type = std::ptrdiff_t;
// Introspection (for unit tests)
using is_unordered = std::false_type;
using is_multi = std::integral_constant<bool, IsMulti>;
using is_map = std::integral_constant<bool, IsMap>;
using IsUnorderedType = std::false_type;
using IsMultiType = std::integral_constant<bool, IsMulti>;
using IsMapType = std::integral_constant<bool, IsMap>;
private:
static Key const&
@@ -127,8 +127,8 @@ private:
class PairValueCompare : public Compare
{
public:
using first_argument = value_type;
using second_argument = value_type;
using FirstArgument = value_type;
using SecondArgument = value_type;
using result_type = bool;
bool
@@ -156,8 +156,8 @@ private:
class KeyValueCompare : public Compare
{
public:
using first_argument = Key;
using second_argument = Element;
using FirstArgument = Key;
using SecondArgument = Element;
using result_type = bool;
KeyValueCompare() = default;
@@ -197,10 +197,10 @@ private:
}
};
using list_type =
using ListType =
boost::intrusive::make_list<Element, boost::intrusive::constant_time_size<false>>::type;
using cont_type = std::conditional_t<
using ContType = std::conditional_t<
IsMulti,
typename boost::intrusive::make_multiset<
Element,
@@ -219,20 +219,20 @@ private:
public beast::detail::EmptyBaseOptimization<ElementAllocator>
{
public:
explicit ConfigT(clock_type& clock) : clock(clock)
explicit ConfigT(ClockType& clock) : clock(clock)
{
}
ConfigT(clock_type& clock, Compare const& comp) : KeyValueCompare(comp), clock(clock)
ConfigT(ClockType& clock, Compare const& comp) : KeyValueCompare(comp), clock(clock)
{
}
ConfigT(clock_type& clock, Allocator const& alloc)
ConfigT(ClockType& clock, Allocator const& alloc)
: beast::detail::EmptyBaseOptimization<ElementAllocator>(alloc), clock(clock)
{
}
ConfigT(clock_type& clock, Compare const& comp, Allocator const& alloc)
ConfigT(ClockType& clock, Compare const& comp, Allocator const& alloc)
: KeyValueCompare(comp)
, beast::detail::EmptyBaseOptimization<ElementAllocator>(alloc)
, clock(clock)
@@ -328,7 +328,7 @@ private:
return beast::detail::EmptyBaseOptimization<ElementAllocator>::member();
}
std::reference_wrapper<clock_type> clock;
std::reference_wrapper<ClockType> clock;
};
template <class... Args>
@@ -383,12 +383,12 @@ public:
// A set iterator (IsMap==false) is always const
// because the elements of a set are immutable.
using iterator = beast::detail::AgedContainerIterator<!IsMap, typename cont_type::iterator>;
using const_iterator = beast::detail::AgedContainerIterator<true, typename cont_type::iterator>;
using iterator = beast::detail::AgedContainerIterator<!IsMap, typename ContType::iterator>;
using const_iterator = beast::detail::AgedContainerIterator<true, typename ContType::iterator>;
using reverse_iterator =
beast::detail::AgedContainerIterator<!IsMap, typename cont_type::reverse_iterator>;
beast::detail::AgedContainerIterator<!IsMap, typename ContType::reverse_iterator>;
using const_reverse_iterator =
beast::detail::AgedContainerIterator<true, typename cont_type::reverse_iterator>;
beast::detail::AgedContainerIterator<true, typename ContType::reverse_iterator>;
//--------------------------------------------------------------------------
//
@@ -406,13 +406,13 @@ public:
public:
// A set iterator (IsMap==false) is always const
// because the elements of a set are immutable.
using iterator = beast::detail::AgedContainerIterator<!IsMap, typename list_type::iterator>;
using iterator = beast::detail::AgedContainerIterator<!IsMap, typename ListType::iterator>;
using const_iterator =
beast::detail::AgedContainerIterator<true, typename list_type::iterator>;
beast::detail::AgedContainerIterator<true, typename ListType::iterator>;
using reverse_iterator =
beast::detail::AgedContainerIterator<!IsMap, typename list_type::reverse_iterator>;
beast::detail::AgedContainerIterator<!IsMap, typename ListType::reverse_iterator>;
using const_reverse_iterator =
beast::detail::AgedContainerIterator<true, typename list_type::reverse_iterator>;
beast::detail::AgedContainerIterator<true, typename ListType::reverse_iterator>;
iterator
begin()
@@ -509,7 +509,7 @@ public:
private:
friend class AgedOrderedContainer;
list_type mutable list_;
ListType mutable list_;
} chronological;
//--------------------------------------------------------------------------
@@ -520,28 +520,28 @@ public:
AgedOrderedContainer() = delete;
explicit AgedOrderedContainer(clock_type& clock);
explicit AgedOrderedContainer(ClockType& clock);
AgedOrderedContainer(clock_type& clock, Compare const& comp);
AgedOrderedContainer(ClockType& clock, Compare const& comp);
AgedOrderedContainer(clock_type& clock, Allocator const& alloc);
AgedOrderedContainer(ClockType& clock, Allocator const& alloc);
AgedOrderedContainer(clock_type& clock, Compare const& comp, Allocator const& alloc);
AgedOrderedContainer(ClockType& clock, Compare const& comp, Allocator const& alloc);
template <class InputIt>
AgedOrderedContainer(InputIt first, InputIt last, clock_type& clock);
AgedOrderedContainer(InputIt first, InputIt last, ClockType& clock);
template <class InputIt>
AgedOrderedContainer(InputIt first, InputIt last, clock_type& clock, Compare const& comp);
AgedOrderedContainer(InputIt first, InputIt last, ClockType& clock, Compare const& comp);
template <class InputIt>
AgedOrderedContainer(InputIt first, InputIt last, clock_type& clock, Allocator const& alloc);
AgedOrderedContainer(InputIt first, InputIt last, ClockType& clock, Allocator const& alloc);
template <class InputIt>
AgedOrderedContainer(
InputIt first,
InputIt last,
clock_type& clock,
ClockType& clock,
Compare const& comp,
Allocator const& alloc);
@@ -556,21 +556,21 @@ public:
AgedOrderedContainer&& other,
Allocator const& alloc);
AgedOrderedContainer(std::initializer_list<value_type> init, clock_type& clock);
AgedOrderedContainer(std::initializer_list<value_type> init, ClockType& clock);
AgedOrderedContainer(
std::initializer_list<value_type> init,
clock_type& clock,
ClockType& clock,
Compare const& comp);
AgedOrderedContainer(
std::initializer_list<value_type> init,
clock_type& clock,
ClockType& clock,
Allocator const& alloc);
AgedOrderedContainer(
std::initializer_list<value_type> init,
clock_type& clock,
ClockType& clock,
Compare const& comp,
Allocator const& alloc);
@@ -591,13 +591,13 @@ public:
return config_.alloc();
}
clock_type&
ClockType&
clock()
{
return config_.clock;
}
clock_type const&
ClockType const&
clock() const
{
return config_.clock;
@@ -820,7 +820,7 @@ public:
template <class P, bool MaybeMap = IsMap>
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>
insert(P&& value)
requires(MaybeMap && std::is_constructible_v<value_type, P &&>)
requires(MaybeMap && std::is_constructible_v<value_type, P&&>)
{
return emplace(std::forward<P>(value));
}
@@ -829,7 +829,7 @@ public:
template <class P, bool MaybeMap = IsMap>
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>
insert(const_iterator hint, P&& value)
requires(MaybeMap && std::is_constructible_v<value_type, P &&>)
requires(MaybeMap && std::is_constructible_v<value_type, P&&>)
{
return emplaceHint(hint, std::forward<P>(value));
}
@@ -1121,7 +1121,7 @@ private:
void
touch(
beast::detail::AgedContainerIterator<IsConst, Iterator> pos,
clock_type::time_point const& now)
ClockType::time_point const& now)
requires(!IsBoostReverseIterator<Iterator>::value);
template <
@@ -1138,21 +1138,21 @@ private:
private:
ConfigT config_;
cont_type mutable cont_;
ContType mutable cont_;
};
//------------------------------------------------------------------------------
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrderedContainer(
clock_type& clock)
ClockType& clock)
: config_(clock)
{
}
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrderedContainer(
clock_type& clock,
ClockType& clock,
Compare const& comp)
: config_(clock, comp), cont_(comp)
{
@@ -1160,7 +1160,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrd
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrderedContainer(
clock_type& clock,
ClockType& clock,
Allocator const& alloc)
: config_(clock, alloc)
{
@@ -1168,7 +1168,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrd
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrderedContainer(
clock_type& clock,
ClockType& clock,
Compare const& comp,
Allocator const& alloc)
: config_(clock, comp, alloc), cont_(comp)
@@ -1180,7 +1180,7 @@ template <class InputIt>
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrderedContainer(
InputIt first,
InputIt last,
clock_type& clock)
ClockType& clock)
: config_(clock)
{
insert(first, last);
@@ -1191,7 +1191,7 @@ template <class InputIt>
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrderedContainer(
InputIt first,
InputIt last,
clock_type& clock,
ClockType& clock,
Compare const& comp)
: config_(clock, comp), cont_(comp)
{
@@ -1203,7 +1203,7 @@ template <class InputIt>
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrderedContainer(
InputIt first,
InputIt last,
clock_type& clock,
ClockType& clock,
Allocator const& alloc)
: config_(clock, alloc)
{
@@ -1215,7 +1215,7 @@ template <class InputIt>
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrderedContainer(
InputIt first,
InputIt last,
clock_type& clock,
ClockType& clock,
Compare const& comp,
Allocator const& alloc)
: config_(clock, comp, alloc), cont_(comp)
@@ -1261,7 +1261,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrd
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrderedContainer(
std::initializer_list<value_type> init,
clock_type& clock)
ClockType& clock)
: config_(clock)
{
insert(init.begin(), init.end());
@@ -1270,7 +1270,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrd
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrderedContainer(
std::initializer_list<value_type> init,
clock_type& clock,
ClockType& clock,
Compare const& comp)
: config_(clock, comp), cont_(comp)
{
@@ -1280,7 +1280,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrd
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrderedContainer(
std::initializer_list<value_type> init,
clock_type& clock,
ClockType& clock,
Allocator const& alloc)
: config_(clock, alloc)
{
@@ -1290,7 +1290,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrd
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::AgedOrderedContainer(
std::initializer_list<value_type> init,
clock_type& clock,
ClockType& clock,
Compare const& comp,
Allocator const& alloc)
: config_(clock, comp, alloc), cont_(comp)
@@ -1372,7 +1372,7 @@ std::conditional_t<IsMap, T, void*>&
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operator[](Key const& key)
requires(MaybeMap && !MaybeMulti)
{
typename cont_type::insert_commit_data d;
typename ContType::insert_commit_data d;
auto const result(cont_.insert_check(key, std::cref(config_.keyCompare()), d));
if (result.second)
{
@@ -1391,7 +1391,7 @@ std::conditional_t<IsMap, T, void*>&
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operator[](Key&& key)
requires(MaybeMap && !MaybeMulti)
{
typename cont_type::insert_commit_data d;
typename ContType::insert_commit_data d;
auto const result(cont_.insert_check(key, std::cref(config_.keyCompare()), d));
if (result.second)
{
@@ -1426,7 +1426,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(
value_type const& value) -> std::pair<iterator, bool>
requires(!MaybeMulti)
{
typename cont_type::insert_commit_data d;
typename ContType::insert_commit_data d;
auto const result(cont_.insert_check(extract(value), std::cref(config_.keyCompare()), d));
if (result.second)
{
@@ -1461,7 +1461,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(
-> std::pair<iterator, bool>
requires(!MaybeMulti && !MaybeMap)
{
typename cont_type::insert_commit_data d;
typename ContType::insert_commit_data d;
auto const result(cont_.insert_check(extract(value), std::cref(config_.keyCompare()), d));
if (result.second)
{
@@ -1499,7 +1499,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(
value_type const& value) -> iterator
requires(!MaybeMulti)
{
typename cont_type::insert_commit_data d;
typename ContType::insert_commit_data d;
auto const result(
cont_.insert_check(hint.iterator(), extract(value), std::cref(config_.keyCompare()), d));
if (result.second)
@@ -1521,7 +1521,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::insert(
value_type&& value) -> iterator
requires(!MaybeMulti)
{
typename cont_type::insert_commit_data d;
typename ContType::insert_commit_data d;
auto const result(
cont_.insert_check(hint.iterator(), extract(value), std::cref(config_.keyCompare()), d));
if (result.second)
@@ -1545,7 +1545,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::emplace
// VFALCO NOTE Its unfortunate that we need to
// construct element here
Element* const p(newElement(std::forward<Args>(args)...));
typename cont_type::insert_commit_data d;
typename ContType::insert_commit_data d;
auto const result(cont_.insert_check(extract(p->value), std::cref(config_.keyCompare()), d));
if (result.second)
{
@@ -1584,7 +1584,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::emplace
// VFALCO NOTE Its unfortunate that we need to
// construct element here
Element* const p(newElement(std::forward<Args>(args)...));
typename cont_type::insert_commit_data d;
typename ContType::insert_commit_data d;
auto const result(
cont_.insert_check(hint.iterator(), extract(p->value), std::cref(config_.keyCompare()), d));
if (result.second)
@@ -1721,7 +1721,7 @@ template <bool IsConst, class Iterator>
void
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::touch(
beast::detail::AgedContainerIterator<IsConst, Iterator> pos,
clock_type::time_point const& now)
ClockType::time_point const& now)
requires(!IsBoostReverseIterator<Iterator>::value)
{
auto& e(*pos.iterator());

View File

@@ -59,8 +59,8 @@ namespace detail {
* whose items expire after a certain amount of time. The chronological
* iterators allow for fully customizable expiration strategies.
*
* @see aged_unordered_set, aged_unordered_multiset
* @see aged_unordered_map, aged_unordered_multimap
* @see AgedUnorderedSet, AgedUnorderedMultiset
* @see AgedUnorderedMap, AgedUnorderedMultimap
*/
template <
bool IsMulti,
@@ -74,9 +74,9 @@ template <
class AgedUnorderedContainer
{
public:
using clock_type = AbstractClock<Clock>;
using time_point = clock_type::time_point;
using duration = clock_type::duration;
using ClockType = AbstractClock<Clock>;
using time_point = ClockType::time_point;
using duration = ClockType::duration;
using key_type = Key;
using mapped_type = T;
using value_type = std::conditional_t<IsMap, std::pair<Key const, T>, Key>;
@@ -84,9 +84,9 @@ public:
using difference_type = std::ptrdiff_t;
// Introspection (for unit tests)
using is_unordered = std::true_type;
using is_multi = std::integral_constant<bool, IsMulti>;
using is_map = std::integral_constant<bool, IsMap>;
using IsUnorderedType = std::true_type;
using IsMultiType = std::integral_constant<bool, IsMulti>;
using IsMapType = std::integral_constant<bool, IsMap>;
private:
static Key const&
@@ -208,10 +208,10 @@ private:
}
};
using list_type =
using ListType =
boost::intrusive::make_list<Element, boost::intrusive::constant_time_size<false>>::type;
using cont_type = std::conditional_t<
using ContType = std::conditional_t<
IsMulti,
typename boost::intrusive::make_unordered_multiset<
Element,
@@ -226,8 +226,8 @@ private:
boost::intrusive::equal<KeyValueEqual>,
boost::intrusive::cache_begin<true>>::type>;
using bucket_type = cont_type::bucket_type;
using bucket_traits = cont_type::bucket_traits;
using BucketType = ContType::bucket_type;
using BucketTraits = ContType::bucket_traits;
using ElementAllocator = std::allocator_traits<Allocator>::template rebind_alloc<Element>;
@@ -242,36 +242,36 @@ private:
private beast::detail::EmptyBaseOptimization<ElementAllocator>
{
public:
explicit ConfigT(clock_type& clock) : clock(clock)
explicit ConfigT(ClockType& clock) : clock(clock)
{
}
ConfigT(clock_type& clock, Hash const& hash) : ValueHash(hash), clock(clock)
ConfigT(ClockType& clock, Hash const& hash) : ValueHash(hash), clock(clock)
{
}
ConfigT(clock_type& clock, KeyEqual const& keyEqual) : KeyValueEqual(keyEqual), clock(clock)
ConfigT(ClockType& clock, KeyEqual const& keyEqual) : KeyValueEqual(keyEqual), clock(clock)
{
}
ConfigT(clock_type& clock, Allocator const& alloc)
ConfigT(ClockType& clock, Allocator const& alloc)
: beast::detail::EmptyBaseOptimization<ElementAllocator>(alloc), clock(clock)
{
}
ConfigT(clock_type& clock, Hash const& hash, KeyEqual const& keyEqual)
ConfigT(ClockType& clock, Hash const& hash, KeyEqual const& keyEqual)
: ValueHash(hash), KeyValueEqual(keyEqual), clock(clock)
{
}
ConfigT(clock_type& clock, Hash const& hash, Allocator const& alloc)
ConfigT(ClockType& clock, Hash const& hash, Allocator const& alloc)
: ValueHash(hash)
, beast::detail::EmptyBaseOptimization<ElementAllocator>(alloc)
, clock(clock)
{
}
ConfigT(clock_type& clock, KeyEqual const& keyEqual, Allocator const& alloc)
ConfigT(ClockType& clock, KeyEqual const& keyEqual, Allocator const& alloc)
: KeyValueEqual(keyEqual)
, beast::detail::EmptyBaseOptimization<ElementAllocator>(alloc)
, clock(clock)
@@ -279,7 +279,7 @@ private:
}
ConfigT(
clock_type& clock,
ClockType& clock,
Hash const& hash,
KeyEqual const& keyEqual,
Allocator const& alloc)
@@ -405,29 +405,29 @@ private:
return beast::detail::EmptyBaseOptimization<ElementAllocator>::member();
}
std::reference_wrapper<clock_type> clock;
std::reference_wrapper<ClockType> clock;
};
class Buckets
{
public:
using vec_type = std::vector<
bucket_type,
typename std::allocator_traits<Allocator>::template rebind_alloc<bucket_type>>;
using VecType = std::vector<
BucketType,
typename std::allocator_traits<Allocator>::template rebind_alloc<BucketType>>;
Buckets() : maxLoadFactor_(1.f), vec_()
{
vec_.resize(cont_type::suggested_upper_bucket_count(0));
vec_.resize(ContType::suggested_upper_bucket_count(0));
}
Buckets(Allocator const& alloc) : maxLoadFactor_(1.f), vec_(alloc)
{
vec_.resize(cont_type::suggested_upper_bucket_count(0));
vec_.resize(ContType::suggested_upper_bucket_count(0));
}
operator bucket_traits()
operator BucketTraits()
{
return bucket_traits(&vec_[0], vec_.size());
return BucketTraits(&vec_[0], vec_.size());
}
void
@@ -466,10 +466,10 @@ private:
{
// Need two vectors otherwise we
// will destroy non-empty buckets.
vec_type vec(vec_.get_allocator());
VecType vec(vec_.get_allocator());
std::swap(vec_, vec);
vec_.resize(count);
c.rehash(bucket_traits(&vec_[0], vec_.size()));
c.rehash(BucketTraits(&vec_[0], vec_.size()));
return;
}
// Rehash in place.
@@ -478,12 +478,12 @@ private:
// This should not reallocate since
// we checked capacity earlier.
vec_.resize(count);
c.rehash(bucket_traits(&vec_[0], count));
c.rehash(BucketTraits(&vec_[0], count));
return;
}
// Resize must happen after rehash otherwise
// we might destroy non-empty buckets.
c.rehash(bucket_traits(&vec_[0], count));
c.rehash(BucketTraits(&vec_[0], count));
vec_.resize(count);
}
@@ -492,13 +492,13 @@ private:
void
resize(size_type n, Container& c)
{
size_type const suggested(cont_type::suggested_upper_bucket_count(n));
size_type const suggested(ContType::suggested_upper_bucket_count(n));
rehash(suggested, c);
}
private:
float maxLoadFactor_;
vec_type vec_;
VecType vec_;
};
template <class... Args>
@@ -553,13 +553,13 @@ public:
// A set iterator (IsMap==false) is always const
// because the elements of a set are immutable.
using iterator = beast::detail::AgedContainerIterator<!IsMap, typename cont_type::iterator>;
using const_iterator = beast::detail::AgedContainerIterator<true, typename cont_type::iterator>;
using iterator = beast::detail::AgedContainerIterator<!IsMap, typename ContType::iterator>;
using const_iterator = beast::detail::AgedContainerIterator<true, typename ContType::iterator>;
using local_iterator =
beast::detail::AgedContainerIterator<!IsMap, typename cont_type::local_iterator>;
beast::detail::AgedContainerIterator<!IsMap, typename ContType::local_iterator>;
using const_local_iterator =
beast::detail::AgedContainerIterator<true, typename cont_type::local_iterator>;
beast::detail::AgedContainerIterator<true, typename ContType::local_iterator>;
//--------------------------------------------------------------------------
//
@@ -575,13 +575,13 @@ public:
public:
// A set iterator (IsMap==false) is always const
// because the elements of a set are immutable.
using iterator = beast::detail::AgedContainerIterator<!IsMap, typename list_type::iterator>;
using iterator = beast::detail::AgedContainerIterator<!IsMap, typename ListType::iterator>;
using const_iterator =
beast::detail::AgedContainerIterator<true, typename list_type::iterator>;
beast::detail::AgedContainerIterator<true, typename ListType::iterator>;
using reverse_iterator =
beast::detail::AgedContainerIterator<!IsMap, typename list_type::reverse_iterator>;
beast::detail::AgedContainerIterator<!IsMap, typename ListType::reverse_iterator>;
using const_reverse_iterator =
beast::detail::AgedContainerIterator<true, typename list_type::reverse_iterator>;
beast::detail::AgedContainerIterator<true, typename ListType::reverse_iterator>;
iterator
begin()
@@ -679,7 +679,7 @@ public:
private:
friend class AgedUnorderedContainer;
list_type mutable list_;
ListType mutable list_;
} chronological;
//--------------------------------------------------------------------------
@@ -690,43 +690,43 @@ public:
AgedUnorderedContainer() = delete;
explicit AgedUnorderedContainer(clock_type& clock);
explicit AgedUnorderedContainer(ClockType& clock);
AgedUnorderedContainer(clock_type& clock, Hash const& hash);
AgedUnorderedContainer(ClockType& clock, Hash const& hash);
AgedUnorderedContainer(clock_type& clock, KeyEqual const& keyEq);
AgedUnorderedContainer(ClockType& clock, KeyEqual const& keyEq);
AgedUnorderedContainer(clock_type& clock, Allocator const& alloc);
AgedUnorderedContainer(ClockType& clock, Allocator const& alloc);
AgedUnorderedContainer(clock_type& clock, Hash const& hash, KeyEqual const& keyEq);
AgedUnorderedContainer(ClockType& clock, Hash const& hash, KeyEqual const& keyEq);
AgedUnorderedContainer(clock_type& clock, Hash const& hash, Allocator const& alloc);
AgedUnorderedContainer(ClockType& clock, Hash const& hash, Allocator const& alloc);
AgedUnorderedContainer(clock_type& clock, KeyEqual const& keyEq, Allocator const& alloc);
AgedUnorderedContainer(ClockType& clock, KeyEqual const& keyEq, Allocator const& alloc);
AgedUnorderedContainer(
clock_type& clock,
ClockType& clock,
Hash const& hash,
KeyEqual const& keyEq,
Allocator const& alloc);
template <class InputIt>
AgedUnorderedContainer(InputIt first, InputIt last, clock_type& clock);
AgedUnorderedContainer(InputIt first, InputIt last, ClockType& clock);
template <class InputIt>
AgedUnorderedContainer(InputIt first, InputIt last, clock_type& clock, Hash const& hash);
AgedUnorderedContainer(InputIt first, InputIt last, ClockType& clock, Hash const& hash);
template <class InputIt>
AgedUnorderedContainer(InputIt first, InputIt last, clock_type& clock, KeyEqual const& keyEq);
AgedUnorderedContainer(InputIt first, InputIt last, ClockType& clock, KeyEqual const& keyEq);
template <class InputIt>
AgedUnorderedContainer(InputIt first, InputIt last, clock_type& clock, Allocator const& alloc);
AgedUnorderedContainer(InputIt first, InputIt last, ClockType& clock, Allocator const& alloc);
template <class InputIt>
AgedUnorderedContainer(
InputIt first,
InputIt last,
clock_type& clock,
ClockType& clock,
Hash const& hash,
KeyEqual const& keyEq);
@@ -734,7 +734,7 @@ public:
AgedUnorderedContainer(
InputIt first,
InputIt last,
clock_type& clock,
ClockType& clock,
Hash const& hash,
Allocator const& alloc);
@@ -742,7 +742,7 @@ public:
AgedUnorderedContainer(
InputIt first,
InputIt last,
clock_type& clock,
ClockType& clock,
KeyEqual const& keyEq,
Allocator const& alloc);
@@ -750,7 +750,7 @@ public:
AgedUnorderedContainer(
InputIt first,
InputIt last,
clock_type& clock,
ClockType& clock,
Hash const& hash,
KeyEqual const& keyEq,
Allocator const& alloc);
@@ -766,44 +766,44 @@ public:
AgedUnorderedContainer&& other,
Allocator const& alloc);
AgedUnorderedContainer(std::initializer_list<value_type> init, clock_type& clock);
AgedUnorderedContainer(std::initializer_list<value_type> init, ClockType& clock);
AgedUnorderedContainer(
std::initializer_list<value_type> init,
clock_type& clock,
ClockType& clock,
Hash const& hash);
AgedUnorderedContainer(
std::initializer_list<value_type> init,
clock_type& clock,
ClockType& clock,
KeyEqual const& keyEq);
AgedUnorderedContainer(
std::initializer_list<value_type> init,
clock_type& clock,
ClockType& clock,
Allocator const& alloc);
AgedUnorderedContainer(
std::initializer_list<value_type> init,
clock_type& clock,
ClockType& clock,
Hash const& hash,
KeyEqual const& keyEq);
AgedUnorderedContainer(
std::initializer_list<value_type> init,
clock_type& clock,
ClockType& clock,
Hash const& hash,
Allocator const& alloc);
AgedUnorderedContainer(
std::initializer_list<value_type> init,
clock_type& clock,
ClockType& clock,
KeyEqual const& keyEq,
Allocator const& alloc);
AgedUnorderedContainer(
std::initializer_list<value_type> init,
clock_type& clock,
ClockType& clock,
Hash const& hash,
KeyEqual const& keyEq,
Allocator const& alloc);
@@ -825,13 +825,13 @@ public:
return config_.alloc();
}
clock_type&
ClockType&
clock()
{
return config_.clock;
}
clock_type const&
ClockType const&
clock() const
{
return config_.clock;
@@ -1028,7 +1028,7 @@ public:
template <class P, bool MaybeMap = IsMap>
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>
insert(P&& value)
requires(MaybeMap && std::is_constructible_v<value_type, P &&>)
requires(MaybeMap && std::is_constructible_v<value_type, P&&>)
{
return emplace(std::forward<P>(value));
}
@@ -1037,7 +1037,7 @@ public:
template <class P, bool MaybeMap = IsMap>
std::conditional_t<IsMulti, iterator, std::pair<iterator, bool>>
insert(const_iterator hint, P&& value)
requires(MaybeMap && std::is_constructible_v<value_type, P &&>)
requires(MaybeMap && std::is_constructible_v<value_type, P&&>)
{
return emplaceHint(hint, std::forward<P>(value));
}
@@ -1399,7 +1399,7 @@ private:
void
touch(
beast::detail::AgedContainerIterator<IsConst, Iterator> pos,
clock_type::time_point const& now)
ClockType::time_point const& now)
{
auto& e(*pos.iterator());
e.when = now;
@@ -1433,7 +1433,7 @@ private:
private:
ConfigT config_;
Buckets buck_;
cont_type mutable cont_;
ContType mutable cont_;
};
//------------------------------------------------------------------------------
@@ -1448,7 +1448,7 @@ template <
class KeyEqual,
class Allocator>
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
AgedUnorderedContainer(clock_type& clock)
AgedUnorderedContainer(ClockType& clock)
: config_(clock)
, cont_(buck_, std::cref(config_.valueHash()), std::cref(config_.keyValueEqual()))
{
@@ -1464,7 +1464,7 @@ template <
class KeyEqual,
class Allocator>
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
AgedUnorderedContainer(clock_type& clock, Hash const& hash)
AgedUnorderedContainer(ClockType& clock, Hash const& hash)
: config_(clock, hash)
, cont_(buck_, std::cref(config_.valueHash()), std::cref(config_.keyValueEqual()))
{
@@ -1480,7 +1480,7 @@ template <
class KeyEqual,
class Allocator>
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
AgedUnorderedContainer(clock_type& clock, KeyEqual const& keyEq)
AgedUnorderedContainer(ClockType& clock, KeyEqual const& keyEq)
: config_(clock, keyEq)
, cont_(buck_, std::cref(config_.valueHash()), std::cref(config_.keyValueEqual()))
{
@@ -1496,7 +1496,7 @@ template <
class KeyEqual,
class Allocator>
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
AgedUnorderedContainer(clock_type& clock, Allocator const& alloc)
AgedUnorderedContainer(ClockType& clock, Allocator const& alloc)
: config_(clock, alloc)
, buck_(alloc)
, cont_(buck_, std::cref(config_.valueHash()), std::cref(config_.keyValueEqual()))
@@ -1513,7 +1513,7 @@ template <
class KeyEqual,
class Allocator>
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
AgedUnorderedContainer(clock_type& clock, Hash const& hash, KeyEqual const& keyEq)
AgedUnorderedContainer(ClockType& clock, Hash const& hash, KeyEqual const& keyEq)
: config_(clock, hash, keyEq)
, cont_(buck_, std::cref(config_.valueHash()), std::cref(config_.keyValueEqual()))
{
@@ -1529,7 +1529,7 @@ template <
class KeyEqual,
class Allocator>
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
AgedUnorderedContainer(clock_type& clock, Hash const& hash, Allocator const& alloc)
AgedUnorderedContainer(ClockType& clock, Hash const& hash, Allocator const& alloc)
: config_(clock, hash, alloc)
, buck_(alloc)
, cont_(buck_, std::cref(config_.valueHash()), std::cref(config_.keyValueEqual()))
@@ -1546,7 +1546,7 @@ template <
class KeyEqual,
class Allocator>
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
AgedUnorderedContainer(clock_type& clock, KeyEqual const& keyEq, Allocator const& alloc)
AgedUnorderedContainer(ClockType& clock, KeyEqual const& keyEq, Allocator const& alloc)
: config_(clock, keyEq, alloc)
, buck_(alloc)
, cont_(buck_, std::cref(config_.valueHash()), std::cref(config_.keyValueEqual()))
@@ -1564,7 +1564,7 @@ template <
class Allocator>
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
AgedUnorderedContainer(
clock_type& clock,
ClockType& clock,
Hash const& hash,
KeyEqual const& keyEq,
Allocator const& alloc)
@@ -1585,7 +1585,7 @@ template <
class Allocator>
template <class InputIt>
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
AgedUnorderedContainer(InputIt first, InputIt last, clock_type& clock)
AgedUnorderedContainer(InputIt first, InputIt last, ClockType& clock)
: config_(clock)
, cont_(buck_, std::cref(config_.valueHash()), std::cref(config_.keyValueEqual()))
{
@@ -1603,7 +1603,7 @@ template <
class Allocator>
template <class InputIt>
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
AgedUnorderedContainer(InputIt first, InputIt last, clock_type& clock, Hash const& hash)
AgedUnorderedContainer(InputIt first, InputIt last, ClockType& clock, Hash const& hash)
: config_(clock, hash)
, cont_(buck_, std::cref(config_.valueHash()), std::cref(config_.keyValueEqual()))
{
@@ -1621,7 +1621,7 @@ template <
class Allocator>
template <class InputIt>
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
AgedUnorderedContainer(InputIt first, InputIt last, clock_type& clock, KeyEqual const& keyEq)
AgedUnorderedContainer(InputIt first, InputIt last, ClockType& clock, KeyEqual const& keyEq)
: config_(clock, keyEq)
, cont_(buck_, std::cref(config_.valueHash()), std::cref(config_.keyValueEqual()))
{
@@ -1639,7 +1639,7 @@ template <
class Allocator>
template <class InputIt>
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
AgedUnorderedContainer(InputIt first, InputIt last, clock_type& clock, Allocator const& alloc)
AgedUnorderedContainer(InputIt first, InputIt last, ClockType& clock, Allocator const& alloc)
: config_(clock, alloc)
, buck_(alloc)
, cont_(buck_, std::cref(config_.valueHash()), std::cref(config_.keyValueEqual()))
@@ -1661,7 +1661,7 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
AgedUnorderedContainer(
InputIt first,
InputIt last,
clock_type& clock,
ClockType& clock,
Hash const& hash,
KeyEqual const& keyEq)
: config_(clock, hash, keyEq)
@@ -1684,7 +1684,7 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
AgedUnorderedContainer(
InputIt first,
InputIt last,
clock_type& clock,
ClockType& clock,
Hash const& hash,
Allocator const& alloc)
: config_(clock, hash, alloc)
@@ -1708,7 +1708,7 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
AgedUnorderedContainer(
InputIt first,
InputIt last,
clock_type& clock,
ClockType& clock,
KeyEqual const& keyEq,
Allocator const& alloc)
: config_(clock, keyEq, alloc)
@@ -1732,7 +1732,7 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
AgedUnorderedContainer(
InputIt first,
InputIt last,
clock_type& clock,
ClockType& clock,
Hash const& hash,
KeyEqual const& keyEq,
Allocator const& alloc)
@@ -1829,7 +1829,7 @@ template <
class KeyEqual,
class Allocator>
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
AgedUnorderedContainer(std::initializer_list<value_type> init, clock_type& clock)
AgedUnorderedContainer(std::initializer_list<value_type> init, ClockType& clock)
: config_(clock)
, cont_(buck_, std::cref(config_.valueHash()), std::cref(config_.keyValueEqual()))
{
@@ -1848,7 +1848,7 @@ template <
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
AgedUnorderedContainer(
std::initializer_list<value_type> init,
clock_type& clock,
ClockType& clock,
Hash const& hash)
: config_(clock, hash)
, cont_(buck_, std::cref(config_.valueHash()), std::cref(config_.keyValueEqual()))
@@ -1868,7 +1868,7 @@ template <
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
AgedUnorderedContainer(
std::initializer_list<value_type> init,
clock_type& clock,
ClockType& clock,
KeyEqual const& keyEq)
: config_(clock, keyEq)
, cont_(buck_, std::cref(config_.valueHash()), std::cref(config_.keyValueEqual()))
@@ -1888,7 +1888,7 @@ template <
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
AgedUnorderedContainer(
std::initializer_list<value_type> init,
clock_type& clock,
ClockType& clock,
Allocator const& alloc)
: config_(clock, alloc)
, buck_(alloc)
@@ -1909,7 +1909,7 @@ template <
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
AgedUnorderedContainer(
std::initializer_list<value_type> init,
clock_type& clock,
ClockType& clock,
Hash const& hash,
KeyEqual const& keyEq)
: config_(clock, hash, keyEq)
@@ -1930,7 +1930,7 @@ template <
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
AgedUnorderedContainer(
std::initializer_list<value_type> init,
clock_type& clock,
ClockType& clock,
Hash const& hash,
Allocator const& alloc)
: config_(clock, hash, alloc)
@@ -1952,7 +1952,7 @@ template <
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
AgedUnorderedContainer(
std::initializer_list<value_type> init,
clock_type& clock,
ClockType& clock,
KeyEqual const& keyEq,
Allocator const& alloc)
: config_(clock, keyEq, alloc)
@@ -1974,7 +1974,7 @@ template <
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
AgedUnorderedContainer(
std::initializer_list<value_type> init,
clock_type& clock,
ClockType& clock,
Hash const& hash,
KeyEqual const& keyEq,
Allocator const& alloc)
@@ -2127,7 +2127,7 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
requires(MaybeMap && !MaybeMulti)
{
maybeRehash(1);
typename cont_type::insert_commit_data d;
typename ContType::insert_commit_data d;
auto const result(cont_.insert_check(
key, std::cref(config_.hashFunction()), std::cref(config_.keyValueEqual()), d));
if (result.second)
@@ -2157,7 +2157,7 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
requires(MaybeMap && !MaybeMulti)
{
maybeRehash(1);
typename cont_type::insert_commit_data d;
typename ContType::insert_commit_data d;
auto const result(cont_.insert_check(
key, std::cref(config_.hashFunction()), std::cref(config_.keyValueEqual()), d));
if (result.second)
@@ -2211,7 +2211,7 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
requires(!MaybeMulti)
{
maybeRehash(1);
typename cont_type::insert_commit_data d;
typename ContType::insert_commit_data d;
auto const result(cont_.insert_check(
extract(value), std::cref(config_.hashFunction()), std::cref(config_.keyValueEqual()), d));
if (result.second)
@@ -2264,7 +2264,7 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
requires(!MaybeMulti && !MaybeMap)
{
maybeRehash(1);
typename cont_type::insert_commit_data d;
typename ContType::insert_commit_data d;
auto const result(cont_.insert_check(
extract(value), std::cref(config_.hashFunction()), std::cref(config_.keyValueEqual()), d));
if (result.second)
@@ -2374,7 +2374,7 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
// VFALCO NOTE Its unfortunate that we need to
// construct element here
Element* const p(newElement(std::forward<Args>(args)...));
typename cont_type::insert_commit_data d;
typename ContType::insert_commit_data d;
auto const result(cont_.insert_check(
extract(p->value),
std::cref(config_.hashFunction()),
@@ -2611,7 +2611,7 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
value_type const& value) -> std::pair<iterator, bool>
requires(!MaybeMulti)
{
typename cont_type::insert_commit_data d;
typename ContType::insert_commit_data d;
auto const result(cont_.insert_check(
extract(value), std::cref(config_.hashFunction()), std::cref(config_.keyValueEqual()), d));
if (result.second)

View File

@@ -26,7 +26,7 @@ namespace beast::insight {
class Collector
{
public:
using ptr = std::shared_ptr<Collector>;
using Ptr = std::shared_ptr<Collector>;
virtual ~Collector() = 0;

View File

@@ -13,7 +13,7 @@ namespace beast::insight {
class Group : public Collector
{
public:
using ptr = std::shared_ptr<Group>;
using Ptr = std::shared_ptr<Group>;
/**
* Returns the name of this group, for diagnostics.

View File

@@ -20,10 +20,10 @@ public:
* Find or create a new collector with a given name.
*/
/** @{ */
virtual Group::ptr const&
virtual Group::Ptr const&
get(std::string const& name) = 0;
Group::ptr const&
Group::Ptr const&
operator[](std::string const& name)
{
return get(name);
@@ -35,6 +35,6 @@ public:
* Create a group container that uses the specified collector.
*/
std::unique_ptr<Groups>
makeGroups(Collector::ptr const& collector);
makeGroups(Collector::Ptr const& collector);
} // namespace beast::insight

View File

@@ -108,12 +108,12 @@ Result
split(FwdIt first, FwdIt last, Char delim)
{
using namespace detail;
using string = Result::value_type;
using String = Result::value_type;
Result result;
FwdIt iter = first;
string e;
String e;
while (iter != last)
{
if (*iter == '"')
@@ -205,10 +205,10 @@ splitCommas(std::string_view s)
*/
class ListIterator
{
using iter_type = boost::string_ref::const_iterator;
using IterType = boost::string_ref::const_iterator;
iter_type it_;
iter_type end_;
IterType it_;
IterType end_;
boost::string_ref value_;
public:
@@ -218,7 +218,7 @@ public:
using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag;
ListIterator(iter_type begin, iter_type end) : it_(begin), end_(end)
ListIterator(IterType begin, IterType end) : it_(begin), end_(end)
{
if (it_ != end_)
increment();

View File

@@ -42,7 +42,7 @@ public:
/**
* The type of yield context passed to functions.
*/
using yield_context = boost::asio::yield_context;
using YieldContext = boost::asio::yield_context;
explicit EnableYieldTo(std::size_t concurrency = 1) : work_(boost::asio::make_work_guard(ios_))
{
@@ -120,7 +120,7 @@ EnableYieldTo::spawn(F0&& f, FN&&... fn)
ios_,
boost::allocator_arg,
boost::context::fixedsize_stack(2 * 1024 * 1024),
[&](yield_context yield) {
[&](YieldContext yield) {
f(yield);
std::scoped_lock const lock{m_};
if (--running_ == 0)

View File

@@ -15,29 +15,29 @@ template <class Container>
class ConstContainer
{
private:
using cont_type = Container;
using ContType = Container;
cont_type cont_;
ContType cont_;
protected:
cont_type&
ContType&
cont()
{
return cont_;
}
[[nodiscard]] cont_type const&
[[nodiscard]] ContType const&
cont() const
{
return cont_;
}
public:
using value_type = cont_type::value_type;
using size_type = cont_type::size_type;
using difference_type = cont_type::difference_type;
using iterator = cont_type::const_iterator;
using const_iterator = cont_type::const_iterator;
using value_type = ContType::value_type;
using size_type = ContType::size_type;
using difference_type = ContType::difference_type;
using iterator = ContType::const_iterator;
using const_iterator = ContType::const_iterator;
/**
* Returns `true` if the container is empty.

View File

@@ -32,7 +32,7 @@ template <class = void>
class Reporter : public Runner
{
private:
using clock_type = std::chrono::steady_clock;
using ClockType = std::chrono::steady_clock;
struct CaseResults
{
@@ -51,7 +51,7 @@ private:
std::size_t cases = 0;
std::size_t total = 0;
std::size_t failed = 0;
clock_type::time_point start = clock_type::now();
ClockType::time_point start = ClockType::now();
explicit SuiteResults(std::string name = "") : name(std::move(name))
{
@@ -63,7 +63,7 @@ private:
struct Results
{
using run_time = std::pair<std::string, clock_type::duration>;
using RunTime = std::pair<std::string, ClockType::duration>;
static constexpr auto kMaxTop = 10;
@@ -71,8 +71,8 @@ private:
std::size_t cases = 0;
std::size_t total = 0;
std::size_t failed = 0;
std::vector<run_time> top;
clock_type::time_point start = clock_type::now();
std::vector<RunTime> top;
ClockType::time_point start = ClockType::now();
void
add(SuiteResults const& r);
@@ -94,7 +94,7 @@ public:
private:
static std::string
fmtdur(clock_type::duration const& d);
fmtdur(ClockType::duration const& d);
void
onSuiteBegin(SuiteInfo const& info) override;
@@ -137,14 +137,13 @@ Reporter<Unused>::Results::add(SuiteResults const& r)
total += r.total;
cases += r.cases;
failed += r.failed;
auto const elapsed = clock_type::now() - r.start;
auto const elapsed = ClockType::now() - r.start;
if (elapsed >= std::chrono::seconds{1})
{
auto const iter = std::lower_bound(
top.begin(),
top.end(),
elapsed,
[](run_time const& t1, clock_type::duration const& t2) { return t1.second > t2; });
top.begin(), top.end(), elapsed, [](RunTime const& t1, ClockType::duration const& t2) {
return t1.second > t2;
});
if (iter != top.end())
{
if (top.size() == kMaxTop)
@@ -174,7 +173,7 @@ Reporter<Unused>::~Reporter()
for (auto const& i : results_.top)
os_ << std::setw(8) << fmtdur(i.second) << " " << i.first << '\n';
}
auto const elapsed = clock_type::now() - results_.start;
auto const elapsed = ClockType::now() - results_.start;
os_ << fmtdur(elapsed) << ", " << Amount{results_.suites, "suite"} << ", "
<< Amount{results_.cases, "case"} << ", " << Amount{results_.total, "test"} << " total, "
<< Amount{results_.failed, "failure"} << std::endl;
@@ -182,7 +181,7 @@ Reporter<Unused>::~Reporter()
template <class Unused>
std::string
Reporter<Unused>::fmtdur(clock_type::duration const& d)
Reporter<Unused>::fmtdur(ClockType::duration const& d)
{
using namespace std::chrono;
auto const ms = duration_cast<milliseconds>(d);
@@ -249,6 +248,10 @@ Reporter<Unused>::onLog(std::string const& s)
} // namespace detail
using reporter = detail::Reporter<>;
using Reporter = detail::Reporter<>;
// TODO [#8340]: Legacy name still used by external consumers of libxrpl (e.g. validator-keys-tool).
// Do not use in new code; remove once those consumers have migrated.
using reporter = Reporter; // NOLINT(readability-identifier-naming)
} // namespace beast::unit_test

View File

@@ -20,7 +20,7 @@ namespace beast::unit_test {
namespace detail {
template <class String>
static std::string
std::string
makeReason(String const& reason, char const* file, int line)
{
std::string s(reason);
@@ -643,12 +643,12 @@ Suite::run(Runner& r)
* Library Identifies the library.
*
* The declaration for the class implementing the test should be the same
* as Class ## _test. For example, if Class is aged_ordered_container, the
* as Class ## _test. For example, if Class is AgedOrderedContainer, the
* test class must be declared as:
*
* @code
*
* struct aged_ordered_container_test : beast::unit_test::suite
* struct AgedOrderedContainer_test : beast::unit_test::suite
* {
* //...
* };

View File

@@ -18,14 +18,14 @@ class Runner;
*/
class SuiteInfo
{
using run_type = std::function<void(Runner&)>;
using RunType = std::function<void(Runner&)>;
std::string name_;
std::string module_;
std::string library_;
bool manual_;
int priority_;
run_type run_;
RunType run_;
public:
SuiteInfo(
@@ -34,7 +34,7 @@ public:
std::string library,
bool manual,
int priority,
run_type run)
RunType run)
: name_(std::move(name))
, module_(std::move(module))
, library_(std::move(library))

View File

@@ -24,7 +24,7 @@ private:
std::thread t_;
public:
using id = std::thread::id;
using Id = std::thread::id;
using native_handle_type = std::thread::native_handle_type;
Thread() = default;

View File

@@ -471,7 +471,7 @@ public:
}
};
using logstream = BasicLogstream<char>;
using logwstream = BasicLogstream<wchar_t>;
using LogStream = BasicLogstream<char>;
using LogWStream = BasicLogstream<wchar_t>;
} // namespace beast

View File

@@ -19,6 +19,6 @@ struct MaybeConst
* Alias for omitting `typename`.
*/
template <bool IsConst, class T>
using maybe_const_t = MaybeConst<IsConst, T>::type;
using MaybeConstT = MaybeConst<IsConst, T>::type;
} // namespace beast

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