Compare commits

..

318 Commits

Author SHA1 Message Date
Mayukha Vadari
7db4d36333 fix build 2026-06-24 17:10:21 -04:00
Mayukha Vadari
6b1438d78f update tests 2026-06-24 16:38:29 -04:00
Mayukha Vadari
3bdc96c0f3 fix SponsorshipTransfer too 2026-06-24 16:28:44 -04:00
Mayukha Vadari
49fc14d703 only keep the tx checks 2026-06-24 16:26:17 -04:00
Mayukha Vadari
6ecf413c64 refactor: Clean up spf flag usage (#7608)
Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com>
2026-06-24 10:25:15 -04:00
Mayukha Vadari
8c98b50de8 refactor: Simplify variable names (#7604) 2026-06-23 20:15:04 -04:00
Mayukha Vadari
2b727cd292 fix: Remove callback in getPageForToken (#7576) 2026-06-23 17:28:50 -04:00
Mayukha Vadari
05bb41056d refactor: rename STTx::getFeePayer to getInitiator (#7603) 2026-06-23 15:48:51 -04:00
yinyiqian1
51264617f3 Merge pull request #7599 from yinyiqian1/merge-develop-sponsor
Merge develop sponsor and apply permissions.macro
2026-06-23 12:42:17 -04:00
Mayukha Vadari
05d3614a19 nit: fix spacing (#7594) 2026-06-23 00:17:32 -04:00
yinyiqian1
494391b4ab replace sponsorshipSet checkPermission with macro 2026-06-22 20:58:57 -04:00
yinyiqian1
fba4ba6ebd Merge remote-tracking branch 'origin/develop' into merge-develop-sponsor 2026-06-22 20:00:11 -04:00
yinyiqian1
018e736a3b Fix sponsor reserve accounting edge cases (#7575) 2026-06-22 15:18:22 -04:00
Mayukha Vadari
4a3abc0407 fix: Assorted AI comments (#7569) 2026-06-22 15:16:14 -04:00
Mayukha Vadari
1eef7473d3 Revert "Sponsorship should be non-obligated for sponsee (#7552)" (#7577) 2026-06-22 14:42:53 -04:00
Mayukha Vadari
c3b3bce35d feat: Update to keylet::sponsorship and sfRemainingOwnerCount (#7578) 2026-06-22 11:07:59 -04:00
Mayukha Vadari
d1a77b453e Merge branch 'develop' of https://github.com/XRPLF/rippled into xrplf/sponsor 2026-06-17 17:50:49 -04:00
Mayukha Vadari
c2ab83c960 fix: Fix UBSan issue (#7554) 2026-06-17 17:50:17 -04:00
yinyiqian1
aac6be218a fix new CI rule switch fallthrough (#7568) 2026-06-17 17:39:12 -04:00
yinyiqian1
14986cc043 Sponsorship should be non-obligated for sponsee (#7552) 2026-06-17 14:08:06 -04:00
Oleksandr
4fc781ef93 Merge remote-tracking branch 'ripp/develop' into xrplf/sponsor 2026-06-15 18:37:38 -04:00
Oleksandr
e52113956e clang-tidy 2026-06-15 18:21:33 -04:00
Oleksandr
f650d52ada Merge remote-tracking branch 'ripple/develop' into xrplf/sponsor 2026-06-15 12:54:37 -04:00
Oleksandr
64159eb040 Revert clang-tidy 2026-06-03 22:40:10 -04:00
Oleksandr
942a950e93 Codegen update 2026-06-03 19:48:20 -04:00
Oleksandr
d70eca3d7d Merge remote-tracking branch 'ripple/develop' into xrplf/sponsor 2026-06-03 19:47:19 -04:00
Oleksandr
7e5ac6f8cb Merge remote-tracking branch 'ripple/develop' into xrplf/sponsor 2026-06-03 19:31:46 -04:00
Oleksandr
03fb6d1e0c Codegen update 2026-06-03 18:29:55 -04:00
Oleksandr
9ef1949309 Merge remote-tracking branch 'ripple/develop' into xrplf/sponsor 2026-05-28 15:19:29 -04:00
Oleksandr
595b612589 Merge fixes 2026-05-28 01:54:20 -04:00
Oleksandr
d561f0d84d Merge remote-tracking branch 'tequ/sponsor' into spns5 2026-05-26 17:06:36 -04:00
Oleksandr
3859fcad73 clang-tidy fixes 2026-05-26 17:06:36 -04:00
Oleksandr
8d905ac21b Merge remote-tracking branch 'ripp/develop' into spns5 2026-05-26 17:06:36 -04:00
Oleksandr
0997b92de3 Merge fixes 2026-05-26 17:04:16 -04:00
Oleksandr
9e5b7281cf Merge remote-tracking branch 'ripple/develop' into spns5 2026-05-26 17:00:29 -04:00
Oleksandr
0bfdfa73ff Merge fixes 2026-05-26 15:50:54 -04:00
Oleksandr
39e819927f Merge remote-tracking branch 'ripple/develop' into spns5 2026-05-26 15:49:42 -04:00
Oleksandr
08357b196f sponsor AccountID -> sponsorSle 2026-05-26 15:42:03 -04:00
tequ
bb4c443fe5 fix ReserveCount Inflation via Co-Signed + Pre-Funded Interaction
fix #6864
2026-05-26 15:39:50 -04:00
tequ
a669099f21 fix 2026-05-26 15:39:50 -04:00
tequ
7624c18c76 fix: XChainAddAccountCreateAttestation redirects relayer sponsorship to door-owned claim objects 2026-05-26 15:39:50 -04:00
tequ
ab7bbac8f9 Merge remote-tracking branch 'oleks-rip/dev_rename_merge' into sponsor 2026-05-26 15:39:49 -04:00
Oleksandr
960aaec91e merge fixes 2026-05-26 15:39:46 -04:00
Oleksandr
f042cd8e25 Merge remote-tracking branch 'ripple/develop' into dev_rename_merge 2026-05-26 15:37:34 -04:00
tequ
9d4c4968ad fix tidy error 2026-05-26 14:47:54 -04:00
Oleksandr
b76652bdf4 XRPL_ASSERT -> Throw 2026-05-26 14:47:54 -04:00
tequ
405b314842 fix clang-tidy error 2026-05-26 14:47:54 -04:00
tequ
77ebc2921e clang-format 2026-05-26 14:47:54 -04:00
tequ
c72fd59539 clang-tidy 2026-05-26 14:47:54 -04:00
tequ
6f4365557d Merge branch 'develop' into sponsor 2026-05-26 14:47:54 -04:00
Oleksandr
d792e03468 adjustOwnerCountObj, more checks, some fixes 2026-05-26 14:47:53 -04:00
Oleksandr
2b4ce0fc21 Merge fixes 2026-05-26 14:47:53 -04:00
Oleksandr
eb88c0ef6b Fix clang-format, some refactoring 2026-05-26 14:46:41 -04:00
tequ
50d5e2d996 Merge remote-tracking branch 'upstream/develop' into sponsor 2026-05-26 14:46:41 -04:00
tequ
bca6d8e515 fix not to payback ReserveCount 2026-05-26 14:46:41 -04:00
tequ
86c90c8e5c clang-tidy 2026-05-26 14:46:41 -04:00
tequ
0c683bfd66 levelization 2026-05-26 14:46:41 -04:00
tequ
33be9abbef clang-format 2026-05-26 14:46:41 -04:00
tequ
aa70d6051b Merge remote-tracking branch 'upstream/develop' into sponsor 2026-05-26 14:46:41 -04:00
tequ
d057f07d0e fix: setSponsorFieldU32 silently clamps to 0 on underflow instead of failing 2026-05-26 14:40:07 -04:00
tequ
688e568e39 fix: getLedgerEntryOwner missing ltLOAN_BROKER and ltLOAN prevents object sponsorship 2026-05-26 14:40:07 -04:00
tequ
3ad93af34d fix: Sponsor's MaxFee cap is bypassed in reset() path, allowing sponsee to drain entire pre-funded FeeAmount in a single tec-failing transaction 2026-05-26 14:40:07 -04:00
Oleksandr
c5941d6b14 Unify accountReserve, ownerCount, ownerReserve 2026-05-26 14:40:07 -04:00
Oleksandr
ee8d9ca73e More universal adjustSponsorOwnerCountHlp 2026-05-26 14:40:07 -04:00
Oleksandr
462a0b2338 Read/const_ref 2026-05-26 14:40:06 -04:00
Oleksandr
9b4ab67864 Fix delegable test 2026-05-26 14:40:06 -04:00
Oleksandr
84bffad2bf merge_fix 2026-05-26 14:40:06 -04:00
tequ
b153213e83 run pre-commit 2026-04-28 17:20:00 +09:00
tequ
c12eff6646 apply tidy diff 2026-04-28 17:09:57 +09:00
tequ
fbff1c065c levelization 2026-04-28 17:04:14 +09:00
tequ
e8deaa12d8 pre-commit run 2026-04-28 16:55:07 +09:00
tequ
6ee071c5b0 fix: An incorrect available XRP balance check in AMM deposit allows reserve-locked funds to be used as adding liquidity 2026-04-28 15:57:49 +09:00
tequ
381094498d Merge remote-tracking branch 'upstream/develop' into sponsor 2026-04-28 09:49:52 +09:00
tequ
c072b125a0 fix: No invariant verifying sfSponsor field on objects matches sponsoring/sponsored count deltas #6897 2026-04-21 18:59:36 +09:00
tequ
b2b2babe1e fix: PermissionedDomain invariant skips credential validation for SponsorshipTransfer #6902 2026-04-21 18:28:09 +09:00
tequ
bb27479686 fix: TrustSet free trust line check uses sponsor's ownerCount, skipping sponsor reserve validation #6901 2026-04-21 17:51:50 +09:00
tequ
278e25d8ad fix: Preclaim XRP reserve overestimate for sponsored checks #6899 2026-04-21 17:25:33 +09:00
tequ
773acf0af7 fix: SponsoringAccountCount has no overflow protection #6898 2026-04-21 17:20:22 +09:00
tequ
7639bd9061 fix: MPTokenIssuanceDestroy reads sponsor from erased SLE #6895 2026-04-21 16:27:33 +09:00
tequ
207a33d3da fix: SponsorshipSet Update FeeAmount Lacks Reserve Floor Check 2026-04-21 15:56:28 +09:00
tequ
52e7cdc24d fix: Sponsored account creation double-counts base reserve #6894 2026-04-21 13:48:07 +09:00
tequ
dd82977e6c Merge remote-tracking branch 'upstream/develop' into sponsor 2026-04-13 18:08:30 +09:00
tequ
31bc25973a fix SponsorshipSet Update FeeAmount Lacks Reserve Floor Check 2026-04-13 15:56:29 +09:00
tequ
021eaa81bf fix Co-Signed Sponsoring Bypasses Sponsor Balance Check 2026-04-13 15:30:33 +09:00
tequ
84e84fbadf fix Sponsor able to provide sponsorship with just base reserve 2026-04-13 14:03:37 +09:00
tequ
b6b317597f add test for insufficient balance to sponsor fee 2026-04-10 21:43:35 +09:00
tequ
525adf122f fix reset() Does Not makeFieldAbsent for Zero FeeAmount 2026-04-10 18:28:28 +09:00
tequ
16e4f24226 fix XRPL_ASSERT(false) to UNREACHABLE 2026-04-10 17:59:25 +09:00
tequ
3df1e668da fix Unchecked std::optional Dereference in SponsorshipSet Create Path 2026-04-10 17:55:40 +09:00
tequ
9264136b36 fix deleteAMMTrustLine Reads Sponsor Fields After They Are Erased 2026-04-10 17:41:33 +09:00
tequ
6bd2e911eb fix Wrong Account in Sponsorship Keylet Lookup Causes Reserve Count
Leakage
2026-04-10 17:07:36 +09:00
tequ
828b4753fe fix Wrong Account Passed to getLedgerEntryOwner in doApply 2026-04-10 15:57:15 +09:00
tequ
d524670bcd fix SponsorshipEnd Bypass 2026-04-10 15:54:16 +09:00
tequ
25de0ce1b1 fix comment 2026-04-10 14:21:05 +09:00
tequ
4026af175b format 2026-04-10 14:13:55 +09:00
tequ
a115d73c56 return tecHAS_OBLIGATIONS for any conditions when deleting account linked to ltSponsorship 2026-04-10 14:13:25 +09:00
tequ
71003699dc Add test for no SponsorFlag with valid sponsor 2026-04-10 13:45:14 +09:00
tequ
831f99862d clang-tidy 2026-04-10 05:51:22 +09:00
tequ
4d2945323d fix AccountObjects_test.cpp error 2026-04-10 04:21:11 +09:00
tequ
700a528a25 Merge remote-tracking branch 'upstream/develop' into sponsor 2026-04-10 03:38:07 +09:00
tequ
07d0887efb fix path 2026-04-09 00:46:20 +09:00
tequ
3ea0067e6a clang-format 2026-04-08 12:03:12 +09:00
tequ
5a195d2585 fix path 2026-04-08 11:55:35 +09:00
tequ
3f4e88c300 Merge remote-tracking branch 'xrplf/develop' into sponsor 2026-04-08 11:47:16 +09:00
tequ
7c3ca98bd5 Merge remote-tracking branch 'upstream/develop' into sponsor 2026-03-31 14:22:49 +09:00
tequ
2505fa86f7 fix 2026-03-30 17:52:36 +09:00
tequ
d0d4f1d153 Merge remote-tracking branch 'upstream/develop' into sponsor 2026-03-30 17:25:14 +09:00
tequ
41429dcc99 Merge remote-tracking branch 'upstream/develop' into sponsor 2026-03-25 11:59:44 +09:00
tequ
aacb8e4a68 return tem error when SponsorReserve flag is set in Batch OuterTxn 2026-03-23 13:31:36 +09:00
tequ
98257d3b96 Fix SponsorshipSet targeting Pseudo Accounts to return an error 2026-03-23 13:07:28 +09:00
tequ
afcc3c6464 Merge remote-tracking branch 'upstream/develop' into sponsor 2026-03-23 12:46:27 +09:00
tequ
fd393685dd fix L20 2026-03-23 12:46:17 +09:00
tequ
de64bc7855 fix L18 2026-03-23 12:34:33 +09:00
tequ
1adaeac8a7 fix L14 2026-03-23 12:14:44 +09:00
tequ
7ddda1b1e6 fix L5 2026-03-23 12:01:30 +09:00
tequ
5280a185d0 fix L4 2026-03-23 11:59:46 +09:00
tequ
64f699a974 fix M17 2026-03-23 11:14:41 +09:00
tequ
968493f43b fix M16 2026-03-23 11:10:45 +09:00
tequ
22bfc5e743 fix M15 2026-03-23 11:02:59 +09:00
tequ
2f0adfae3b fix M11 2026-03-23 10:55:42 +09:00
tequ
53bdfb2bc7 Add comment to clarify that the door account should not have a sponsor in the reserve check 2026-03-23 10:28:27 +09:00
tequ
b695b4bf9b Add comments for PreFunded sponsor reserve checks on TrustSet 2026-03-23 10:27:18 +09:00
tequ
6d7ffcbb91 fix M7 2026-03-19 15:39:55 +09:00
tequ
d1346fa3f6 fix M6 2026-03-19 15:14:14 +09:00
tequ
d6803868a1 fix M5 2026-03-19 15:00:09 +09:00
tequ
9a6432dd66 fix M3 2026-03-19 14:50:09 +09:00
tequ
f8a8c2301c fix M2 2026-03-19 14:33:55 +09:00
tequ
e40e15a866 fix C2, C4 2026-03-19 14:01:11 +09:00
tequ
6555001cd9 make sponsor helpers inline 2026-03-19 11:50:55 +09:00
tequ
f13945eff9 Merge remote-tracking branch 'upstream/develop' into sponsor 2026-03-19 11:10:44 +09:00
tequ
b32ff18c21 refactor getFeePayer() 2026-03-18 00:19:21 +09:00
tequ
8baec5634c pre-commit run --all-files 2026-03-18 00:03:31 +09:00
tequ
37c95ead69 Merge remote-tracking branch 'upstream/develop' into sponsor 2026-03-18 00:02:57 +09:00
tequ
234d2e5414 Refactor ownerCount and calculateReserve to use SLE::const_ref 2026-03-17 21:38:25 +09:00
tequ
024ab07eb4 minor fixes 2026-03-17 21:35:08 +09:00
tequ
d95b6e41e5 Refactor variable declarations in xrpLiquid 2026-03-17 21:15:41 +09:00
tequ
8d75f3bdc6 remove asfDisallowIncomingSponsor 2026-03-17 21:13:35 +09:00
tequ
eb7e01de7e Remove unused tx parameter from removeEmptyHolding() 2026-03-17 21:04:40 +09:00
tequ
c79814a037 remove unused Sponsor.h 2026-03-17 20:39:57 +09:00
tequ
15be71469d remove unnecessary reserveCount check 2026-03-17 20:35:50 +09:00
tequ
c9666d7b45 refactor adjustOwnerCount() to use adjustSponsorOwnerCountHlp() 2026-03-17 20:28:01 +09:00
tequ
839ba17dae Refactor: sponsorship-related helpers 2026-03-17 20:11:49 +09:00
tequ
85e1f2b16c Rename [sponsor|sponsee]Acc,[sponsor|sponsee]Account to [sponsor|sponsee]AccountID for clarity 2026-03-17 18:32:30 +09:00
tequ
8a05e3d93b remove unnecessary #endif in Sponsor.h and sponsor.h 2026-03-17 18:14:48 +09:00
tequ
8c8ecffe1f remove tx parameter from adjustOwnerCount() 2026-03-17 18:14:24 +09:00
tequ
b9f1c97518 format SetTrust.cpp 2026-03-17 17:43:35 +09:00
tequ
d1eb22b403 fix transactions.macro format 2026-03-17 17:38:04 +09:00
tequ
fb86735800 use pragma once 2026-03-17 17:26:13 +09:00
tequ
53f407e1bd Merge remote-tracking branch 'upstream/develop' into sponsor 2026-03-17 17:22:54 +09:00
tequ
99618877e4 clang-format 2026-02-23 23:55:25 +09:00
tequ
062ece321b Merge remote-tracking branch 'upstream/develop' into sponsor 2026-02-23 23:20:21 +09:00
tequ
1ad6dd1846 Add tests for deleting Sponsor Account with ltSponsorship 2026-02-23 11:10:46 +09:00
tequ
4a91351bcd Add sfSponsee to ttSponsorshipTransfer 2026-02-22 17:21:04 +09:00
tequ
f86b255e73 Add SponsorshipEnd/Create/Reassign flags for SponsorshipTransfer 2026-02-22 02:41:01 +09:00
tequ
178bb8f7e9 Allow zero value for ReserveCount, FeeAmount, MaxFee 2026-02-22 00:01:56 +09:00
tequ
293394fbc6 audit 14 2026-02-18 17:22:23 +09:00
tequ
dcfcb1f3fd audit 13 2026-02-18 16:33:32 +09:00
tequ
2fd8e1be3c audit 12 2026-02-18 15:55:10 +09:00
tequ
fe5fab00ed audit 11 2026-02-18 15:18:17 +09:00
tequ
9cde57d284 audit 10 2026-02-18 15:09:12 +09:00
tequ
9859ba85a8 audit 9 2026-02-18 15:01:35 +09:00
tequ
f6d79f74d6 audit 8 2026-02-18 14:53:21 +09:00
tequ
bf4fa37937 audit 7 2026-02-18 14:48:51 +09:00
tequ
686f945909 audit 6 2026-02-18 14:46:03 +09:00
tequ
c1e1be510f audit 5 2026-02-18 14:39:27 +09:00
tequ
d1d613da27 audit 4 2026-02-18 14:19:40 +09:00
tequ
392a913631 audit 3 2026-02-18 14:09:11 +09:00
tequ
446681dc3d Merge remote-tracking branch 'upstream/develop' into sponsor 2026-02-18 13:39:57 +09:00
tequ
e1aee43359 address review 2026-02-03 14:45:55 +09:00
tequ
fe075470f8 address review 2026-02-02 18:57:04 +09:00
tequ
49c52695cb sfSponsorAccount -> sfSponsor/sfCounterpartySponsor 2026-02-02 12:51:35 +09:00
tequ
37f4ea94cb Add tests for Loan 2026-02-02 12:30:06 +09:00
tequ
f8209087a3 Add tests for LoanBroker transactions 2026-02-01 20:38:37 +09:00
tequ
d390bc7a87 clang-format 2026-01-31 01:33:36 +09:00
tequ
4e87de7303 add test for Sponsored trustline 2026-01-31 01:31:37 +09:00
tequ
8d24afe59d Merge remote-tracking branch 'upstream/develop' into sponsor 2026-01-30 23:29:56 +09:00
tequ
527d7bbede fix to return error if FeeAmount > Balance on SponsorshipSet 2026-01-30 23:24:50 +09:00
tequ
4a205eb9d8 add checks to accountReserve and fix sponsored owner count for xrpLiquid 2026-01-30 22:23:45 +09:00
tequ
0a410024a5 refactor SponsorshipSet flag checks 2026-01-30 22:22:09 +09:00
tequ
8f8fc03800 Add InvariantChecks for if OwnerCount < SponsoredOwnerCount 2026-01-30 21:21:38 +09:00
tequ
40cf5993c1 Add sanity check for sponsoringAccountCount = 0 2026-01-30 20:36:43 +09:00
tequ
7cdaa24e63 Fixed the minimum amount for creating a Sponsored Account. 2026-01-30 20:27:46 +09:00
tequ
175a2dfd28 chang sfFeeAmount to soeOPTIONAL 2026-01-30 20:03:24 +09:00
tequ
4cd8d0d178 fix simulate test 2026-01-30 19:51:07 +09:00
tequ
5155a94015 Add sponsor tests for Batch innerTxn 2026-01-30 17:20:15 +09:00
tequ
c0de722cfa sfHigh/LowSponsorAccount -> High/LowSponsor 2026-01-30 12:32:48 +09:00
tequ
d7ab1b48e1 Separate test suite 2026-01-30 11:43:45 +09:00
tequ
65768237cd Payback ReserveCount 2026-01-30 11:36:56 +09:00
tequ
5f385e0f9b update to use sfSponsorFlags 2026-01-30 10:36:48 +09:00
tequ
ab1de456cc add comment 2026-01-29 13:52:19 +09:00
tequ
8be44c7fc4 Merge remote-tracking branch 'upstream/develop' into sponsor 2026-01-29 11:22:42 +09:00
tequ
87718bdb3b remove unused HashPrefix 2026-01-29 10:58:06 +09:00
tequ
88e870b1c6 change sfSponsor to STAccount, Sponsor flags as global flags 2026-01-27 12:38:01 +09:00
tequ
ce8049a17f fix parseSponsorship 2026-01-27 11:34:08 +09:00
tequ
990627fc9e Merge remote-tracking branch 'upstream/develop' into sponsor 2026-01-27 10:38:24 +09:00
tequ
1823d70b21 refactor Oracle Reserve calculation 2026-01-27 10:34:15 +09:00
tequ
f333dd1b2e add signature existence check, consume ReserveCount if pre-funded sponsoring 2026-01-27 10:33:52 +09:00
tequ
204138fb0e Revert the use of calculateReserve in xrpLiquid 2026-01-15 18:48:35 +09:00
tequ
52ae31bb17 Merge commit 'c9458b72cab68d3cbbf533cc87d14309c2eb93b7' into sponsor 2026-01-15 16:34:24 +09:00
tequ
c3e5bcfafd address review (DeleteAccount) 2026-01-15 15:53:29 +09:00
tequ
3568df43c4 add calculateReserve helper 2026-01-15 15:01:55 +09:00
tequ
c321e1070d address reviews 2026-01-15 14:51:05 +09:00
tequ
9e65dba253 fix redundant co-signed sponsor check 2026-01-15 14:32:47 +09:00
tequ
5b91d815d1 address revew (std::optional + std::shared_ptr<SLE>) 2026-01-15 14:29:37 +09:00
tequ
f885f02ede address spec changes (sfReserveCount, sfFeeAmount) 2026-01-14 19:28:10 +09:00
tequ
1bc5a1bb43 address spec changes (payment flags/ iou amount) 2026-01-14 12:49:49 +09:00
tequ
ec05613472 fix typo 2026-01-09 16:45:12 +09:00
tequ
f88e964dac allow sponsee on cspell 2026-01-09 16:40:15 +09:00
tequ
ffb538242a Merge remote-tracking branch 'upstream/develop' into sponsor 2026-01-09 16:38:44 +09:00
tequ
1e8f6ce1b5 address reviews 2026-01-09 16:31:22 +09:00
tequ
82b146bf03 fix ripple -> xrpl 2026-01-07 17:16:50 +09:00
tequ
0791ca164a fix template exception 2026-01-07 16:42:18 +09:00
tequ
dc325a93e7 Merge branch 'develop' into sponsor 2026-01-07 12:35:47 +09:00
tequ
edddf3fe4b address review 2026-01-07 12:34:51 +09:00
tequ
cf03c4cb8f change Sponsor related fields to soeDEFAULT 2026-01-07 12:31:01 +09:00
tequ
2813fea294 address review 2026-01-07 11:39:56 +09:00
tequ
163a2acbf5 add sfPreviousTxnID and sfPreviousTxnLgrSeq to ltSponsorship 2026-01-07 11:27:10 +09:00
tequ
198f3f83db remove unused insSponsorCoSigning args 2026-01-07 11:14:01 +09:00
tequ
0f36de8ef5 Merge remote-tracking branch 'upstream/develop' into sponsor 2026-01-07 10:58:21 +09:00
tequ
ea29fe5ede Merge remote-tracking branch 'upstream/develop' into sponsor 2025-12-11 10:31:48 +09:00
tequ
f5e2195bbb address reviews 2025-12-11 10:31:30 +09:00
tequ
e49d338cd8 address SponsorshipSet reviews 2025-11-26 17:48:35 +09:00
tequ
d96998ce47 Merge remote-tracking branch 'upstream/develop' into sponsor 2025-11-26 17:20:19 +09:00
tequ
a9629ae325 address reviews 2025-11-21 17:44:05 +09:00
tequ
7f0a940a43 Merge remote-tracking branch 'upstream/develop' into sponsor 2025-11-21 17:18:20 +09:00
tequ
c38cb902ad Merge remote-tracking branch 'upstream/develop' into sponsor 2025-11-21 17:17:48 +09:00
tequ
b5db59644a update Sponsored VaultCreate test 2025-11-17 18:29:22 +09:00
tequ
9d1b5eb373 Merge remote-tracking branch 'upstream/develop' into sponsor 2025-11-17 18:19:30 +09:00
tequ
af9d91bc72 add tests fro SponsorshipTransfer 2025-11-10 22:22:32 +09:00
tequ
3f9673510a fix comment for LCOV 2025-11-10 21:50:31 +09:00
tequ
a49cb91c73 add tests 2025-11-10 12:11:42 +09:00
tequ
fbf403aaa4 add tests for sponsor field 2025-11-10 00:55:39 +09:00
tequ
e03c7a9c96 add sponsor transfer test 2025-11-10 00:40:15 +09:00
tequ
cd62f7f4cf remove copyright 2025-11-06 21:08:51 +09:00
tequ
297083e27b fix: specify type for adjust variable in SetOracle transaction processing 2025-11-06 18:36:17 +09:00
tequ
13145f6db2 fix header name 2025-11-06 18:34:24 +09:00
tequ
3e6d6c6f80 Merge remote-tracking branch 'upstream/develop' into sponsor 2025-11-06 18:08:13 +09:00
tequ
b4188a887a address reviews 2025-11-06 17:53:07 +09:00
tequ
774917db22 Merge remote-tracking branch 'upstream/develop' into sponsor 2025-10-31 11:24:47 +09:00
tequ
965ecd3f27 Add sponsored outer batch 2025-10-28 21:07:20 +09:00
tequ
d0bcca6bf1 Fix the behavior of co-sign + pre-fund 2025-10-28 17:18:38 +09:00
tequ
4fe7e87b4f Merge remote-tracking branch 'upstream/develop' into sponsor 2025-10-17 19:21:24 +09:00
tequ
2337d340e5 Allow delegation for Sponsorship transactions 2025-10-17 18:56:46 +09:00
tequ
5d597e3b69 Merge remote-tracking branch 'upstream/develop' into sponsor 2025-10-16 22:08:42 +09:00
tequ
d8dc000488 add prefunded sponsor tests 2025-10-09 19:12:14 +09:00
tequ
a65cf6e07d add tests for sponsor flags 2025-10-08 14:09:02 +09:00
tequ
7f922c4919 reserve co-signing 2025-10-08 02:50:08 +09:00
tequ
754f597078 Support sfSponsorSignature autofilling in Simulate RPC 2025-10-07 16:02:02 +09:00
tequ
32cc7825f2 Merge branch 'refactor-simulate-autofill' into sponsor 2025-10-07 15:30:48 +09:00
tequ
a6b0efff87 typo 2025-10-07 11:19:31 +09:00
tequ
28c5cadbea fix transactions.macro format 2025-10-07 10:45:30 +09:00
tequ
9df0ad64d1 Merge branch 'sponsor-new-signing' into sponsor 2025-10-07 09:24:58 +09:00
tequ
1441abcf01 use sfSponsorSignature 2025-10-07 09:01:45 +09:00
Ed Hennis
8d32b0f856 Add jtx, STObject, and RPC support for sig object fields 2025-10-07 08:41:43 +09:00
tequ
d59772657e refactor: signature autofilling for Simulate RPC 2025-10-04 14:37:06 +09:00
Ed Hennis
bc71d9c138 Add support for extra transaction signature validation
- Restructures `STTx` signature checking code to be able to handle
  a `sigObject`, which may be the full transaction, or may be an object
  field containing a separate signature. Either way, the `sigObject` can
  be a single- or multi-sign signature.
- This is distinct from 550f90a75e (#5594), which changed the check in
  Transactor, which validates whether a given account is allowed to sign
  for the given transaction. This cryptographically checks the signature
  validity.
2025-10-04 13:22:56 +09:00
tequ
101b70f0e8 add assert when adding/removing sponsor field to LedgerEntry 2025-10-03 15:07:46 +09:00
tequ
ee385e9d3b fix bad merge 2025-10-03 15:04:33 +09:00
tequ
4126d53978 Merge remote-tracking branch 'origin/develop' into sponsor 2025-10-03 09:39:47 +09:00
tequ
59c3d5bddc add insufficient reserve check for xchain, vault 2025-10-02 23:37:44 +09:00
tequ
bc1ef1e839 add tests for XChainBridge 2025-10-02 18:29:12 +09:00
tequ
5b64ff0dd6 address 5594, 5592 changes 2025-09-30 18:30:38 +09:00
tequ
1ee250881b Merge remote-tracking branch 'upstream/develop' into sponsor 2025-09-30 12:06:09 +09:00
tequ
75aaeb5aae Merge remote-tracking branch 'upstream/develop' into sponsor 2025-09-26 18:26:40 +09:00
tequ
b09666210d add InvariantChecks for pseudo-account 2025-09-26 18:25:49 +09:00
tequ
dbbfc1354c test for Vault 2025-09-26 18:21:24 +09:00
tequ
e82c300de7 test Sponsor Reserve checks for AMM 2025-09-26 10:15:00 +09:00
tequ
d5a1314c47 test Sponsor Reserve checks for TrustSet 2025-09-24 19:05:22 +09:00
tequ
699297f01a test Sponsor Reserve checks for SignerListSet 2025-09-24 18:59:16 +09:00
tequ
71b81b743e test Sponsor Reserve checks for PayChan, PermissionedDomain, Oracle 2025-09-24 17:35:23 +09:00
tequ
ec11763def test Sponsor Reserve checks for NFToken 2025-09-24 17:12:02 +09:00
tequ
cc4b07dbd6 test Sponsor Reserve checks for DID, Escrow 2025-09-24 16:18:09 +09:00
tequ
b78885d98c test Sponsor Reserve checks for DepositPreauth 2025-09-24 15:59:06 +09:00
tequ
0c93bd6f08 test Sponsor Reserve checks for DelegateSet 2025-09-24 15:57:49 +09:00
tequ
9694de92da test Sponsor Reserve checks for Credentials 2025-09-24 15:54:48 +09:00
tequ
c4b798e8ed test Sponsor Reserve checks for TicketCreate 2025-09-24 15:41:58 +09:00
tequ
350130911a test Sponsor Reserve checks for OfferCreate 2025-09-24 15:34:55 +09:00
tequ
ab4ac64c92 test Sponsor Reserve checks for Checks 2025-09-24 15:05:31 +09:00
tequ
aeaf679deb Merge remote-tracking branch 'upstream/develop' into sponsor 2025-09-24 13:42:57 +09:00
tequ
ea72198a1d Transfer Trustline Sponsorship 2025-09-24 13:42:05 +09:00
tequ
6eb453f07d Merge branch 'develop' into sponsor 2025-09-20 23:08:53 +09:00
tequ
d4947386d7 Fully Support NFTokenMint/Burn 2025-09-20 17:03:20 +09:00
tequ
fed56b2eeb address SponsorAccount/Sponsee field changes 2025-09-20 14:29:33 +09:00
tequ
f7e1d4bbb9 add AccountTx tests for Sponsorship 2025-09-20 12:20:29 +09:00
tequ
613fe48d54 update account_objects for sponsorship 2025-09-20 11:44:47 +09:00
tequ
5dc63b64eb fix SponsorshipTransfer 2025-09-20 10:34:46 +09:00
tequ
cc5e063438 add Credential sponsor test 2025-09-19 21:25:46 +09:00
tequ
453fd23512 add Sponsor Oracle 2025-09-19 21:12:34 +09:00
tequ
89af81745b add tests 2025-09-19 01:36:45 +09:00
tequ
a43ae9a3ce add InvariantCheck for sponsor count 2025-09-18 18:49:53 +09:00
tequ
2afe5707ab High/Low SponsorAccount 2025-09-18 16:32:50 +09:00
tequ
759f843020 Sponsor permissions 2025-09-16 23:11:19 +09:00
tequ
5ac7bbf51b test SponsorshipRequire flags 2025-09-15 22:48:40 +09:00
tequ
2a27280f1a fix test error 2025-09-15 22:07:43 +09:00
tequ
6c0732ccbe test checks 2025-09-15 20:29:58 +09:00
tequ
20bce64946 test AccountDelete for sponsorship 2025-09-15 19:09:57 +09:00
tequ
110b222579 add MaxFee test 2025-09-15 18:52:42 +09:00
tequ
1cdf7bb745 feePayer 2025-09-15 16:25:16 +09:00
tequ
4abd94e7ac MaxFee 2025-09-15 11:04:47 +09:00
tequ
6aa0331ffe sfAccount to sfOwner 2025-09-13 22:40:19 +09:00
tequ
4eea76ca92 Create Sponsored Account / AccountDelete with ltSponsorship, Sponsored Account 2025-09-13 22:34:54 +09:00
tequ
8e895a3e7d fullly rename 2025-09-13 09:49:30 +09:00
tequ
e589b71ee0 v2. SponsorSet 2025-09-13 09:36:38 +09:00
tequ
02d8f9fbef Sponsor signing 2025-09-08 00:20:14 +09:00
tequ
9ff71aa109 Merge remote-tracking branch 'upstream/develop' into sponsor 2025-09-06 23:11:10 +09:00
tequ
2071b39d6a use helper 2025-08-01 18:33:19 +09:00
tequ
5e65813a52 add reserve checks for SponsorTransfer 2025-08-01 18:21:44 +09:00
tequ
abd8620c97 Add SponsorTransfer 2025-08-01 13:23:41 +09:00
tequ
6e01f233e4 fix fees().accountReserve(0) to fees().reserve 2025-08-01 01:59:08 +09:00
tequ
0bddc95444 clang-format 2025-08-01 01:19:37 +09:00
tequ
67bdd099c8 check reserve 2025-08-01 00:44:11 +09:00
tequ
f0addd81a1 fix addEmptyHolding 2025-07-31 17:43:54 +09:00
tequ
a798c60a08 test Disabled 2025-07-31 00:12:23 +09:00
tequ
198ed72fe3 fix OwnerCount 2025-07-31 00:12:09 +09:00
tequ
d40f8cc232 SponsorReserve,SponsorAccount
- not fully tested
- need to modify: Reserve check where using sfOwnerCount
2025-07-30 23:39:14 +09:00
tequ
5b9c767b07 Merge remote-tracking branch 'upstream/develop' into sponsor 2025-07-29 22:58:03 +09:00
Mayukha Vadari
43c16f35f7 PoC for sponsored reserve 2025-06-17 11:35:23 +09:00
Mayukha Vadari
cad305ac7e PoC for sponsored fees 2025-06-17 11:32:13 +09:00
294 changed files with 10946 additions and 1752 deletions

View File

@@ -11,7 +11,6 @@ Checks: "-*,
bugprone-copy-constructor-init,
bugprone-crtp-constructor-accessibility,
bugprone-dangling-handle,
bugprone-derived-method-shadowing-base-method,
bugprone-dynamic-static-initializers,
bugprone-empty-catch,
bugprone-fold-init-type,
@@ -22,7 +21,6 @@ Checks: "-*,
bugprone-incorrect-roundings,
bugprone-infinite-loop,
bugprone-integer-division,
bugprone-invalid-enum-default-initialization,
bugprone-lambda-function-name,
bugprone-macro-parentheses,
bugprone-macro-repeated-side-effects,
@@ -139,7 +137,6 @@ Checks: "-*,
readability-enum-initial-value,
readability-identifier-naming,
readability-implicit-bool-conversion,
readability-inconsistent-ifelse-braces,
readability-make-member-function-const,
readability-math-missing-parentheses,
readability-misleading-indentation,
@@ -148,9 +145,7 @@ Checks: "-*,
readability-redundant-declaration,
readability-redundant-inline-specifier,
readability-redundant-member-init,
readability-redundant-parentheses,
readability-redundant-string-init,
readability-redundant-typename,
readability-reference-to-constructed-temporary,
readability-simplify-boolean-expr,
readability-static-definition-in-anonymous-namespace,
@@ -158,8 +153,7 @@ Checks: "-*,
readability-use-std-min-max
"
# ---
# bugprone-narrowing-conversions, # This will break a lot of code but we should enable it in the future because it can eliminate a lot of bugs
# misc-override-with-different-visibility, # Will be addressed in a future PR, but for now it generates too many warnings
# bugprone-narrowing-conversions, # this will break a lot of code but we should enable it in the future because it can eliminate a lot of bugs
# readability-inconsistent-declaration-parameter-name, # In this codebase this check will break a lot of arg names
# readability-static-accessed-through-instance, # this check is probably unnecessary. It makes the code less readable
# ---

View File

@@ -96,6 +96,3 @@ function(verbose_find_path variable name)
${ARGN}
)
endfunction()
function(patch_nix_binary target)
endfunction()

View File

@@ -83,6 +83,7 @@ test.conditions > xrpl.basics
test.conditions > xrpl.conditions
test.consensus > test.csf
test.consensus > test.jtx
test.consensus > test.toplevel
test.consensus > test.unit_test
test.consensus > xrpl.basics
test.consensus > xrpld.app

View File

@@ -1,5 +1,5 @@
{
"image_tag": "sha-e29b523",
"image_tag": "sha-fe4c8ae",
"configs": {
"ubuntu": [
{

View File

@@ -1,6 +1,6 @@
{
"platform": "windows/amd64",
"runner": ["self-hosted", "Windows", "dev-box-windows-2026"],
"runner": ["self-hosted", "Windows", "devbox"],
"configs": [
{ "build_type": "Release" },
{

View File

@@ -70,7 +70,6 @@ jobs:
.github/workflows/reusable-upload-recipe.yml
.clang-tidy
.codecov.yml
bin/check-tools.sh
cfg/**
cmake/**
conan/**

View File

@@ -27,7 +27,6 @@ on:
- ".github/workflows/reusable-upload-recipe.yml"
- ".clang-tidy"
- ".codecov.yml"
- "bin/check-tools.sh"
- "cfg/**"
- "cmake/**"
- "conan/**"

View File

@@ -41,7 +41,7 @@ env:
jobs:
build:
runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-e29b523
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-fe4c8ae
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

View File

@@ -82,7 +82,7 @@ jobs:
name: ${{ inputs.config_name }}
runs-on: ${{ fromJSON(inputs.runs_on) }}
container: ${{ inputs.image != '' && inputs.image || null }}
timeout-minutes: ${{ inputs.sanitizers != '' && 360 || 180 }}
timeout-minutes: ${{ inputs.sanitizers != '' && 360 || 90 }}
env:
# Use a namespace to keep the objects separate for each configuration.
CCACHE_NAMESPACE: ${{ inputs.config_name }}
@@ -163,7 +163,7 @@ jobs:
CMAKE_ARGS: ${{ inputs.cmake_args }}
run: |
cmake \
-G '${{ runner.os == 'Windows' && 'Visual Studio 18 2026' || 'Ninja' }}' \
-G '${{ runner.os == 'Windows' && 'Visual Studio 17 2022' || 'Ninja' }}' \
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
${CMAKE_ARGS} \
@@ -229,6 +229,21 @@ jobs:
--parallel "${BUILD_NPROC}" \
--target "${CMAKE_TARGET}"
# This step is needed to allow running in non-Nix environments
- name: Patch binary to use default loader and remove rpath (Linux)
if: ${{ runner.os == 'Linux' && env.SANITIZERS_ENABLED == 'false' }}
run: |
loader="$(/tmp/loader-path.sh)"
patchelf --set-interpreter "${loader}" --remove-rpath "${{ env.BUILD_DIR }}/xrpld"
# We're only running aarch64 Linux builds in Ubuntu-based images, so this is kept simple
- name: Install libatomic (Linux aarch64)
if: ${{ runner.os == 'Linux' && runner.arch == 'ARM64' }}
run: |
apt update --yes
apt install -y --no-install-recommends \
libatomic1
- name: Show ccache statistics
if: ${{ inputs.ccache_enabled }}
run: |

View File

@@ -39,7 +39,7 @@ jobs:
needs: [determine-files]
if: ${{ always() && !cancelled() && (!inputs.check_only_changed || needs.determine-files.outputs.cpp_changed_files != '' || needs.determine-files.outputs.clang_tidy_config_changed == 'true') }}
runs-on: ["self-hosted", "Linux", "X64", "heavy"]
container: "ghcr.io/xrplf/xrpld/nix-debian:sha-e29b523"
container: "ghcr.io/xrplf/xrpld/nix-debian:sha-fe4c8ae"
permissions:
contents: read
issues: write

View File

@@ -39,8 +39,23 @@ jobs:
working-directory: .github/scripts/strategy-matrix
run: ./generate.py --packaging >>"${GITHUB_OUTPUT}"
generate-version:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
sparse-checkout: |
.github/actions/generate-version
src/libxrpl/protocol/BuildInfo.cpp
- name: Generate version
id: version
uses: ./.github/actions/generate-version
package:
needs: [generate-matrix]
needs: [generate-matrix, generate-version]
if: ${{ github.event.repository.visibility == 'public' }}
strategy:
fail-fast: false
@@ -67,13 +82,14 @@ jobs:
- name: Build package
env:
PKG_VERSION: ${{ needs.generate-version.outputs.version }}
PKG_RELEASE: ${{ inputs.pkg_release }}
run: ./package/build_pkg.sh
- name: Upload package artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ matrix.artifact_name }}-pkg
name: ${{ matrix.artifact_name }}-pkg-${{ needs.generate-version.outputs.version }}
path: |
${{ env.BUILD_DIR }}/debbuild/*.deb
${{ env.BUILD_DIR }}/debbuild/*.ddeb

View File

@@ -40,7 +40,7 @@ defaults:
jobs:
upload:
runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-e29b523
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-fe4c8ae
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

View File

@@ -15,7 +15,6 @@ repos:
hooks:
- id: check-added-large-files
args: [--maxkb=400, --enforce-all]
- id: check-executables-have-shebangs
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-merge-conflict
@@ -36,18 +35,13 @@ repos:
language: python
types_or: [c++, c]
exclude: ^include/xrpl/protocol_autogen/(transactions|ledger_entries)/
- id: fix-pragma-once
name: fix missing '#pragma once' declarations in header files
language: python
entry: ./bin/pre-commit/fix_pragma_once.py
files: \.(h|hpp)$
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: dd18dad857d6133e90bbe478f4f2f22ec0030269 # frozen: v22.1.5
hooks:
- id: clang-format
args: [--style=file]
types_or: [c++, c, proto]
"types_or": [c++, c, proto]
exclude: ^include/xrpl/protocol_autogen/(transactions|ledger_entries)/
- repo: https://github.com/BlankSpruce/gersemi-pre-commit

View File

@@ -57,8 +57,6 @@ if(target)
)
endif()
include(PatchNixBinary)
include(XrplSanity)
include(XrplVersion)
include(XrplSettings)

View File

@@ -90,19 +90,16 @@ if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then
check perl
check pkg-config
check vim
check zip
# These tools are present in our Linux CI images and in local development
# setups, but not in the macOS CI environment. So check them everywhere
# except when running in CI on macOS.
if [ "${os}" = "linux" ] || [ -z "${CI:-}" ]; then
check clang-format
check dot
check doxygen
check gcovr
check gh
check git-cliff
check git-lfs
check gpg
# pre-commit, or its alternative implementation prek
check pre-commit sh -c 'pre-commit --version || prek --version'

View File

@@ -1,34 +0,0 @@
#!/usr/bin/env python3
"""
Adds "#pragma once" to the top of header files that don't already have it.
Usage: ./bin/pre-commit/fix_pragma_once.py <file1> <file2> ...
"""
import sys
from pathlib import Path
PRAGMA_ONCE = "#pragma once\n\n"
def fix_pragma_once(path: Path) -> bool:
original = path.read_text(encoding="utf-8")
if PRAGMA_ONCE not in original:
path.write_text(PRAGMA_ONCE + original, encoding="utf-8")
return False
return True
def main() -> int:
files = [Path(f) for f in sys.argv[1:]]
success = True
for path in files:
success &= fix_pragma_once(path)
return 0 if success else 1
if __name__ == "__main__":
sys.exit(main())

View File

@@ -56,16 +56,3 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|ARM64")
else()
message(FATAL_ERROR "Unknown architecture: ${CMAKE_SYSTEM_PROCESSOR}")
endif()
# --------------------------------------------------------------------
# Sanitizers
# --------------------------------------------------------------------
# SANITIZERS is injected by the Conan toolchain when a sanitizer build is
# requested (see conan/profiles/sanitizers). The flags are applied to the
# 'common' target in XrplSanitizers; this flag lets other modules know a
# sanitizer build is active without depending on that module.
if(DEFINED SANITIZERS)
set(SANITIZERS_ENABLED TRUE)
else()
set(SANITIZERS_ENABLED FALSE)
endif()

View File

@@ -1,53 +0,0 @@
#[===================================================================[
Patch executables to run in non-Nix environments.
The Nix-based CI image links binaries against an ELF interpreter (loader)
that lives in the Nix store, so the resulting binaries don't run elsewhere
(including once installed from the .deb package). `patch_nix_binary` adds a
POST_BUILD step that resets the interpreter to the system default loader and
drops the rpath.
This is only active inside the Nix-based image, detected by the presence of
/tmp/loader-path.sh (shipped by that image, resolves the default loader). It
is skipped for sanitizer builds, whose runtime libraries are resolved through
the rpath. Everywhere else `patch_nix_binary` is a no-op.
#]===================================================================]
include_guard(GLOBAL)
include(CompilationEnv)
# Provided by the Nix-based CI image; prints the system default ELF loader path.
set(_loader_path_script "/tmp/loader-path.sh")
if(is_linux AND NOT SANITIZERS_ENABLED AND EXISTS "${_loader_path_script}")
execute_process(
COMMAND "${_loader_path_script}"
OUTPUT_VARIABLE DEFAULT_LOADER_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ERROR_IS_FATAL ANY
)
find_program(PATCHELF_COMMAND patchelf REQUIRED)
set(PATCH_NIX_BINARIES TRUE)
message(
STATUS
"Binaries will be patched to use loader '${DEFAULT_LOADER_PATH}'"
)
else()
set(PATCH_NIX_BINARIES FALSE)
endif()
function(patch_nix_binary target)
if(NOT PATCH_NIX_BINARIES)
return()
endif()
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND
"${PATCHELF_COMMAND}" --set-interpreter "${DEFAULT_LOADER_PATH}"
--remove-rpath "$<TARGET_FILE:${target}>"
COMMENT "Patching ${target}: set default loader, remove rpath"
VERBATIM
)
endfunction()

View File

@@ -154,15 +154,6 @@ else()
>
)
# On aarch64, libatomic is required for atomic operations. It is not needed on x86_64.
# Linking it statically on Linux
if(is_arm64 AND is_linux)
target_link_options(
common
INTERFACE -Wl,--push-state -Wl,-Bstatic -latomic -Wl,--pop-state
)
endif()
# Keep -stdlib=libstdc++ off the compile commands, but preserve it for linking.
#
# Conan turns `compiler.libcxx=libstdc++` into `-stdlib=libstdc++` and puts it in

View File

@@ -247,7 +247,6 @@ target_link_modules(
if(xrpld)
add_executable(xrpld)
patch_nix_binary(xrpld)
if(tests)
target_compile_definitions(xrpld PUBLIC ENABLE_TESTS)
target_compile_definitions(

View File

@@ -28,6 +28,7 @@ endif()
set(package_env
SRC_DIR=${CMAKE_SOURCE_DIR}
BUILD_DIR=${CMAKE_BINARY_DIR}
PKG_VERSION=${xrpld_version}
PKG_RELEASE=${pkg_release}
)

View File

@@ -14,9 +14,11 @@
include_guard(GLOBAL)
include(CompilationEnv)
if(NOT SANITIZERS_ENABLED)
if(NOT DEFINED SANITIZERS)
set(SANITIZERS_ENABLED FALSE)
return()
endif()
set(SANITIZERS_ENABLED TRUE)
message(STATUS "=== Configuring Sanitizers ===")
message(STATUS " SANITIZERS: ${SANITIZERS}")

View File

@@ -1,9 +1,9 @@
{
"version": "0.5",
"requires": [
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1778091116.056",
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1777558780.503",
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987",
"sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1778091117.311",
"sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1776096494.149",
"soci/4.0.3#fe32b9ad5eb47e79ab9e45a68f363945%1774450067.231",
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1765850147.878",
"secp256k1/0.7.1#481881709eb0bdd0185a12b912bbe8ad%1770910500.329",
@@ -15,19 +15,19 @@
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914",
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492",
"libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1765842973.03",
"libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1778091117.848",
"libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1776147552.838",
"jemalloc/5.3.1#1fc58d55316041f10fbc1e8a2eae632a%1776700028.228",
"gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1768312129.152",
"grpc/1.81.0#2fb144aeb47e7f35c6ebb0e5f35bed31%1781620605.685",
"grpc/1.78.1#b1a9e74b145cc471bed4dc64dc6eb2c1%1774467387.342",
"ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1765850143.772",
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772",
"c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1774439234.681",
"bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837",
"boost/1.91.0#ea540ca2133d831b560036aa24dece3c%1778091165.282",
"boost/1.91.0#ea540ca2133d831b560036aa24dece3c%1778050991.9",
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196"
],
"build_requires": [
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1778091116.056",
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1777558780.503",
"strawberryperl/5.32.1.1#8d114504d172cfea8ea1662d09b6333e%1774447376.964",
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12",
"nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1765850144.707",

View File

@@ -28,7 +28,7 @@ class Xrpl(ConanFile):
requires = [
"ed25519/2015.03",
"grpc/1.81.0",
"grpc/1.78.1",
"libarchive/3.8.7",
"nudb/2.0.9",
"openssl/3.6.2",

View File

@@ -271,6 +271,8 @@ words:
- sles
- soci
- socidb
- sponsee
- sponsees
- SRPMS
- sslws
- statsd
@@ -301,7 +303,6 @@ words:
- txs
- ubsan
- UBSAN
- ufdio
- umant
- unacquired
- unambiguity

View File

@@ -12,8 +12,8 @@ template <int Window, typename Clock>
class DecayingSample
{
public:
using value_type = Clock::duration::rep;
using time_point = Clock::time_point;
using value_type = typename Clock::duration::rep;
using time_point = typename Clock::time_point;
DecayingSample() = delete;
@@ -93,7 +93,7 @@ template <int HalfLife, class Clock>
class DecayWindow
{
public:
using time_point = Clock::time_point;
using time_point = typename Clock::time_point;
explicit DecayWindow(time_point now) : when_(now)
{

View File

@@ -206,7 +206,8 @@ private:
#ifndef JLOG
#define JLOG(x) \
if (!(x)) \
; \
{ \
} \
else \
x
#endif

View File

@@ -9,7 +9,6 @@
#include <xrpl/beast/insight/Insight.h>
#include <atomic>
#include <cstddef>
#include <functional>
#include <mutex>
#include <thread>
@@ -18,22 +17,6 @@
namespace xrpl {
namespace detail {
// Replace-policy tags selecting how TaggedCache::canonicalizeImpl resolves a
// collision when the key already exists (defined in TaggedCache.ipp):
// - ReplaceCached: always replace the cached value with `data`. `data` is
// never written back and may be const.
// - ReplaceClient: keep the cached value and write it back into `data` (the
// client's pointer), which must therefore be writable.
// - ReplaceDynamically: call the supplied callback to decide per call; `data`
// is written back when the cached value is kept, so it must be writable.
struct ReplaceCached;
struct ReplaceClient;
struct ReplaceDynamically;
} // namespace detail
/** Map/cache combination.
This class implements a cache and a map. The cache keeps objects alive
in the map. The map allows multiple code paths that reference objects
@@ -113,32 +96,6 @@ public:
bool
del(key_type const& key, bool valid);
private:
// Selects the `data` parameter type of canonicalizeImpl from the replace
// policy: const for detail::ReplaceCached (never written back), otherwise
// writable.
template <typename Policy>
using CanonicalizeClientPointerType = std::conditional_t<
std::is_same_v<detail::ReplaceCached, Policy>,
SharedPointerType const&,
SharedPointerType&>;
/** Shared implementation of the canonicalize family.
`policy` selects how a collision is resolved when `key` already exists:
detail::ReplaceCached, detail::ReplaceClient or
detail::ReplaceDynamically. For ReplaceDynamically `replaceCallback` is
invoked with the existing strong pointer and returns whether to replace
the cached value with `data`; for the tag policies it is unused.
*/
template <class Policy, class Callback = std::nullptr_t>
bool
canonicalizeImpl(
key_type const& key,
CanonicalizeClientPointerType<Policy> data,
Policy policy,
Callback&& replaceCallback = nullptr);
public:
/** Replace aliased objects with originals.
@@ -147,52 +104,19 @@ public:
This routine eliminates the duplicate and performs a replacement
on the callers shared pointer if needed.
`replaceCallback` is a callable taking the existing strong pointer and
returning whether to replace the cached value with `data` (true) or to
keep the cached value and write it back into `data` (false). Because the
write-back case mutates `data`, `data` must be writable.
@param key The key corresponding to the object
@param data A shared pointer to the data corresponding to the object.
@param replaceCallback A callable (existing strong pointer -> bool).
@param replace Function that decides if cache should be replaced
@return `true` if an existing live entry was found and used; `false` if a new entry was
inserted or an expired tracked entry was re-cached.
**/
template <class Callback>
@return `true` If the key already existed.
*/
template <class R>
bool
canonicalize(key_type const& key, SharedPointerType& data, Callback&& replaceCallback);
canonicalize(key_type const& key, SharedPointerType& data, R&& replaceCallback);
/** Insert/update the canonical entry for `key`, always replacing the
cached value with `data`.
If an entry already exists for `key`, the cached value is unconditionally
replaced with `data`; otherwise `data` is inserted. `data` is never
written back, so it may be const.
@param key The key corresponding to the object.
@param data A shared pointer to the data corresponding to the object.
@return `true` if an existing live entry was found and used; `false` if a new entry was
inserted or an expired tracked entry was re-cached.
**/
bool
canonicalizeReplaceCache(key_type const& key, SharedPointerType const& data);
/** Insert the canonical entry for `key`, keeping any existing cached value.
If an entry already exists for `key`, the cached value is kept and
written back into `data` so the caller ends up with the canonical
object; otherwise `data` is inserted. Because `data` may be overwritten
it must be writable.
@param key The key corresponding to the object.
@param data A shared pointer to the data corresponding to the object;
updated to the canonical value when one already exists.
@return `true` if an existing live entry was found and used; `false` if a new entry was
inserted or an expired tracked entry was re-cached.
**/
bool
canonicalizeReplaceClient(key_type const& key, SharedPointerType& data);
@@ -338,7 +262,7 @@ private:
sweepHelper(
clock_type::time_point const& whenExpire,
[[maybe_unused]] clock_type::time_point const& now,
KeyValueCacheType::map_type& partition,
typename KeyValueCacheType::map_type& partition,
SweptPointersVector& stuffToSweep,
std::atomic<int>& allRemovals,
std::scoped_lock<std::recursive_mutex> const&);
@@ -347,7 +271,7 @@ private:
sweepHelper(
clock_type::time_point const& whenExpire,
clock_type::time_point const& now,
KeyOnlyCacheType::map_type& partition,
typename KeyOnlyCacheType::map_type& partition,
SweptPointersVector&,
std::atomic<int>& allRemovals,
std::scoped_lock<std::recursive_mutex> const&);

View File

@@ -5,30 +5,6 @@
namespace xrpl {
namespace detail {
// Replace-policy tags selecting how TaggedCache::canonicalizeImpl resolves a
// collision when the key already exists:
// - ReplaceCached: always replace the cached value with `data`. `data` is
// never written back and may be const.
// - ReplaceClient: keep the cached value and write it back into `data` (the
// client's pointer), which must therefore be writable.
// - ReplaceDynamically: call the supplied callback to decide per call; `data`
// is written back when the cached value is kept, so it must be writable.
struct ReplaceCached
{
};
struct ReplaceClient
{
};
struct ReplaceDynamically
{
};
} // namespace detail
template <
class Key,
class T,
@@ -324,29 +300,13 @@ template <
class Hash,
class KeyEqual,
class Mutex>
template <class Policy, class Callback>
template <class R>
inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
canonicalizeImpl(
key_type const& key,
CanonicalizeClientPointerType<Policy> data,
[[maybe_unused]] Policy policy,
[[maybe_unused]] Callback&& replaceCallback)
canonicalize(key_type const& key, SharedPointerType& data, R&& replaceCallback)
{
// Return canonical value, store if needed, refresh in cache
// Return values: true=we had the data already
// `Policy` is one of:
// - detail::ReplaceCached: always replace the cached value with `data`;
// `data` is never written back and may be const.
// - detail::ReplaceClient: keep the cached value and write it back into
// `data` (the client's pointer), which must therefore be writable.
// - detail::ReplaceDynamically: call `replaceCallback` to decide at run
// time; `data` must be writable.
// For the latter two the write-back below requires a mutable `data`, so
// passing a const argument is a compile error.
constexpr bool replaceCached = std::is_same_v<Policy, detail::ReplaceCached>;
std::scoped_lock const lock(mutex_);
auto cit = cache_.find(key);
@@ -364,14 +324,13 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
Entry& entry = cit->second;
entry.touch(clock_.now());
auto shouldReplaceCached = [&] {
if constexpr (replaceCached)
auto shouldReplace = [&] {
if constexpr (std::is_invocable_r_v<bool, R>)
{
return true;
}
else if constexpr (std::is_same_v<Policy, detail::ReplaceClient>)
{
return false;
// The reason for this extra complexity is for intrusive
// strong/weak combo getting a strong is relatively expensive
// and not needed for many cases.
return replaceCallback();
}
else
{
@@ -381,11 +340,11 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
if (entry.isCached())
{
if (shouldReplaceCached())
if (shouldReplace())
{
entry.ptr = data;
}
else if constexpr (!replaceCached)
else
{
data = entry.ptr.getStrong();
}
@@ -397,11 +356,11 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
if (cachedData)
{
if (shouldReplaceCached())
if (shouldReplace())
{
entry.ptr = data;
}
else if constexpr (!replaceCached)
else
{
entry.ptr.convertToStrong();
data = cachedData;
@@ -417,24 +376,6 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
return false;
}
template <
class Key,
class T,
bool IsKeyCache,
class SharedWeakUnionPointer,
class SharedPointerType,
class Hash,
class KeyEqual,
class Mutex>
template <class Callback>
inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
canonicalize(key_type const& key, SharedPointerType& data, Callback&& replaceCallback)
{
return canonicalizeImpl(
key, data, detail::ReplaceDynamically{}, std::forward<Callback>(replaceCallback));
}
template <
class Key,
class T,
@@ -448,7 +389,7 @@ inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
canonicalizeReplaceCache(key_type const& key, SharedPointerType const& data)
{
return canonicalizeImpl(key, data, detail::ReplaceCached{});
return canonicalize(key, const_cast<SharedPointerType&>(data), []() { return true; });
}
template <
@@ -464,7 +405,7 @@ inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
canonicalizeReplaceClient(key_type const& key, SharedPointerType& data)
{
return canonicalizeImpl(key, data, detail::ReplaceClient{});
return canonicalize(key, data, []() { return false; });
}
template <
@@ -735,7 +676,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
sweepHelper(
clock_type::time_point const& whenExpire,
[[maybe_unused]] clock_type::time_point const& now,
KeyValueCacheType::map_type& partition,
typename KeyValueCacheType::map_type& partition,
SweptPointersVector& stuffToSweep,
std::atomic<int>& allRemovals,
std::scoped_lock<std::recursive_mutex> const&)
@@ -815,7 +756,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
sweepHelper(
clock_type::time_point const& whenExpire,
clock_type::time_point const& now,
KeyOnlyCacheType::map_type& partition,
typename KeyOnlyCacheType::map_type& partition,
SweptPointersVector&,
std::atomic<int>& allRemovals,
std::scoped_lock<std::recursive_mutex> const&)

View File

@@ -75,7 +75,7 @@ private:
detail::seed_pair seeds_{detail::makeSeedPair<>()};
public:
using result_type = HashAlgorithm::result_type;
using result_type = typename HashAlgorithm::result_type;
HardenedHash() = default;

View File

@@ -57,8 +57,8 @@ public:
{
using iterator_category = std::forward_iterator_tag;
partition_map_type* map{nullptr};
partition_map_type::iterator ait{};
map_type::iterator mit;
typename partition_map_type::iterator ait{};
typename map_type::iterator mit;
Iterator() = default;
@@ -126,8 +126,8 @@ public:
using iterator_category = std::forward_iterator_tag;
partition_map_type* map{nullptr};
partition_map_type::iterator ait{};
map_type::iterator mit;
typename partition_map_type::iterator ait{};
typename map_type::iterator mit;
ConstIterator() = default;

View File

@@ -29,7 +29,6 @@ static_assert(
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>;
} // namespace detail

View File

@@ -18,8 +18,8 @@ template <class Clock>
class IOLatencyProbe
{
private:
using duration = Clock::duration;
using time_point = Clock::time_point;
using duration = typename Clock::duration;
using time_point = typename Clock::time_point;
std::recursive_mutex mutex_;
std::condition_variable_any cond_;

View File

@@ -34,10 +34,10 @@ template <class Clock>
class AbstractClock
{
public:
using rep = Clock::rep;
using period = Clock::period;
using duration = Clock::duration;
using time_point = Clock::time_point;
using rep = typename Clock::rep;
using period = typename Clock::period;
using duration = typename Clock::duration;
using time_point = typename Clock::time_point;
using clock_type = Clock;
static bool const is_steady = Clock::is_steady; // NOLINT(readability-identifier-naming)

View File

@@ -20,10 +20,10 @@ public:
explicit BasicSecondsClock() = default;
using rep = Clock::rep;
using period = Clock::period;
using duration = Clock::duration;
using time_point = Clock::time_point;
using rep = typename Clock::rep;
using period = typename Clock::period;
using duration = typename Clock::duration;
using time_point = typename Clock::time_point;
static bool const is_steady = // NOLINT(readability-identifier-naming)
Clock::is_steady;

View File

@@ -16,15 +16,15 @@ template <bool IsConst, class Iterator>
class AgedContainerIterator
{
public:
using iterator_category = std::iterator_traits<Iterator>::iterator_category;
using iterator_category = typename std::iterator_traits<Iterator>::iterator_category;
using value_type = std::conditional_t<
IsConst,
typename Iterator::value_type::Stashed::value_type const,
typename Iterator::value_type::Stashed::value_type>;
using difference_type = std::iterator_traits<Iterator>::difference_type;
using difference_type = typename std::iterator_traits<Iterator>::difference_type;
using pointer = value_type*;
using reference = value_type&;
using time_point = Iterator::value_type::Stashed::time_point;
using time_point = typename Iterator::value_type::Stashed::time_point;
AgedContainerIterator() = default;

View File

@@ -62,8 +62,8 @@ class AgedOrderedContainer
{
public:
using clock_type = AbstractClock<Clock>;
using time_point = clock_type::time_point;
using duration = clock_type::duration;
using time_point = typename clock_type::time_point;
using duration = typename clock_type::duration;
using key_type = Key;
using mapped_type = T;
using value_type = std::conditional_t<IsMap, std::pair<Key const, T>, Key>;
@@ -94,8 +94,8 @@ private:
{
explicit Stashed() = default;
using value_type = AgedOrderedContainer::value_type;
using time_point = AgedOrderedContainer::time_point;
using value_type = typename AgedOrderedContainer::value_type;
using time_point = typename AgedOrderedContainer::time_point;
};
Element(time_point const& when, value_type const& value) : value(value), when(when)
@@ -192,8 +192,8 @@ private:
}
};
using list_type =
boost::intrusive::make_list<Element, boost::intrusive::constant_time_size<false>>::type;
using list_type = typename boost::intrusive::
make_list<Element, boost::intrusive::constant_time_size<false>>::type;
using cont_type = std::conditional_t<
IsMulti,
@@ -206,7 +206,8 @@ private:
boost::intrusive::constant_time_size<true>,
boost::intrusive::compare<KeyValueCompare>>::type>;
using ElementAllocator = std::allocator_traits<Allocator>::template rebind_alloc<Element>;
using ElementAllocator =
typename std::allocator_traits<Allocator>::template rebind_alloc<Element>;
using ElementAllocatorTraits = std::allocator_traits<ElementAllocator>;
@@ -372,8 +373,8 @@ public:
using allocator_type = Allocator;
using reference = value_type&;
using const_reference = value_type const&;
using pointer = std::allocator_traits<Allocator>::pointer;
using const_pointer = std::allocator_traits<Allocator>::const_pointer;
using pointer = typename std::allocator_traits<Allocator>::pointer;
using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
// A set iterator (IsMap==false) is always const
// because the elements of a set are immutable.
@@ -616,7 +617,7 @@ public:
bool MaybeMulti = IsMulti,
bool MaybeMap = IsMap,
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
std::conditional<IsMap, T, void*>::type const&
typename std::conditional<IsMap, T, void*>::type const&
at(K const& k) const;
template <
@@ -1145,7 +1146,7 @@ private:
void
touch(
beast::detail::AgedContainerIterator<IsConst, Iterator> pos,
clock_type::time_point const& now);
typename clock_type::time_point const& now);
template <
bool MaybePropagate = std::allocator_traits<Allocator>::propagate_on_container_swap::value>
@@ -1392,7 +1393,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::at(K co
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
template <class K, bool MaybeMulti, bool MaybeMap, class>
std::conditional<IsMap, T, void*>::type const&
typename std::conditional<IsMap, T, void*>::type const&
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::at(K const& k) const
{
auto const iter(cont_.find(k, std::cref(config_.keyCompare())));
@@ -1731,7 +1732,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::operato
cend(),
other.cbegin(),
other.cend(),
[&eq, &other](value_type const& lhs, Other::value_type const& rhs) {
[&eq, &other](value_type const& lhs, typename Other::value_type const& rhs) {
return eq(extract(lhs), other.extract(rhs));
});
}
@@ -1743,7 +1744,7 @@ template <bool IsConst, class Iterator, class>
void
AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::touch(
beast::detail::AgedContainerIterator<IsConst, Iterator> pos,
clock_type::time_point const& now)
typename clock_type::time_point const& now)
{
auto& e(*pos.iterator());
e.when = now;

View File

@@ -67,8 +67,8 @@ class AgedUnorderedContainer
{
public:
using clock_type = AbstractClock<Clock>;
using time_point = clock_type::time_point;
using duration = clock_type::duration;
using time_point = typename clock_type::time_point;
using duration = typename clock_type::duration;
using key_type = Key;
using mapped_type = T;
using value_type = std::conditional_t<IsMap, std::pair<Key const, T>, Key>;
@@ -99,8 +99,8 @@ private:
{
explicit Stashed() = default;
using value_type = AgedUnorderedContainer::value_type;
using time_point = AgedUnorderedContainer::time_point;
using value_type = typename AgedUnorderedContainer::value_type;
using time_point = typename AgedUnorderedContainer::time_point;
};
Element(time_point const& when, value_type const& value) : value(value), when(when)
@@ -201,8 +201,8 @@ private:
}
};
using list_type =
boost::intrusive::make_list<Element, boost::intrusive::constant_time_size<false>>::type;
using list_type = typename boost::intrusive::
make_list<Element, boost::intrusive::constant_time_size<false>>::type;
using cont_type = std::conditional_t<
IsMulti,
@@ -219,14 +219,16 @@ 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 bucket_type = typename cont_type::bucket_type;
using bucket_traits = typename cont_type::bucket_traits;
using ElementAllocator = std::allocator_traits<Allocator>::template rebind_alloc<Element>;
using ElementAllocator =
typename std::allocator_traits<Allocator>::template rebind_alloc<Element>;
using ElementAllocatorTraits = std::allocator_traits<ElementAllocator>;
using BucketAllocator = std::allocator_traits<Allocator>::template rebind_alloc<Element>;
using BucketAllocator =
typename std::allocator_traits<Allocator>::template rebind_alloc<Element>;
using BucketAllocatorTraits = std::allocator_traits<BucketAllocator>;
@@ -540,8 +542,8 @@ public:
using allocator_type = Allocator;
using reference = value_type&;
using const_reference = value_type const&;
using pointer = std::allocator_traits<Allocator>::pointer;
using const_pointer = std::allocator_traits<Allocator>::const_pointer;
using pointer = typename std::allocator_traits<Allocator>::pointer;
using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
// A set iterator (IsMap==false) is always const
// because the elements of a set are immutable.
@@ -848,7 +850,7 @@ public:
bool MaybeMulti = IsMulti,
bool MaybeMap = IsMap,
class = std::enable_if_t<MaybeMap && !MaybeMulti>>
std::conditional<IsMap, T, void*>::type const&
typename std::conditional<IsMap, T, void*>::type const&
at(K const& k) const;
template <
@@ -1412,7 +1414,7 @@ private:
void
touch(
beast::detail::AgedContainerIterator<IsConst, Iterator> pos,
clock_type::time_point const& now)
typename clock_type::time_point const& now)
{
auto& e(*pos.iterator());
e.when = now;
@@ -2109,7 +2111,7 @@ template <
class KeyEqual,
class Allocator>
template <class K, bool MaybeMulti, bool MaybeMap, class>
std::conditional<IsMap, T, void*>::type const&
typename std::conditional<IsMap, T, void*>::type const&
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::at(
K const& k) const
{

View File

@@ -24,7 +24,7 @@ struct CopyConst<T const, U>
{
explicit CopyConst() = default;
using type = std::remove_const<U>::type const;
using type = typename std::remove_const<U>::type const;
};
/** @} */
@@ -56,7 +56,7 @@ class ListIterator
{
public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type = beast::detail::CopyConst<N, typename N::value_type>::type;
using value_type = typename beast::detail::CopyConst<N, typename N::value_type>::type;
using difference_type = std::ptrdiff_t;
using pointer = value_type*;
using reference = value_type&;
@@ -259,7 +259,7 @@ template <typename T, typename Tag = void>
class List
{
public:
using Node = detail::ListNode<T, Tag>;
using Node = typename detail::ListNode<T, Tag>;
using value_type = T;
using pointer = value_type*;

View File

@@ -12,13 +12,13 @@ template <class Container, bool IsConst>
class LockFreeStackIterator
{
protected:
using Node = Container::Node;
using Node = typename Container::Node;
using NodePtr = std::conditional_t<IsConst, Node const*, Node*>;
public:
using iterator_category = std::forward_iterator_tag;
using value_type = Container::value_type;
using difference_type = Container::difference_type;
using value_type = typename Container::value_type;
using difference_type = typename Container::difference_type;
using pointer =
std::conditional_t<IsConst, typename Container::const_pointer, typename Container::pointer>;
using reference = std::

View File

@@ -11,7 +11,7 @@ struct Uhash
{
Uhash() = default;
using result_type = Hasher::result_type;
using result_type = typename Hasher::result_type;
template <class T>
result_type

View File

@@ -102,7 +102,7 @@ Result
split(FwdIt first, FwdIt last, Char delim)
{
using namespace detail;
using string = Result::value_type;
using string = typename Result::value_type;
Result result;

View File

@@ -32,11 +32,11 @@ protected:
}
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 = typename cont_type::value_type;
using size_type = typename cont_type::size_type;
using difference_type = typename cont_type::difference_type;
using iterator = typename cont_type::const_iterator;
using const_iterator = typename cont_type::const_iterator;
/** Returns `true` if the container is empty. */
[[nodiscard]] bool

View File

@@ -48,7 +48,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();
typename clock_type::time_point start = clock_type::now();
explicit SuiteResults(std::string name = "") : name(std::move(name))
{
@@ -60,7 +60,7 @@ private:
struct Results
{
using run_time = std::pair<std::string, clock_type::duration>;
using run_time = std::pair<std::string, typename clock_type::duration>;
static constexpr auto kMaxTop = 10;
@@ -69,7 +69,7 @@ private:
std::size_t total = 0;
std::size_t failed = 0;
std::vector<run_time> top;
clock_type::time_point start = clock_type::now();
typename clock_type::time_point start = clock_type::now();
void
add(SuiteResults const& r);
@@ -91,7 +91,7 @@ public:
private:
static std::string
fmtdur(clock_type::duration const& d);
fmtdur(typename clock_type::duration const& d);
void
onSuiteBegin(SuiteInfo const& info) override;
@@ -141,7 +141,9 @@ Reporter<Unused>::Results::add(SuiteResults const& r)
top.begin(),
top.end(),
elapsed,
[](run_time const& t1, clock_type::duration const& t2) { return t1.second > t2; });
[](run_time const& t1, typename clock_type::duration const& t2) {
return t1.second > t2;
});
if (iter != top.end())
{
if (top.size() == kMaxTop)
@@ -179,7 +181,7 @@ Reporter<Unused>::~Reporter()
template <class Unused>
std::string
Reporter<Unused>::fmtdur(clock_type::duration const& d)
Reporter<Unused>::fmtdur(typename clock_type::duration const& d)
{
using namespace std::chrono;
auto const ms = duration_cast<milliseconds>(d);

View File

@@ -411,9 +411,9 @@ class BasicLogstream : public std::basic_ostream<CharT, Traits>
{
using char_type = CharT;
using traits_type = Traits;
using int_type = traits_type::int_type;
using pos_type = traits_type::pos_type;
using off_type = traits_type::off_type;
using int_type = typename traits_type::int_type;
using pos_type = typename traits_type::pos_type;
using off_type = typename traits_type::off_type;
detail::LogStreamBuf<CharT, Traits> buf_;

View File

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

View File

@@ -13,7 +13,7 @@ template <class Generator>
void
rngfill(void* const buffer, std::size_t const bytes, Generator& g)
{
using result_type = Generator::result_type;
using result_type = typename Generator::result_type;
constexpr std::size_t kResultSize = sizeof(result_type);
std::uint8_t* const bufferStart = static_cast<std::uint8_t*>(buffer);
@@ -42,7 +42,7 @@ template <
void
rngfill(std::array<std::uint8_t, N>& a, Generator& g)
{
using result_type = Generator::result_type;
using result_type = typename Generator::result_type;
auto i = N / sizeof(result_type);
result_type* p = reinterpret_cast<result_type*>(a.data());
while (i--)

View File

@@ -566,7 +566,6 @@ public:
using SelfType = ValueConstIterator;
ValueConstIterator() = default;
ValueConstIterator(ValueConstIterator const& other) = default;
private:
/*! \internal Use by Value to create an iterator.
@@ -575,12 +574,12 @@ private:
public:
SelfType&
operator=(SelfType const& other);
operator=(ValueIteratorBase const& other);
SelfType
operator++(int)
{
SelfType const temp(*this);
SelfType temp(*this);
++*this;
return temp;
}
@@ -588,7 +587,7 @@ public:
SelfType
operator--(int)
{
SelfType const temp(*this);
SelfType temp(*this);
--*this;
return temp;
}

View File

@@ -33,9 +33,96 @@ isGlobalFrozen(ReadView const& view, AccountID const& issuer);
[[nodiscard]] XRPAmount
xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj, beast::Journal j);
/** Returns the account reserve, in drops.
Actual owner count can be adjusted by delta in ownerCountAdj
The reserve is calculated as
(ownerCount + "sponsoring object count" - "sponsored object count" + additionalOwnerCount) *
increment + (1 if not sponsored account + sponsoringAccountCount) * "reserve base"
*/
[[nodiscard]] XRPAmount
accountReserve(
ReadView const& view,
SLE::const_ref sle,
beast::Journal j,
std::int32_t ownerCountAdj = 0,
std::int32_t reserveCountAdj = 0);
[[nodiscard]] inline XRPAmount
accountReserve(
ReadView const& view,
AccountID const& id,
beast::Journal j,
std::int32_t ownerCountAdj = 0,
std::int32_t reserveCountAdj = 0)
{
return accountReserve(view, view.read(keylet::account(id)), j, ownerCountAdj, reserveCountAdj);
}
XRPAmount
baseAccountReserve(ReadView const& view, std::int32_t ownerCount);
[[nodiscard]] TER
checkInsufficientReserve(
ReadView const& view,
STTx const& tx,
SLE::const_ref accSle,
STAmount const& accBalance,
SLE::const_ref sponsorSle,
std::int32_t ownerCountDelta,
std::int32_t reserveCountDelta = 0,
beast::Journal j = beast::Journal{beast::Journal::getNullSink()});
std::uint32_t
ownerCount(
ReadView const& view,
SLE::const_ref sle,
beast::Journal j,
std::int32_t ownerCountAdj = 0);
/** Adjust the owner count up or down. */
void
adjustOwnerCount(ApplyView& view, SLE::ref sle, std::int32_t amount, beast::Journal j);
adjustOwnerCount(
ApplyView& view,
SLE::ref accountSle,
SLE::ref sponsorSle,
std::int32_t amount,
beast::Journal j = beast::Journal{beast::Journal::getNullSink()});
inline void
adjustOwnerCount(
ApplyView& view,
AccountID const& account,
std::optional<AccountID> const& sponsor,
std::int32_t amount,
beast::Journal j = beast::Journal{beast::Journal::getNullSink()})
{
adjustOwnerCount(
view,
view.peek(keylet::account(account)),
sponsor ? view.peek(keylet::account(*sponsor)) : SLE::pointer(),
amount,
j);
}
void
adjustOwnerCountObj(
ApplyView& view,
SLE::ref accountSle,
SLE::ref objectSle,
std::int32_t amount,
beast::Journal j = beast::Journal{beast::Journal::getNullSink()});
inline void
adjustOwnerCountObj(
ApplyView& view,
AccountID const& account,
SLE::ref objectSle,
std::int32_t amount,
beast::Journal j = beast::Journal{beast::Journal::getNullSink()})
{
SLE::ref accountSle = view.peek(keylet::account(account));
adjustOwnerCountObj(view, accountSle, objectSle, amount, j);
}
/** Returns IOU issuer transfer fee as Rate. Rate specifies
* the fee as fractions of 1 billion. For example, 1% transfer rate
@@ -71,7 +158,7 @@ getPseudoAccountFields();
- null pointer
*/
[[nodiscard]] bool
isPseudoAccount(SLE::const_pointer sleAcct, std::set<SField const*> const& pseudoFieldFilter = {});
isPseudoAccount(SLE::const_ref sleAcct, std::set<SField const*> const& pseudoFieldFilter = {});
/** Convenience overload that reads the account from the view. */
[[nodiscard]] inline bool

View File

@@ -6,6 +6,7 @@
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/MPTAmount.h>
@@ -17,6 +18,7 @@ template <ValidIssueType T>
TER
escrowUnlockApplyHelper(
ApplyView& view,
STTx const& tx,
Rate lockedRate,
SLE::ref sleDest,
STAmount const& xrpBalance,
@@ -31,6 +33,7 @@ template <>
inline TER
escrowUnlockApplyHelper<Issue>(
ApplyView& view,
STTx const& tx,
Rate lockedRate,
SLE::ref sleDest,
STAmount const& xrpBalance,
@@ -56,8 +59,13 @@ escrowUnlockApplyHelper<Issue>(
if (!view.exists(trustLineKey) && createAsset)
{
// Can the account cover the trust line's reserve?
if (std::uint32_t const ownerCount = {sleDest->at(sfOwnerCount)};
xrpBalance < view.fees().accountReserve(ownerCount + 1))
auto const sponsorSle = getTxReserveSponsor(view, tx);
if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE
if (auto const ret =
checkInsufficientReserve(view, tx, sleDest, xrpBalance, *sponsorSle, 1, 0, journal);
!isTesSuccess(ret))
{
JLOG(journal.trace()) << "Trust line does not exist. "
"Insufficient reserve to create line.";
@@ -84,6 +92,7 @@ escrowUnlockApplyHelper<Issue>(
Issue(currency, receiver), // limit of zero
0, // quality in
0, // quality out
*sponsorSle, // sponsor
journal); // journal
!isTesSuccess(ter))
{
@@ -161,6 +170,7 @@ template <>
inline TER
escrowUnlockApplyHelper<MPTIssue>(
ApplyView& view,
STTx const& tx,
Rate lockedRate,
SLE::ref sleDest,
STAmount const& xrpBalance,
@@ -176,24 +186,31 @@ escrowUnlockApplyHelper<MPTIssue>(
auto const mptID = amount.get<MPTIssue>().getMptID();
auto const issuanceKey = keylet::mptIssuance(mptID);
if (!view.exists(keylet::mptoken(issuanceKey.key, receiver)) && createAsset && !receiverIssuer)
auto const mptKeylet = keylet::mptoken(issuanceKey.key, receiver);
if (!view.exists(mptKeylet) && createAsset && !receiverIssuer)
{
if (std::uint32_t const ownerCount = {sleDest->at(sfOwnerCount)};
xrpBalance < view.fees().accountReserve(ownerCount + 1))
{
return tecINSUFFICIENT_RESERVE;
}
auto const sponsorSle = getTxReserveSponsor(view, tx);
if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE
if (auto const ter = createMPToken(view, mptID, receiver, 0); !isTesSuccess(ter))
if (auto const ret =
checkInsufficientReserve(view, tx, sleDest, xrpBalance, *sponsorSle, 1, 0, journal);
!isTesSuccess(ret))
return ret;
if (auto const ter = createMPToken(view, mptID, receiver, *sponsorSle, 0);
!isTesSuccess(ter))
{
return ter; // LCOV_EXCL_LINE
}
// update owner count.
adjustOwnerCount(view, sleDest, 1, journal);
adjustOwnerCount(view, sleDest, *sponsorSle, 1, journal);
auto mptSle = view.peek(mptKeylet);
addSponsorToLedgerEntry(mptSle, *sponsorSle);
}
if (!view.exists(keylet::mptoken(issuanceKey.key, receiver)) && !receiverIssuer)
if (!view.exists(mptKeylet) && !receiverIssuer)
return tecNO_PERMISSION;
auto const xferRate = transferRate(view, amount);

View File

@@ -72,6 +72,7 @@ canAddHolding(ReadView const& view, MPTIssue const& mptIssue);
[[nodiscard]] TER
authorizeMPToken(
ApplyView& view,
STTx const& tx,
XRPAmount const& priorBalance,
MPTID const& mptIssuanceID,
AccountID const& account,
@@ -103,6 +104,7 @@ requireAuth(
[[nodiscard]] TER
enforceMPTokenAuthorization(
ApplyView& view,
STTx const& tx,
MPTID const& mptIssuanceID,
AccountID const& account,
XRPAmount const& priorBalance,
@@ -189,6 +191,7 @@ canMPTTradeAndTransfer(
[[nodiscard]] TER
addEmptyHolding(
ApplyView& view,
STTx const& tx,
AccountID const& accountID,
XRPAmount priorBalance,
MPTIssue const& mptIssue,
@@ -197,6 +200,7 @@ addEmptyHolding(
[[nodiscard]] TER
removeEmptyHolding(
ApplyView& view,
STTx const& tx,
AccountID const& accountID,
MPTIssue const& mptIssue,
beast::Journal journal);
@@ -228,6 +232,7 @@ createMPToken(
ApplyView& view,
MPTID const& mptIssuanceID,
AccountID const& account,
SLE::ref sponsorSle,
std::uint32_t const flags);
TER
@@ -235,6 +240,7 @@ checkCreateMPT(
xrpl::ApplyView& view,
xrpl::MPTIssue const& mptIssue,
xrpl::AccountID const& holder,
SLE::ref sponsorSle,
beast::Journal j);
//------------------------------------------------------------------------------

View File

@@ -39,7 +39,7 @@ findTokenAndPage(ApplyView& view, AccountID const& owner, uint256 const& nftoken
/** Insert the token in the owner's token directory. */
TER
insertToken(ApplyView& view, AccountID owner, STObject&& nft);
insertToken(ApplyView& view, STTx const& tx, AccountID owner, SLE::ref sponsorSle, STObject&& nft);
/** Remove the token from the owner's token directory. */
TER
@@ -107,6 +107,7 @@ tokenOfferCreatePreclaim(
TER
tokenOfferCreateApply(
ApplyView& view,
STTx const& tx,
AccountID const& acctID,
STAmount const& amount,
std::optional<AccountID> const& dest,

View File

@@ -1,5 +1,4 @@
#pragma once
#include <xrpl/ledger/View.h>
namespace xrpl::permissioned_dex {

View File

@@ -149,6 +149,7 @@ trustCreate(
// Issuer should be the account being set.
std::uint32_t uQualityIn,
std::uint32_t uQualityOut,
SLE::ref sponsorSle,
beast::Journal j);
[[nodiscard]] TER
@@ -229,6 +230,7 @@ canTransfer(ReadView const& view, Issue const& issue, AccountID const& from, Acc
[[nodiscard]] TER
addEmptyHolding(
ApplyView& view,
STTx const& tx,
AccountID const& accountID,
XRPAmount priorBalance,
Issue const& issue,

View File

@@ -0,0 +1,134 @@
#pragma once
#include <xrpl/basics/Log.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/View.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TxFlags.h>
#include <expected>
namespace xrpl {
inline bool
isFeeSponsored(STTx const& tx)
{
return (tx.getFieldU32(sfSponsorFlags) & spfSponsorFee) != 0u;
}
inline bool
isReserveSponsored(STTx const& tx)
{
return (tx.getFieldU32(sfSponsorFlags) & spfSponsorReserve) != 0u;
}
inline bool
isSponsorReserveCoSigning(STTx const& tx)
{
if (!tx.isFieldPresent(sfSponsorSignature))
return false;
return isReserveSponsored(tx);
}
inline std::optional<AccountID>
getTxReserveSponsorAccountID(STTx const& tx)
{
if (tx.isFieldPresent(sfSponsor) && isReserveSponsored(tx))
{
return tx.getAccountID(sfSponsor);
}
return {};
}
inline std::expected<SLE::pointer, TER>
getTxReserveSponsor(ApplyView& view, STTx const& tx)
{
auto const sponsorID = getTxReserveSponsorAccountID(tx);
if (sponsorID)
{
auto sle = view.peek(keylet::account(*sponsorID));
// already checked in Transactor::checkSponsor
if (!sle)
return std::unexpected(tecINTERNAL);
return sle;
}
return SLE::pointer();
}
inline std::expected<SLE::const_pointer, TER>
getTxReserveSponsor(ReadView const& view, STTx const& tx)
{
auto const sponsorID = getTxReserveSponsorAccountID(tx);
if (sponsorID)
{
auto sle = view.read(keylet::account(*sponsorID));
// already checked in Transactor::checkSponsor
if (!sle)
return std::unexpected(tecINTERNAL);
return sle;
}
return SLE::pointer();
}
inline std::optional<AccountID>
getLedgerEntryReserveSponsorAccountID(SLE::const_ref sle, SF_ACCOUNT const& field = sfSponsor)
{
if (sle->isFieldPresent(field))
return sle->getAccountID(field);
return {};
}
inline SLE::pointer
getLedgerEntryReserveSponsor(
ApplyView& view,
SLE::const_ref sle,
SF_ACCOUNT const& field = sfSponsor)
{
auto const sponsorID = getLedgerEntryReserveSponsorAccountID(sle, field);
if (sponsorID)
return view.peek(keylet::account(*sponsorID));
return {};
}
inline SLE::const_pointer
getLedgerEntryReserveSponsor(
ReadView const& view,
SLE::const_ref sle,
SF_ACCOUNT const& field = sfSponsor)
{
auto const sponsorID = getLedgerEntryReserveSponsorAccountID(sle, field);
if (sponsorID)
return view.read(keylet::account(*sponsorID));
return {};
}
inline void
addSponsorToLedgerEntry(
SLE::ref sle,
SLE::const_ref sponsorSle,
SF_ACCOUNT const& field = sfSponsor)
{
XRPL_ASSERT(
(sle->getType() == ltRIPPLE_STATE && (field == sfHighSponsor || field == sfLowSponsor)) ||
(sle->getType() != ltRIPPLE_STATE && field == sfSponsor),
"addSponsorToLedgerEntry : Invalid field to the LedgerEntry");
if (sponsorSle)
sle->setAccountID(field, sponsorSle->getAccountID(sfAccount));
}
inline void
removeSponsorFromLedgerEntry(SLE::ref sle, SF_ACCOUNT const& field = sfSponsor)
{
XRPL_ASSERT(
(sle->getType() == ltRIPPLE_STATE && (field == sfHighSponsor || field == sfLowSponsor)) ||
(sle->getType() != ltRIPPLE_STATE && field == sfSponsor),
"removeSponsorFromLedgerEntry : Invalid field to the LedgerEntry");
if (sle->isFieldPresent(field))
sle->makeFieldAbsent(field);
}
} // namespace xrpl

View File

@@ -231,6 +231,7 @@ canAddHolding(ReadView const& view, Asset const& asset);
[[nodiscard]] TER
addEmptyHolding(
ApplyView& view,
STTx const& tx,
AccountID const& accountID,
XRPAmount priorBalance,
Asset const& asset,
@@ -239,6 +240,7 @@ addEmptyHolding(
[[nodiscard]] TER
removeEmptyHolding(
ApplyView& view,
STTx const& tx,
AccountID const& accountID,
Asset const& asset,
beast::Journal journal);
@@ -299,6 +301,7 @@ accountSend(
AccountID const& to,
STAmount const& saAmount,
beast::Journal j,
SLE::ref sponsorSle = {},
WaiveTransferFee waiveFee = WaiveTransferFee::No,
AllowMPTOverflow allowOverflow = AllowMPTOverflow::No);
@@ -316,6 +319,7 @@ accountSendMulti(
Asset const& asset,
MultiplePaymentDestinations const& receivers,
beast::Journal j,
SLE::ref sponsorSle,
WaiveTransferFee waiveFee = WaiveTransferFee::No);
[[nodiscard]] TER

View File

@@ -1,5 +1,3 @@
#pragma once
#include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/STVector256.h>
#include <xrpl/protocol/Serializer.h>

View File

@@ -33,17 +33,6 @@ struct Fees
: base(base), reserve(reserve), increment(increment)
{
}
/** Returns the account reserve given the owner count, in drops.
The reserve is calculated as the reserve base plus
the reserve increment times the number of increments.
*/
[[nodiscard]] XRPAmount
accountReserve(std::size_t ownerCount) const
{
return reserve + ownerCount * increment;
}
};
} // namespace xrpl

View File

@@ -151,6 +151,10 @@ static TicketT const kTicket{};
Keylet
signers(AccountID const& account) noexcept;
/** A Sponsorship */
Keylet
sponsorship(AccountID const& sponsor, AccountID const& sponsee) noexcept;
/** A Check */
/** @{ */
Keylet

View File

@@ -118,13 +118,13 @@ public:
}
// begin() and end() are provided for testing purposes.
[[nodiscard]] std::forward_list<Item>::const_iterator
[[nodiscard]] typename std::forward_list<Item>::const_iterator
begin() const
{
return formats_.begin();
}
[[nodiscard]] std::forward_list<Item>::const_iterator
[[nodiscard]] typename std::forward_list<Item>::const_iterator
end() const
{
return formats_.end();

View File

@@ -203,7 +203,11 @@ enum LedgerEntryType : std::uint16_t {
LEDGER_OBJECT(Loan, \
LSF_FLAG(lsfLoanDefault, 0x00010000) \
LSF_FLAG(lsfLoanImpaired, 0x00020000) \
LSF_FLAG(lsfLoanOverpayment, 0x00040000)) /* True, loan allows overpayments */
LSF_FLAG(lsfLoanOverpayment, 0x00040000)) /* True, loan allows overpayments */ \
\
LEDGER_OBJECT(Sponsorship, \
LSF_FLAG(lsfSponsorshipRequireSignForFee, 0x00010000) \
LSF_FLAG(lsfSponsorshipRequireSignForReserve, 0x00020000))
// clang-format on

View File

@@ -163,7 +163,7 @@ STBitString<Bits>::setValue(BaseUInt<Bits, Tag> const& v)
}
template <int Bits>
STBitString<Bits>::value_type const&
typename STBitString<Bits>::value_type const&
STBitString<Bits>::value() const
{
return value_;

View File

@@ -120,7 +120,7 @@ STInteger<Integer>::operator=(value_type const& v)
}
template <typename Integer>
inline STInteger<Integer>::value_type
inline typename STInteger<Integer>::value_type
STInteger<Integer>::value() const noexcept
{
return value_;

View File

@@ -243,7 +243,7 @@ public:
@throws STObject::FieldErr if the field is not present.
*/
template <class T>
T::value_type
typename T::value_type
operator[](TypedField<T> const& f) const;
/** Get the value of a field as a std::optional
@@ -290,7 +290,7 @@ public:
@throws STObject::FieldErr if the field is not present.
*/
template <class T>
[[nodiscard]] T::value_type
[[nodiscard]] typename T::value_type
at(TypedField<T> const& f) const;
/** Get the value of a field as std::optional
@@ -478,7 +478,7 @@ template <class T>
class STObject::Proxy
{
public:
using value_type = T::value_type;
using value_type = typename T::value_type;
[[nodiscard]] value_type
value() const;
@@ -513,10 +513,13 @@ protected:
template <typename U>
concept IsArithmeticNumber =
std::is_arithmetic_v<U> || std::is_same_v<U, Number> || std::is_same_v<U, STAmount>;
template <typename U, typename Value = U::value_type, typename Unit = U::unit_type>
template <
typename U,
typename Value = typename U::value_type,
typename Unit = typename U::unit_type>
concept IsArithmeticValueUnit = std::is_same_v<U, unit::ValueUnit<Unit, Value>> &&
IsArithmeticNumber<Value> && std::is_class_v<Unit>;
template <typename U, typename Value = U::value_type>
template <typename U, typename Value = typename U::value_type>
concept IsArithmeticST = !IsArithmeticValueUnit<U> && IsArithmeticNumber<Value>;
template <typename U>
concept IsArithmetic = IsArithmeticNumber<U> || IsArithmeticST<U> || IsArithmeticValueUnit<U>;
@@ -531,7 +534,7 @@ template <class T>
class STObject::ValueProxy : public Proxy<T>
{
private:
using value_type = T::value_type;
using value_type = typename T::value_type;
public:
ValueProxy(ValueProxy const&) = default;
@@ -573,7 +576,7 @@ template <class T>
class STObject::OptionalProxy : public Proxy<T>
{
private:
using value_type = T::value_type;
using value_type = typename T::value_type;
using optional_type = std::optional<std::decay_t<value_type>>;
@@ -837,7 +840,7 @@ operator typename STObject::OptionalProxy<T>::optional_type() const
}
template <class T>
STObject::OptionalProxy<T>::optional_type
typename STObject::OptionalProxy<T>::optional_type
STObject::OptionalProxy<T>::operator~() const
{
return optionalValue();
@@ -930,7 +933,7 @@ STObject::OptionalProxy<T>::optionalValue() const -> optional_type
}
template <class T>
STObject::OptionalProxy<T>::value_type
typename STObject::OptionalProxy<T>::value_type
STObject::OptionalProxy<T>::valueOr(value_type val) const
{
return engaged() ? this->value() : val;
@@ -1037,7 +1040,7 @@ STObject::getPIndex(int offset)
}
template <class T>
T::value_type
typename T::value_type
STObject::operator[](TypedField<T> const& f) const
{
return at(f);
@@ -1065,7 +1068,7 @@ STObject::operator[](OptionaledField<T> const& of) -> OptionalProxy<T>
}
template <class T>
[[nodiscard]] T::value_type
[[nodiscard]] typename T::value_type
STObject::at(TypedField<T> const& f) const
{
auto const b = peekAtPField(f);

View File

@@ -84,7 +84,7 @@ public:
getSeqValue() const;
AccountID
getFeePayer() const;
getInitiator() const;
boost::container::flat_set<AccountID>
getMentionedAccounts() const;

View File

@@ -220,6 +220,7 @@ enum TERcodes : TERUnderlyingType {
// create a pseudo-account
terNO_DELEGATE_PERMISSION, // Delegate does not have permission
terLOCKED, // MPT is locked
terNO_SPONSORSHIP, // No sponsorship found
};
//------------------------------------------------------------------------------
@@ -358,6 +359,7 @@ enum TECcodes : TERUnderlyingType {
tecLIMIT_EXCEEDED = 195,
tecPSEUDO_ACCOUNT = 196,
tecPRECISION_LOSS = 197,
tecNO_SPONSOR_PERMISSION = 198,
};
//------------------------------------------------------------------------------
@@ -657,13 +659,13 @@ inline bool
isTesSuccess(TER x) noexcept
{
// Makes use of TERSubset::operator bool()
return !x;
return !(x);
}
inline bool
isTecClaim(TER x) noexcept
{
return (x >= tecCLAIM);
return ((x) >= tecCLAIM);
}
std::unordered_map<TERUnderlyingType, std::pair<char const* const, char const* const>> const&

View File

@@ -102,7 +102,8 @@ inline constexpr FlagValue tfUniversalMask = ~tfUniversal;
TRANSACTION(Payment, \
TF_FLAG(tfNoRippleDirect, 0x00010000) \
TF_FLAG(tfPartialPayment, 0x00020000) \
TF_FLAG(tfLimitQuality, 0x00040000), \
TF_FLAG(tfLimitQuality, 0x00040000) \
TF_FLAG(tfSponsorCreatedAccount, 0x00080000), \
MASK_ADJ(0)) \
\
TRANSACTION(TrustSet, \
@@ -214,6 +215,20 @@ inline constexpr FlagValue tfUniversalMask = ~tfUniversal;
TF_FLAG(tfLoanDefault, 0x00010000) \
TF_FLAG(tfLoanImpair, 0x00020000) \
TF_FLAG(tfLoanUnimpair, 0x00040000), \
MASK_ADJ(0)) \
\
TRANSACTION(SponsorshipSet, \
TF_FLAG(tfSponsorshipSetRequireSignForFee, 0x00010000) \
TF_FLAG(tfSponsorshipClearRequireSignForFee, 0x00020000) \
TF_FLAG(tfSponsorshipSetRequireSignForReserve, 0x00040000) \
TF_FLAG(tfSponsorshipClearRequireSignForReserve, 0x00080000) \
TF_FLAG(tfDeleteObject, 0x00100000), \
MASK_ADJ(0)) \
\
TRANSACTION(SponsorshipTransfer, \
TF_FLAG(tfSponsorshipEnd, 0x00000001) \
TF_FLAG(tfSponsorshipCreate, 0x00000002) \
TF_FLAG(tfSponsorshipReassign, 0x00000004), \
MASK_ADJ(0))
// clang-format on
@@ -439,6 +454,12 @@ getAsfFlagMap()
#pragma pop_macro("ACCOUNTSET_FLAG_TO_MAP")
#pragma pop_macro("ACCOUNTSET_FLAGS")
// Sponsor flags (spf)
inline constexpr FlagValue spfSponsorFee = 1;
inline constexpr FlagValue spfSponsorReserve = 2;
inline constexpr FlagValue spfSponsorFlagMask = ~(spfSponsorFee | spfSponsorReserve);
} // namespace xrpl
// NOLINTEND(readability-identifier-naming)

View File

@@ -391,7 +391,7 @@ mulDivU(Source1 value, Dest mul, Source2 div)
return std::nullopt;
}
using desttype = Dest::value_type;
using desttype = typename Dest::value_type;
constexpr auto kMax = std::numeric_limits<desttype>::max();
// Shortcuts, since these happen a lot in the real world

View File

@@ -379,16 +379,16 @@ public:
[[nodiscard]] STArray
toSTArray() const;
[[nodiscard]] AttCollection::const_iterator
[[nodiscard]] typename AttCollection::const_iterator
begin() const;
[[nodiscard]] AttCollection::const_iterator
[[nodiscard]] typename AttCollection::const_iterator
end() const;
AttCollection::iterator
typename AttCollection::iterator
begin();
AttCollection::iterator
typename AttCollection::iterator
end();
template <class F>
@@ -419,7 +419,7 @@ operator==(
}
template <class TAttestation>
inline XChainAttestationsBase<TAttestation>::AttCollection const&
inline typename XChainAttestationsBase<TAttestation>::AttCollection const&
XChainAttestationsBase<TAttestation>::attestations() const
{
return attestations_;

View File

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

View File

@@ -127,29 +127,32 @@ LEDGER_ENTRY(ltTICKET, 0x0054, Ticket, ticket, ({
\sa keylet::account
*/
LEDGER_ENTRY(ltACCOUNT_ROOT, 0x0061, AccountRoot, account, ({
{sfAccount, SoeRequired},
{sfSequence, SoeRequired},
{sfBalance, SoeRequired},
{sfOwnerCount, SoeRequired},
{sfPreviousTxnID, SoeRequired},
{sfPreviousTxnLgrSeq, SoeRequired},
{sfAccountTxnID, SoeOptional},
{sfRegularKey, SoeOptional},
{sfEmailHash, SoeOptional},
{sfWalletLocator, SoeOptional},
{sfWalletSize, SoeOptional},
{sfMessageKey, SoeOptional},
{sfTransferRate, SoeOptional},
{sfDomain, SoeOptional},
{sfTickSize, SoeOptional},
{sfTicketCount, SoeOptional},
{sfNFTokenMinter, SoeOptional},
{sfMintedNFTokens, SoeDefault},
{sfBurnedNFTokens, SoeDefault},
{sfFirstNFTokenSequence, SoeOptional},
{sfAMMID, SoeOptional}, // pseudo-account designator
{sfVaultID, SoeOptional}, // pseudo-account designator
{sfLoanBrokerID, SoeOptional}, // pseudo-account designator
{sfAccount, SoeRequired},
{sfSequence, SoeRequired},
{sfBalance, SoeRequired},
{sfOwnerCount, SoeRequired},
{sfPreviousTxnID, SoeRequired},
{sfPreviousTxnLgrSeq, SoeRequired},
{sfAccountTxnID, SoeOptional},
{sfRegularKey, SoeOptional},
{sfEmailHash, SoeOptional},
{sfWalletLocator, SoeOptional},
{sfWalletSize, SoeOptional},
{sfMessageKey, SoeOptional},
{sfTransferRate, SoeOptional},
{sfDomain, SoeOptional},
{sfTickSize, SoeOptional},
{sfTicketCount, SoeOptional},
{sfNFTokenMinter, SoeOptional},
{sfMintedNFTokens, SoeDefault},
{sfBurnedNFTokens, SoeDefault},
{sfFirstNFTokenSequence, SoeOptional},
{sfSponsoredOwnerCount, SoeDefault},
{sfSponsoringOwnerCount, SoeDefault},
{sfSponsoringAccountCount, SoeDefault},
{sfAMMID, SoeOptional}, // pseudo-account designator
{sfVaultID, SoeOptional}, // pseudo-account designator
{sfLoanBrokerID, SoeOptional}, // pseudo-account designator
}))
/** A ledger object which contains a list of object identifiers.
@@ -286,6 +289,8 @@ LEDGER_ENTRY(ltRIPPLE_STATE, 0x0072, RippleState, state, ({
{sfHighNode, SoeOptional},
{sfHighQualityIn, SoeOptional},
{sfHighQualityOut, SoeOptional},
{sfHighSponsor, SoeOptional},
{sfLowSponsor, SoeOptional},
}))
/** The ledger object which lists the network's fee settings.
@@ -607,5 +612,20 @@ LEDGER_ENTRY(ltLOAN, 0x0089, Loan, loan, ({
{sfLoanScale, SoeDefault},
}))
/** A ledger object representing a sponsorship.
\sa keylet::sponsorship
*/
LEDGER_ENTRY(ltSPONSORSHIP, 0x0090, Sponsorship, sponsorship, ({
{sfPreviousTxnID, SoeRequired},
{sfPreviousTxnLgrSeq, SoeRequired},
{sfOwner, SoeRequired},
{sfSponsee, SoeRequired},
{sfFeeAmount, SoeOptional},
{sfMaxFee, SoeOptional},
{sfRemainingOwnerCount, SoeDefault},
{sfOwnerNode, SoeRequired},
{sfSponseeNode, SoeRequired},
}))
#undef EXPAND
#undef LEDGER_ENTRY_DUPLICATE

View File

@@ -72,3 +72,16 @@ GRANULAR_PERMISSION(MPTokenIssuanceLock, ttMPTOKEN_ISSUANCE_SET, 65547, tfUniver
GRANULAR_PERMISSION(MPTokenIssuanceUnlock, ttMPTOKEN_ISSUANCE_SET, 65548, tfUniversal | tfMPTUnlock,
({{sfMPTokenIssuanceID, SoeRequired},
{sfHolder, SoeOptional}}))
/** This permission grants the delegated account the ability to set SponsorFee. */
GRANULAR_PERMISSION(SponsorFee, ttSPONSORSHIP_SET, 65549,
tfUniversal | tfSponsorshipSetRequireSignForFee | tfSponsorshipClearRequireSignForFee,
({{sfSponsee, SoeOptional},
{sfFeeAmount, SoeOptional},
{sfMaxFee, SoeOptional}}))
/** This permission grants the delegated account the ability to set SponsorReserve. */
GRANULAR_PERMISSION(SponsorReserve, ttSPONSORSHIP_SET, 65550,
tfUniversal | tfSponsorshipSetRequireSignForReserve | tfSponsorshipClearRequireSignForReserve,
({{sfSponsee, SoeOptional},
{sfRemainingOwnerCount, SoeOptional}}))

View File

@@ -113,6 +113,11 @@ TYPED_SFIELD(sfInterestRate, UINT32, 65) // 1/10 basis points (bi
TYPED_SFIELD(sfLateInterestRate, UINT32, 66) // 1/10 basis points (bips)
TYPED_SFIELD(sfCloseInterestRate, UINT32, 67) // 1/10 basis points (bips)
TYPED_SFIELD(sfOverpaymentInterestRate, UINT32, 68) // 1/10 basis points (bips)
TYPED_SFIELD(sfSponsoredOwnerCount, UINT32, 69)
TYPED_SFIELD(sfSponsoringOwnerCount, UINT32, 70)
TYPED_SFIELD(sfSponsoringAccountCount, UINT32, 71)
TYPED_SFIELD(sfRemainingOwnerCount, UINT32, 72)
TYPED_SFIELD(sfSponsorFlags, UINT32, 73)
// 64-bit integers (common)
TYPED_SFIELD(sfIndexNext, UINT64, 1)
@@ -146,6 +151,7 @@ TYPED_SFIELD(sfSubjectNode, UINT64, 28)
TYPED_SFIELD(sfLockedAmount, UINT64, 29, SField::kSmdBaseTen|SField::kSmdDefault)
TYPED_SFIELD(sfVaultNode, UINT64, 30)
TYPED_SFIELD(sfLoanBrokerNode, UINT64, 31)
TYPED_SFIELD(sfSponseeNode, UINT64, 32)
// 128-bit
TYPED_SFIELD(sfEmailHash, UINT128, 1)
@@ -206,6 +212,7 @@ TYPED_SFIELD(sfLoanBrokerID, UINT256, 37,
SField::kSmdPseudoAccount | SField::kSmdDefault)
TYPED_SFIELD(sfLoanID, UINT256, 38)
TYPED_SFIELD(sfReferenceHolding, UINT256, 39)
TYPED_SFIELD(sfObjectID, UINT256, 40)
// number (common)
TYPED_SFIELD(sfNumber, NUMBER, 1)
@@ -265,6 +272,8 @@ TYPED_SFIELD(sfPrice, AMOUNT, 28)
TYPED_SFIELD(sfSignatureReward, AMOUNT, 29)
TYPED_SFIELD(sfMinAccountCreateAmount, AMOUNT, 30)
TYPED_SFIELD(sfLPTokenBalance, AMOUNT, 31)
TYPED_SFIELD(sfFeeAmount, AMOUNT, 32)
TYPED_SFIELD(sfMaxFee, AMOUNT, 33)
// variable length (common)
TYPED_SFIELD(sfPublicKey, VL, 1)
@@ -325,6 +334,11 @@ TYPED_SFIELD(sfIssuingChainDoor, ACCOUNT, 23)
TYPED_SFIELD(sfSubject, ACCOUNT, 24)
TYPED_SFIELD(sfBorrower, ACCOUNT, 25)
TYPED_SFIELD(sfCounterparty, ACCOUNT, 26)
TYPED_SFIELD(sfSponsor, ACCOUNT, 27)
TYPED_SFIELD(sfHighSponsor, ACCOUNT, 28)
TYPED_SFIELD(sfLowSponsor, ACCOUNT, 29)
TYPED_SFIELD(sfCounterpartySponsor, ACCOUNT, 30)
TYPED_SFIELD(sfSponsee, ACCOUNT, 31)
// vector of 256-bit
TYPED_SFIELD(sfIndexes, VECTOR256, 1, SField::kSmdNever)
@@ -389,6 +403,7 @@ UNTYPED_SFIELD(sfRawTransaction, OBJECT, 34)
UNTYPED_SFIELD(sfBatchSigner, OBJECT, 35)
UNTYPED_SFIELD(sfBook, OBJECT, 36)
UNTYPED_SFIELD(sfCounterpartySignature, OBJECT, 37, SField::kSmdDefault, SField::kNotSigning)
UNTYPED_SFIELD(sfSponsorSignature, OBJECT, 38, SField::kSmdDefault, SField::kNotSigning)
// array of objects (common)
// ARRAY/1 is reserved for end of array

View File

@@ -1077,6 +1077,35 @@ TRANSACTION(ttLOAN_PAY, 84, LoanPay,
{sfAmount, SoeRequired, SoeMptSupported},
}))
/** This transaction transfer sponsorship */
#if TRANSACTION_INCLUDE
# include <xrpl/tx/transactors/sponsor/SponsorshipTransfer.h>
#endif
TRANSACTION(ttSPONSORSHIP_TRANSFER, 85, SponsorshipTransfer,
Delegation::Delegable,
featureSponsor,
MayModifyVault,
({
{sfObjectID, SoeOptional},
{sfSponsee, SoeOptional},
}))
/** This transaction create sponsorship object */
#if TRANSACTION_INCLUDE
# include <xrpl/tx/transactors/sponsor/SponsorshipSet.h>
#endif
TRANSACTION(ttSPONSORSHIP_SET, 86, SponsorshipSet,
Delegation::Delegable,
featureSponsor,
NoPriv,
({
{sfCounterpartySponsor, SoeOptional},
{sfSponsee, SoeOptional},
{sfFeeAmount, SoeOptional},
{sfMaxFee, SoeOptional},
{sfRemainingOwnerCount, SoeOptional},
}))
/** This system-generated transaction type is used to update the status of the various amendments.
For details, see: https://xrpl.org/amendments.html

View File

@@ -206,7 +206,7 @@ sha512Half(Args const&... args)
sha512_half_hasher h;
using beast::hash_append;
hash_append(h, args...);
return static_cast<sha512_half_hasher::result_type>(h);
return static_cast<typename sha512_half_hasher::result_type>(h);
}
/** Returns the SHA512-Half of a series of objects.
@@ -222,7 +222,7 @@ sha512HalfS(Args const&... args)
sha512_half_hasher_s h;
using beast::hash_append;
hash_append(h, args...);
return static_cast<sha512_half_hasher_s::result_type>(h);
return static_cast<typename sha512_half_hasher_s::result_type>(h);
}
} // namespace xrpl

View File

@@ -552,6 +552,9 @@ JSS(source_account); // in: PathRequest, RipplePathFind
JSS(source_amount); // in: PathRequest, RipplePathFind
JSS(source_currencies); // in: PathRequest, RipplePathFind
JSS(source_tag); // out: AccountChannels
JSS(sponsee); // in: LedgerEntry
JSS(sponsor); // in: LedgerEntry
JSS(sponsored); // in: AccountObjects
JSS(stand_alone); // out: NetworkOPs
JSS(standard_deviation); // out: get_aggregate_price
JSS(start); // in: TxHistory

View File

@@ -447,6 +447,78 @@ public:
return this->sle_->isFieldPresent(sfFirstNFTokenSequence);
}
/**
* @brief Get sfSponsoredOwnerCount (SoeDefault)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_UINT32::type::value_type>
getSponsoredOwnerCount() const
{
if (hasSponsoredOwnerCount())
return this->sle_->at(sfSponsoredOwnerCount);
return std::nullopt;
}
/**
* @brief Check if sfSponsoredOwnerCount is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasSponsoredOwnerCount() const
{
return this->sle_->isFieldPresent(sfSponsoredOwnerCount);
}
/**
* @brief Get sfSponsoringOwnerCount (SoeDefault)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_UINT32::type::value_type>
getSponsoringOwnerCount() const
{
if (hasSponsoringOwnerCount())
return this->sle_->at(sfSponsoringOwnerCount);
return std::nullopt;
}
/**
* @brief Check if sfSponsoringOwnerCount is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasSponsoringOwnerCount() const
{
return this->sle_->isFieldPresent(sfSponsoringOwnerCount);
}
/**
* @brief Get sfSponsoringAccountCount (SoeDefault)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_UINT32::type::value_type>
getSponsoringAccountCount() const
{
if (hasSponsoringAccountCount())
return this->sle_->at(sfSponsoringAccountCount);
return std::nullopt;
}
/**
* @brief Check if sfSponsoringAccountCount is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasSponsoringAccountCount() const
{
return this->sle_->isFieldPresent(sfSponsoringAccountCount);
}
/**
* @brief Get sfAMMID (SoeOptional)
* @return The field value, or std::nullopt if not present.
@@ -786,6 +858,39 @@ public:
return *this;
}
/**
* @brief Set sfSponsoredOwnerCount (SoeDefault)
* @return Reference to this builder for method chaining.
*/
AccountRootBuilder&
setSponsoredOwnerCount(std::decay_t<typename SF_UINT32::type::value_type> const& value)
{
object_[sfSponsoredOwnerCount] = value;
return *this;
}
/**
* @brief Set sfSponsoringOwnerCount (SoeDefault)
* @return Reference to this builder for method chaining.
*/
AccountRootBuilder&
setSponsoringOwnerCount(std::decay_t<typename SF_UINT32::type::value_type> const& value)
{
object_[sfSponsoringOwnerCount] = value;
return *this;
}
/**
* @brief Set sfSponsoringAccountCount (SoeDefault)
* @return Reference to this builder for method chaining.
*/
AccountRootBuilder&
setSponsoringAccountCount(std::decay_t<typename SF_UINT32::type::value_type> const& value)
{
object_[sfSponsoringAccountCount] = value;
return *this;
}
/**
* @brief Set sfAMMID (SoeOptional)
* @return Reference to this builder for method chaining.

View File

@@ -243,6 +243,54 @@ public:
{
return this->sle_->isFieldPresent(sfHighQualityOut);
}
/**
* @brief Get sfHighSponsor (SoeOptional)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_ACCOUNT::type::value_type>
getHighSponsor() const
{
if (hasHighSponsor())
return this->sle_->at(sfHighSponsor);
return std::nullopt;
}
/**
* @brief Check if sfHighSponsor is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasHighSponsor() const
{
return this->sle_->isFieldPresent(sfHighSponsor);
}
/**
* @brief Get sfLowSponsor (SoeOptional)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_ACCOUNT::type::value_type>
getLowSponsor() const
{
if (hasLowSponsor())
return this->sle_->at(sfLowSponsor);
return std::nullopt;
}
/**
* @brief Check if sfLowSponsor is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasLowSponsor() const
{
return this->sle_->isFieldPresent(sfLowSponsor);
}
};
/**
@@ -410,6 +458,28 @@ public:
return *this;
}
/**
* @brief Set sfHighSponsor (SoeOptional)
* @return Reference to this builder for method chaining.
*/
RippleStateBuilder&
setHighSponsor(std::decay_t<typename SF_ACCOUNT::type::value_type> const& value)
{
object_[sfHighSponsor] = value;
return *this;
}
/**
* @brief Set sfLowSponsor (SoeOptional)
* @return Reference to this builder for method chaining.
*/
RippleStateBuilder&
setLowSponsor(std::decay_t<typename SF_ACCOUNT::type::value_type> const& value)
{
object_[sfLowSponsor] = value;
return *this;
}
/**
* @brief Build and return the completed RippleState wrapper.
* @param index The ledger entry index.

View File

@@ -0,0 +1,344 @@
// This file is auto-generated. Do not edit.
#pragma once
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/STParsedJSON.h>
#include <xrpl/protocol/jss.h>
#include <xrpl/protocol_autogen/LedgerEntryBase.h>
#include <xrpl/protocol_autogen/LedgerEntryBuilderBase.h>
#include <xrpl/json/json_value.h>
#include <stdexcept>
#include <optional>
namespace xrpl::ledger_entries {
class SponsorshipBuilder;
/**
* @brief Ledger Entry: Sponsorship
*
* Type: ltSPONSORSHIP (0x0090)
* RPC Name: sponsorship
*
* Immutable wrapper around SLE providing type-safe field access.
* Use SponsorshipBuilder to construct new ledger entries.
*/
class Sponsorship : public LedgerEntryBase
{
public:
static constexpr LedgerEntryType entryType = ltSPONSORSHIP;
/**
* @brief Construct a Sponsorship ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit Sponsorship(SLE::const_pointer sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
if (sle_->getType() != entryType)
{
throw std::runtime_error("Invalid ledger entry type for Sponsorship");
}
}
// Ledger entry-specific field getters
/**
* @brief Get sfPreviousTxnID (SoeRequired)
* @return The field value.
*/
[[nodiscard]]
SF_UINT256::type::value_type
getPreviousTxnID() const
{
return this->sle_->at(sfPreviousTxnID);
}
/**
* @brief Get sfPreviousTxnLgrSeq (SoeRequired)
* @return The field value.
*/
[[nodiscard]]
SF_UINT32::type::value_type
getPreviousTxnLgrSeq() const
{
return this->sle_->at(sfPreviousTxnLgrSeq);
}
/**
* @brief Get sfOwner (SoeRequired)
* @return The field value.
*/
[[nodiscard]]
SF_ACCOUNT::type::value_type
getOwner() const
{
return this->sle_->at(sfOwner);
}
/**
* @brief Get sfSponsee (SoeRequired)
* @return The field value.
*/
[[nodiscard]]
SF_ACCOUNT::type::value_type
getSponsee() const
{
return this->sle_->at(sfSponsee);
}
/**
* @brief Get sfFeeAmount (SoeOptional)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_AMOUNT::type::value_type>
getFeeAmount() const
{
if (hasFeeAmount())
return this->sle_->at(sfFeeAmount);
return std::nullopt;
}
/**
* @brief Check if sfFeeAmount is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasFeeAmount() const
{
return this->sle_->isFieldPresent(sfFeeAmount);
}
/**
* @brief Get sfMaxFee (SoeOptional)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_AMOUNT::type::value_type>
getMaxFee() const
{
if (hasMaxFee())
return this->sle_->at(sfMaxFee);
return std::nullopt;
}
/**
* @brief Check if sfMaxFee is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasMaxFee() const
{
return this->sle_->isFieldPresent(sfMaxFee);
}
/**
* @brief Get sfRemainingOwnerCount (SoeDefault)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_UINT32::type::value_type>
getRemainingOwnerCount() const
{
if (hasRemainingOwnerCount())
return this->sle_->at(sfRemainingOwnerCount);
return std::nullopt;
}
/**
* @brief Check if sfRemainingOwnerCount is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasRemainingOwnerCount() const
{
return this->sle_->isFieldPresent(sfRemainingOwnerCount);
}
/**
* @brief Get sfOwnerNode (SoeRequired)
* @return The field value.
*/
[[nodiscard]]
SF_UINT64::type::value_type
getOwnerNode() const
{
return this->sle_->at(sfOwnerNode);
}
/**
* @brief Get sfSponseeNode (SoeRequired)
* @return The field value.
*/
[[nodiscard]]
SF_UINT64::type::value_type
getSponseeNode() const
{
return this->sle_->at(sfSponseeNode);
}
};
/**
* @brief Builder for Sponsorship ledger entries.
*
* Provides a fluent interface for constructing ledger entries with method chaining.
* Uses STObject internally for flexible ledger entry construction.
* Inherits common field setters from LedgerEntryBuilderBase.
*/
class SponsorshipBuilder : public LedgerEntryBuilderBase<SponsorshipBuilder>
{
public:
/**
* @brief Construct a new SponsorshipBuilder with required fields.
* @param previousTxnID The sfPreviousTxnID field value.
* @param previousTxnLgrSeq The sfPreviousTxnLgrSeq field value.
* @param owner The sfOwner field value.
* @param sponsee The sfSponsee field value.
* @param ownerNode The sfOwnerNode field value.
* @param sponseeNode The sfSponseeNode field value.
*/
SponsorshipBuilder(std::decay_t<typename SF_UINT256::type::value_type> const& previousTxnID,std::decay_t<typename SF_UINT32::type::value_type> const& previousTxnLgrSeq,std::decay_t<typename SF_ACCOUNT::type::value_type> const& owner,std::decay_t<typename SF_ACCOUNT::type::value_type> const& sponsee,std::decay_t<typename SF_UINT64::type::value_type> const& ownerNode,std::decay_t<typename SF_UINT64::type::value_type> const& sponseeNode)
: LedgerEntryBuilderBase<SponsorshipBuilder>(ltSPONSORSHIP)
{
setPreviousTxnID(previousTxnID);
setPreviousTxnLgrSeq(previousTxnLgrSeq);
setOwner(owner);
setSponsee(sponsee);
setOwnerNode(ownerNode);
setSponseeNode(sponseeNode);
}
/**
* @brief Construct a SponsorshipBuilder from an existing SLE object.
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
SponsorshipBuilder(SLE::const_pointer sle)
{
if (sle->at(sfLedgerEntryType) != ltSPONSORSHIP)
{
throw std::runtime_error("Invalid ledger entry type for Sponsorship");
}
object_ = *sle;
}
/** @brief Ledger entry-specific field setters */
/**
* @brief Set sfPreviousTxnID (SoeRequired)
* @return Reference to this builder for method chaining.
*/
SponsorshipBuilder&
setPreviousTxnID(std::decay_t<typename SF_UINT256::type::value_type> const& value)
{
object_[sfPreviousTxnID] = value;
return *this;
}
/**
* @brief Set sfPreviousTxnLgrSeq (SoeRequired)
* @return Reference to this builder for method chaining.
*/
SponsorshipBuilder&
setPreviousTxnLgrSeq(std::decay_t<typename SF_UINT32::type::value_type> const& value)
{
object_[sfPreviousTxnLgrSeq] = value;
return *this;
}
/**
* @brief Set sfOwner (SoeRequired)
* @return Reference to this builder for method chaining.
*/
SponsorshipBuilder&
setOwner(std::decay_t<typename SF_ACCOUNT::type::value_type> const& value)
{
object_[sfOwner] = value;
return *this;
}
/**
* @brief Set sfSponsee (SoeRequired)
* @return Reference to this builder for method chaining.
*/
SponsorshipBuilder&
setSponsee(std::decay_t<typename SF_ACCOUNT::type::value_type> const& value)
{
object_[sfSponsee] = value;
return *this;
}
/**
* @brief Set sfFeeAmount (SoeOptional)
* @return Reference to this builder for method chaining.
*/
SponsorshipBuilder&
setFeeAmount(std::decay_t<typename SF_AMOUNT::type::value_type> const& value)
{
object_[sfFeeAmount] = value;
return *this;
}
/**
* @brief Set sfMaxFee (SoeOptional)
* @return Reference to this builder for method chaining.
*/
SponsorshipBuilder&
setMaxFee(std::decay_t<typename SF_AMOUNT::type::value_type> const& value)
{
object_[sfMaxFee] = value;
return *this;
}
/**
* @brief Set sfRemainingOwnerCount (SoeDefault)
* @return Reference to this builder for method chaining.
*/
SponsorshipBuilder&
setRemainingOwnerCount(std::decay_t<typename SF_UINT32::type::value_type> const& value)
{
object_[sfRemainingOwnerCount] = value;
return *this;
}
/**
* @brief Set sfOwnerNode (SoeRequired)
* @return Reference to this builder for method chaining.
*/
SponsorshipBuilder&
setOwnerNode(std::decay_t<typename SF_UINT64::type::value_type> const& value)
{
object_[sfOwnerNode] = value;
return *this;
}
/**
* @brief Set sfSponseeNode (SoeRequired)
* @return Reference to this builder for method chaining.
*/
SponsorshipBuilder&
setSponseeNode(std::decay_t<typename SF_UINT64::type::value_type> const& value)
{
object_[sfSponseeNode] = value;
return *this;
}
/**
* @brief Build and return the completed Sponsorship wrapper.
* @param index The ledger entry index.
* @return The constructed ledger entry wrapper.
*/
Sponsorship
build(uint256 const& index)
{
return Sponsorship{std::make_shared<SLE>(std::move(object_), index)};
}
};
} // namespace xrpl::ledger_entries

View File

@@ -0,0 +1,290 @@
// This file is auto-generated. Do not edit.
#pragma once
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/STParsedJSON.h>
#include <xrpl/protocol/jss.h>
#include <xrpl/protocol_autogen/TransactionBase.h>
#include <xrpl/protocol_autogen/TransactionBuilderBase.h>
#include <xrpl/json/json_value.h>
#include <stdexcept>
#include <optional>
namespace xrpl::transactions {
class SponsorshipSetBuilder;
/**
* @brief Transaction: SponsorshipSet
*
* Type: ttSPONSORSHIP_SET (86)
* Delegable: Delegation::Delegable
* Amendment: featureSponsor
* Privileges: NoPriv
*
* Immutable wrapper around STTx providing type-safe field access.
* Use SponsorshipSetBuilder to construct new transactions.
*/
class SponsorshipSet : public TransactionBase
{
public:
static constexpr xrpl::TxType txType = ttSPONSORSHIP_SET;
/**
* @brief Construct a SponsorshipSet transaction wrapper from an existing STTx object.
* @throws std::runtime_error if the transaction type doesn't match.
*/
explicit SponsorshipSet(std::shared_ptr<STTx const> tx)
: TransactionBase(std::move(tx))
{
// Verify transaction type
if (tx_->getTxnType() != txType)
{
throw std::runtime_error("Invalid transaction type for SponsorshipSet");
}
}
// Transaction-specific field getters
/**
* @brief Get sfCounterpartySponsor (SoeOptional)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_ACCOUNT::type::value_type>
getCounterpartySponsor() const
{
if (hasCounterpartySponsor())
{
return this->tx_->at(sfCounterpartySponsor);
}
return std::nullopt;
}
/**
* @brief Check if sfCounterpartySponsor is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasCounterpartySponsor() const
{
return this->tx_->isFieldPresent(sfCounterpartySponsor);
}
/**
* @brief Get sfSponsee (SoeOptional)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_ACCOUNT::type::value_type>
getSponsee() const
{
if (hasSponsee())
{
return this->tx_->at(sfSponsee);
}
return std::nullopt;
}
/**
* @brief Check if sfSponsee is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasSponsee() const
{
return this->tx_->isFieldPresent(sfSponsee);
}
/**
* @brief Get sfFeeAmount (SoeOptional)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_AMOUNT::type::value_type>
getFeeAmount() const
{
if (hasFeeAmount())
{
return this->tx_->at(sfFeeAmount);
}
return std::nullopt;
}
/**
* @brief Check if sfFeeAmount is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasFeeAmount() const
{
return this->tx_->isFieldPresent(sfFeeAmount);
}
/**
* @brief Get sfMaxFee (SoeOptional)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_AMOUNT::type::value_type>
getMaxFee() const
{
if (hasMaxFee())
{
return this->tx_->at(sfMaxFee);
}
return std::nullopt;
}
/**
* @brief Check if sfMaxFee is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasMaxFee() const
{
return this->tx_->isFieldPresent(sfMaxFee);
}
/**
* @brief Get sfRemainingOwnerCount (SoeOptional)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_UINT32::type::value_type>
getRemainingOwnerCount() const
{
if (hasRemainingOwnerCount())
{
return this->tx_->at(sfRemainingOwnerCount);
}
return std::nullopt;
}
/**
* @brief Check if sfRemainingOwnerCount is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasRemainingOwnerCount() const
{
return this->tx_->isFieldPresent(sfRemainingOwnerCount);
}
};
/**
* @brief Builder for SponsorshipSet transactions.
*
* Provides a fluent interface for constructing transactions with method chaining.
* Uses STObject internally for flexible transaction construction.
* Inherits common field setters from TransactionBuilderBase.
*/
class SponsorshipSetBuilder : public TransactionBuilderBase<SponsorshipSetBuilder>
{
public:
/**
* @brief Construct a new SponsorshipSetBuilder with required fields.
* @param account The account initiating the transaction.
* @param sequence Optional sequence number for the transaction.
* @param fee Optional fee for the transaction.
*/
SponsorshipSetBuilder(SF_ACCOUNT::type::value_type account,
std::optional<SF_UINT32::type::value_type> sequence = std::nullopt,
std::optional<SF_AMOUNT::type::value_type> fee = std::nullopt
)
: TransactionBuilderBase<SponsorshipSetBuilder>(ttSPONSORSHIP_SET, account, sequence, fee)
{
}
/**
* @brief Construct a SponsorshipSetBuilder from an existing STTx object.
* @param tx The existing transaction to copy from.
* @throws std::runtime_error if the transaction type doesn't match.
*/
SponsorshipSetBuilder(std::shared_ptr<STTx const> tx)
{
if (tx->getTxnType() != ttSPONSORSHIP_SET)
{
throw std::runtime_error("Invalid transaction type for SponsorshipSetBuilder");
}
object_ = *tx;
}
/** @brief Transaction-specific field setters */
/**
* @brief Set sfCounterpartySponsor (SoeOptional)
* @return Reference to this builder for method chaining.
*/
SponsorshipSetBuilder&
setCounterpartySponsor(std::decay_t<typename SF_ACCOUNT::type::value_type> const& value)
{
object_[sfCounterpartySponsor] = value;
return *this;
}
/**
* @brief Set sfSponsee (SoeOptional)
* @return Reference to this builder for method chaining.
*/
SponsorshipSetBuilder&
setSponsee(std::decay_t<typename SF_ACCOUNT::type::value_type> const& value)
{
object_[sfSponsee] = value;
return *this;
}
/**
* @brief Set sfFeeAmount (SoeOptional)
* @return Reference to this builder for method chaining.
*/
SponsorshipSetBuilder&
setFeeAmount(std::decay_t<typename SF_AMOUNT::type::value_type> const& value)
{
object_[sfFeeAmount] = value;
return *this;
}
/**
* @brief Set sfMaxFee (SoeOptional)
* @return Reference to this builder for method chaining.
*/
SponsorshipSetBuilder&
setMaxFee(std::decay_t<typename SF_AMOUNT::type::value_type> const& value)
{
object_[sfMaxFee] = value;
return *this;
}
/**
* @brief Set sfRemainingOwnerCount (SoeOptional)
* @return Reference to this builder for method chaining.
*/
SponsorshipSetBuilder&
setRemainingOwnerCount(std::decay_t<typename SF_UINT32::type::value_type> const& value)
{
object_[sfRemainingOwnerCount] = value;
return *this;
}
/**
* @brief Build and return the SponsorshipSet wrapper.
* @param publicKey The public key for signing.
* @param secretKey The secret key for signing.
* @return The constructed transaction wrapper.
*/
SponsorshipSet
build(PublicKey const& publicKey, SecretKey const& secretKey)
{
sign(publicKey, secretKey);
return SponsorshipSet{std::make_shared<STTx>(std::move(object_))};
}
};
} // namespace xrpl::transactions

View File

@@ -0,0 +1,179 @@
// This file is auto-generated. Do not edit.
#pragma once
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/STParsedJSON.h>
#include <xrpl/protocol/jss.h>
#include <xrpl/protocol_autogen/TransactionBase.h>
#include <xrpl/protocol_autogen/TransactionBuilderBase.h>
#include <xrpl/json/json_value.h>
#include <stdexcept>
#include <optional>
namespace xrpl::transactions {
class SponsorshipTransferBuilder;
/**
* @brief Transaction: SponsorshipTransfer
*
* Type: ttSPONSORSHIP_TRANSFER (85)
* Delegable: Delegation::Delegable
* Amendment: featureSponsor
* Privileges: MayModifyVault
*
* Immutable wrapper around STTx providing type-safe field access.
* Use SponsorshipTransferBuilder to construct new transactions.
*/
class SponsorshipTransfer : public TransactionBase
{
public:
static constexpr xrpl::TxType txType = ttSPONSORSHIP_TRANSFER;
/**
* @brief Construct a SponsorshipTransfer transaction wrapper from an existing STTx object.
* @throws std::runtime_error if the transaction type doesn't match.
*/
explicit SponsorshipTransfer(std::shared_ptr<STTx const> tx)
: TransactionBase(std::move(tx))
{
// Verify transaction type
if (tx_->getTxnType() != txType)
{
throw std::runtime_error("Invalid transaction type for SponsorshipTransfer");
}
}
// Transaction-specific field getters
/**
* @brief Get sfObjectID (SoeOptional)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_UINT256::type::value_type>
getObjectID() const
{
if (hasObjectID())
{
return this->tx_->at(sfObjectID);
}
return std::nullopt;
}
/**
* @brief Check if sfObjectID is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasObjectID() const
{
return this->tx_->isFieldPresent(sfObjectID);
}
/**
* @brief Get sfSponsee (SoeOptional)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_ACCOUNT::type::value_type>
getSponsee() const
{
if (hasSponsee())
{
return this->tx_->at(sfSponsee);
}
return std::nullopt;
}
/**
* @brief Check if sfSponsee is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasSponsee() const
{
return this->tx_->isFieldPresent(sfSponsee);
}
};
/**
* @brief Builder for SponsorshipTransfer transactions.
*
* Provides a fluent interface for constructing transactions with method chaining.
* Uses STObject internally for flexible transaction construction.
* Inherits common field setters from TransactionBuilderBase.
*/
class SponsorshipTransferBuilder : public TransactionBuilderBase<SponsorshipTransferBuilder>
{
public:
/**
* @brief Construct a new SponsorshipTransferBuilder with required fields.
* @param account The account initiating the transaction.
* @param sequence Optional sequence number for the transaction.
* @param fee Optional fee for the transaction.
*/
SponsorshipTransferBuilder(SF_ACCOUNT::type::value_type account,
std::optional<SF_UINT32::type::value_type> sequence = std::nullopt,
std::optional<SF_AMOUNT::type::value_type> fee = std::nullopt
)
: TransactionBuilderBase<SponsorshipTransferBuilder>(ttSPONSORSHIP_TRANSFER, account, sequence, fee)
{
}
/**
* @brief Construct a SponsorshipTransferBuilder from an existing STTx object.
* @param tx The existing transaction to copy from.
* @throws std::runtime_error if the transaction type doesn't match.
*/
SponsorshipTransferBuilder(std::shared_ptr<STTx const> tx)
{
if (tx->getTxnType() != ttSPONSORSHIP_TRANSFER)
{
throw std::runtime_error("Invalid transaction type for SponsorshipTransferBuilder");
}
object_ = *tx;
}
/** @brief Transaction-specific field setters */
/**
* @brief Set sfObjectID (SoeOptional)
* @return Reference to this builder for method chaining.
*/
SponsorshipTransferBuilder&
setObjectID(std::decay_t<typename SF_UINT256::type::value_type> const& value)
{
object_[sfObjectID] = value;
return *this;
}
/**
* @brief Set sfSponsee (SoeOptional)
* @return Reference to this builder for method chaining.
*/
SponsorshipTransferBuilder&
setSponsee(std::decay_t<typename SF_ACCOUNT::type::value_type> const& value)
{
object_[sfSponsee] = value;
return *this;
}
/**
* @brief Build and return the SponsorshipTransfer wrapper.
* @param publicKey The public key for signing.
* @param secretKey The secret key for signing.
* @return The constructed transaction wrapper.
*/
SponsorshipTransfer
build(PublicKey const& publicKey, SecretKey const& secretKey)
{
sign(publicKey, secretKey);
return SponsorshipTransfer{std::make_shared<STTx>(std::move(object_))};
}
};
} // namespace xrpl::transactions

View File

@@ -25,7 +25,7 @@ public:
static constexpr auto kDefaultCacheTargetSize = 0;
using key_type = uint256;
using clock_type = CacheType::clock_type;
using clock_type = typename CacheType::clock_type;
/** Construct the cache.

View File

@@ -2,6 +2,7 @@
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/beast/utility/WrappedSink.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h>
#include <xrpl/protocol/Permissions.h>
#include <xrpl/protocol/XRPAmount.h>
#include <xrpl/tx/ApplyContext.h>
@@ -109,6 +110,20 @@ struct PreflightResult;
// Needed for preflight specialization
class Change;
enum class FeePayerType {
Account,
Delegate,
SponsorCoSigned,
SponsorPreFunded,
};
struct FeePayer
{
Keylet entry;
SF_AMOUNT const& balanceField;
FeePayerType type{FeePayerType::Account};
};
class Transactor
{
protected:
@@ -280,6 +295,9 @@ public:
return T::checkGranularSemantics(view, tx, heldGranularPermissions);
}
static NotTEC
checkSponsor(ReadView const& view, STTx const& tx);
/////////////////////////////////////////////////////
// Interface used by AccountDelete
@@ -418,6 +436,9 @@ private:
std::pair<TER, XRPAmount>
reset(XRPAmount fee);
static FeePayer
getFeePayer(ReadView const& view, STTx const& tx);
TER
consumeSeqProxy(SLE::pointer const& sleAccount);

View File

@@ -14,6 +14,7 @@
#include <xrpl/tx/invariants/NFTInvariant.h>
#include <xrpl/tx/invariants/PermissionedDEXInvariant.h>
#include <xrpl/tx/invariants/PermissionedDomainInvariant.h>
#include <xrpl/tx/invariants/SponsorshipInvariant.h>
#include <xrpl/tx/invariants/VaultInvariant.h>
#include <cstdint>
@@ -415,7 +416,9 @@ using InvariantChecks = std::tuple<
ValidVault,
ValidMPTPayment,
ValidAmounts,
ValidMPTTransfer>;
ValidMPTTransfer,
SponsorshipOwnerCountsMatch,
SponsorshipAccountCountMatchesField>;
/**
* @brief get a tuple of all invariant checks

View File

@@ -0,0 +1,56 @@
#pragma once
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TER.h>
#include <cstdint>
namespace xrpl {
/**
* @brief Invariant: Sponsored owner counts are balanced.
*
* The following check is made for every transaction:
* - The sum of all per-account deltas of `sfSponsoredOwnerCount` equals
* the sum of all per-account deltas of `sfSponsoringOwnerCount`.
* - Account OwnerCount must be greater than or equal to SponsoredOwnerCount.
*/
class SponsorshipOwnerCountsMatch
{
std::int64_t deltaSponsoredOwnerCount_ = 0;
std::int64_t deltaSponsoringOwnerCount_ = 0;
std::int64_t deltaSponsoredObjectOwnerCount_ = 0;
std::uint64_t ownerCountBelowSponsored_ = 0;
public:
void
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
[[nodiscard]] bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&) const;
};
/**
* @brief Invariant: Sponsoring account relationships tracked consistently.
*
* The following check is made for every transaction:
* - The net delta of `sfSponsoringAccountCount` across all accounts equals
* the net delta of the count of ltACCOUNT_ROOT entries having
* `sfSponsor` present (presence transitions only: add/remove).
*/
class SponsorshipAccountCountMatchesField
{
std::int64_t deltaSponsoringAccountCount_ = 0;
std::int64_t deltaSponsorFieldPresence_ = 0;
public:
void
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
[[nodiscard]] bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&) const;
};
} // namespace xrpl

View File

@@ -104,7 +104,10 @@ public:
send(Args&&... args)
{
return accountSend(
std::forward<Args>(args)..., WaiveTransferFee::Yes, AllowMPTOverflow::Yes);
std::forward<Args>(args)...,
SLE::pointer(),
WaiveTransferFee::Yes,
AllowMPTOverflow::Yes);
}
[[nodiscard]] bool

View File

@@ -224,7 +224,8 @@ template <typename... Args>
TER
TOffer<TIn, TOut>::send(Args&&... args)
{
return accountSend(std::forward<Args>(args)..., WaiveTransferFee::No, AllowMPTOverflow::Yes);
return accountSend(
std::forward<Args>(args)..., SLE::pointer(), WaiveTransferFee::No, AllowMPTOverflow::Yes);
}
template <StepAmount TIn, StepAmount TOut>

View File

@@ -3,6 +3,7 @@
#include <xrpl/ledger/PaymentSandbox.h>
#include <xrpl/protocol/IOUAmount.h>
#include <xrpl/protocol/XRPAmount.h>
#include <xrpl/tx/paths/detail/AmountSpec.h>
#include <boost/container/flat_map.hpp>

View File

@@ -9,6 +9,7 @@
#include <xrpl/protocol/IOUAmount.h>
#include <xrpl/protocol/XRPAmount.h>
#include <xrpl/tx/paths/Flow.h>
#include <xrpl/tx/paths/detail/AmountSpec.h>
#include <xrpl/tx/paths/detail/FlatSets.h>
#include <xrpl/tx/paths/detail/FlowDebugInfo.h>
#include <xrpl/tx/paths/detail/Steps.h>

View File

@@ -100,6 +100,7 @@ public:
static std::tuple<TER, STAmount, STAmount, std::optional<STAmount>>
equalWithdrawTokens(
Sandbox& view,
STTx const& tx,
SLE const& ammSle,
AccountID const account,
AccountID const& ammAccount,
@@ -134,6 +135,7 @@ public:
static std::tuple<TER, STAmount, STAmount, std::optional<STAmount>>
withdraw(
Sandbox& view,
STTx const& tx,
SLE const& ammSle,
AccountID const& ammAccount,
AccountID const& account,
@@ -177,6 +179,7 @@ private:
std::pair<TER, STAmount>
withdraw(
Sandbox& view,
STTx const& tx,
SLE const& ammSle,
AccountID const& ammAccount,
STAmount const& amountBalance,
@@ -202,6 +205,7 @@ private:
std::pair<TER, STAmount>
equalWithdrawTokens(
Sandbox& view,
STTx const& tx,
SLE const& ammSle,
AccountID const& ammAccount,
STAmount const& amountBalance,
@@ -227,6 +231,7 @@ private:
std::pair<TER, STAmount>
equalWithdrawLimit(
Sandbox& view,
STTx const& tx,
SLE const& ammSle,
AccountID const& ammAccount,
STAmount const& amountBalance,
@@ -249,6 +254,7 @@ private:
std::pair<TER, STAmount>
singleWithdraw(
Sandbox& view,
STTx const& tx,
SLE const& ammSle,
AccountID const& ammAccount,
STAmount const& amountBalance,
@@ -270,6 +276,7 @@ private:
std::pair<TER, STAmount>
singleWithdrawTokens(
Sandbox& view,
STTx const& tx,
SLE const& ammSle,
AccountID const& ammAccount,
STAmount const& amountBalance,
@@ -292,6 +299,7 @@ private:
std::pair<TER, STAmount>
singleWithdrawEPrice(
Sandbox& view,
STTx const& tx,
SLE const& ammSle,
AccountID const& ammAccount,
STAmount const& amountBalance,

View File

@@ -22,6 +22,12 @@ public:
{
}
static uint32_t
calculateOracleReserve(std::size_t count)
{
return count > 5 ? 2 : 1;
}
static NotTEC
preflight(PreflightContext const& ctx);

View File

@@ -0,0 +1,43 @@
#pragma once
#include <xrpl/tx/Transactor.h>
namespace xrpl {
class SponsorshipSet : public Transactor
{
public:
static constexpr auto kConsequencesFactory = ConsequencesFactoryType::Normal;
explicit SponsorshipSet(ApplyContext& ctx) : Transactor(ctx)
{
}
static std::uint32_t
getFlagsMask(PreflightContext const& ctx);
static NotTEC
preflight(PreflightContext const& ctx);
static TER
preclaim(PreclaimContext const& ctx);
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -0,0 +1,43 @@
#pragma once
#include <xrpl/tx/Transactor.h>
namespace xrpl {
class SponsorshipTransfer : public Transactor
{
public:
static constexpr auto kConsequencesFactory = ConsequencesFactoryType::Normal;
explicit SponsorshipTransfer(ApplyContext& ctx) : Transactor(ctx)
{
}
static std::uint32_t
getFlagsMask(PreflightContext const& ctx);
static NotTEC
preflight(PreflightContext const& ctx);
static TER
preclaim(PreclaimContext const& ctx);
TER
doApply() override;
void
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
STTx const& tx,
TER result,
XRPAmount fee,
ReadView const& view,
beast::Journal const& j) override;
};
} // namespace xrpl

View File

@@ -63,7 +63,7 @@ public:
beast::Journal const& j) override;
static std::expected<MPTID, TER>
create(ApplyView& view, beast::Journal journal, MPTCreateArgs const& args);
create(ApplyView& view, STTx const& tx, beast::Journal journal, MPTCreateArgs const& args);
};
} // namespace xrpl

View File

@@ -6,10 +6,10 @@ This directory contains all files needed to build RPM and Debian packages for `x
```
package/
build_pkg.sh Staging and build script (called by the CMake `package` target and CI)
build_pkg.sh Staging and build script (called by CMake targets and CI)
rpm/
xrpld.spec RPM spec
debian/ Debian control files (control, rules, copyright, xrpld.docs, xrpld.links, source/format)
xrpld.spec RPM spec (xrpld_version/pkg_release passed via rpmbuild --define)
debian/ Debian control files (control, rules, install, links, conffiles, ...)
shared/
xrpld.service systemd unit file (used by both RPM and DEB)
xrpld.sysusers sysusers.d config (used by both RPM and DEB)
@@ -21,19 +21,21 @@ package/
Packaging targets and their container images are declared in
[`.github/scripts/strategy-matrix/linux.json`](../.github/scripts/strategy-matrix/linux.json)
under `package_configs`, one entry per distro. Today only `linux/amd64` is
emitted. Each entry pins its full container image in an `image` field; to move
to a new image, edit that field and both CI and local builds pick it up. The
package format (deb or rpm) is inferred at build time from the container's
package manager (`apt-get` -> deb, `dnf`/`yum` -> rpm).
inside `package_configs` configurations. Today only
`linux/amd64` is emitted. The package format
(deb or rpm) is inferred at build time from the container's package manager
(`apt-get` -> deb, `dnf`/`yum` -> rpm). The image tag is composed as
`ghcr.io/xrplf/xrpld/packaging-<distro>:sha-<git_sha>`
the same scheme used by `reusable-build-test.yml`. Bump `image_sha` in
`linux.json` and both CI and local builds pick up the new image with no
workflow edits.
| Package type | Image (`package_configs.<distro>[].image` in `linux.json`) | Tools required |
| ------------ | ---------------------------------------------------------- | --------------------------------------------------- |
| RPM | `ghcr.io/xrplf/xrpld/packaging-rhel:sha-<sha>` | `rpmbuild` |
| DEB | `ghcr.io/xrplf/xrpld/packaging-debian:sha-<sha>` | `dpkg-buildpackage`, debhelper with compat level 13 |
| Package type | Image (derived from `linux.json`) | Tool required |
| ------------ | ---------------------------------------------------- | --------------------------------------------------------------- |
| RPM | `ghcr.io/xrplf/xrpld/packaging-rhel:sha-<git_sha>` | `rpmbuild` |
| DEB | `ghcr.io/xrplf/xrpld/packaging-debian:sha-<git_sha>` | `dpkg-buildpackage`, `debhelper (>= 13)`, `dh-sequence-systemd` |
To print the full packaging matrix (artifact names and images) for the current
`linux.json`:
To print the exact image tags for the current `linux.json`:
```bash
./.github/scripts/strategy-matrix/generate.py --packaging
@@ -44,13 +46,12 @@ To print the full packaging matrix (artifact names and images) for the current
### Via CI
Caller workflows (`on-pr.yml`, `on-tag.yml`, `on-trigger.yml`) call
`reusable-package.yml`. That workflow generates its own packaging matrix from
`package_configs` in `linux.json` (via `generate.py --packaging`) and fans out
one job per distro. Each job downloads the pre-built `xrpld` binary artifact and
runs in that distro's container, so the package format follows from the
container's package manager. The packaging script derives the package version
from the downloaded binary's `xrpld --version` output; no CMake configure or
build step is needed inside the packaging job.
`reusable-strategy-matrix.yml` with `mode: packaging` to generate the matrix of
`{artifact_name, os}` entries, then fan out to
`reusable-package.yml` per entry. That workflow downloads the pre-built `xrpld`
binary artifact, detects the package format from the container, and calls
`build_pkg.sh` directly — no CMake configure or build step is needed inside
the packaging job.
### Locally (mirrors CI)
@@ -59,19 +60,22 @@ inside the same container CI uses. The image tag is derived from `linux.json`
so you don't need to hardcode a SHA.
```bash
# From the repo root. Each distro's container image is the `image` field of its
# package_configs entry in linux.json; the package format is inferred from the
# container's package manager. Example for the rpm-producing image (use
# .package_configs.debian[0].image for the deb image):
IMAGE=$(jq -r '.package_configs.rhel[0].image' .github/scripts/strategy-matrix/linux.json)
# From the repo root. Pick any image flagged with `"package": true` in
# linux.json; the package format is inferred from the container's package
# manager. Example for the rpm-producing image:
IMAGE=$(jq -r '
.os | map(select(.package == true))[0] |
"ghcr.io/xrplf/ci/\(.distro_name)-\(.distro_version):\(.compiler_name)-\(.compiler_version)-sha-\(.image_sha)"
' .github/scripts/strategy-matrix/linux.json)
VERSION=2.4.0-local
PKG_RELEASE=1
docker run --rm \
-v "$(pwd):/src" \
-w /src \
"${IMAGE}" \
./package/build_pkg.sh --pkg-release "${PKG_RELEASE}"
"$IMAGE" \
./package/build_pkg.sh --pkg-version "$VERSION" --pkg-release "$PKG_RELEASE"
# Output:
# build/debbuild/*.deb (DEB + dbgsym .ddeb)
@@ -87,73 +91,41 @@ needed, but the host toolchain replaces the pinned CI image:
```bash
cmake \
-Dxrpld=ON \
-Dpkg_release=1 \
-Dxrpld_version=2.4.0-local \
-Dtests=OFF \
..
cmake --build . --target package # deb on Debian/Ubuntu, rpm on RHEL
```
The `cmake/XrplPackaging.cmake` module defines the `package` target only if at
least one of `rpmbuild` / `dpkg-buildpackage` is present; `build_pkg.sh` then
infers the package format from the host's package manager. The packaging script
installs to FHS-standard paths (`/usr/bin`, `/etc/xrpld`, etc.) regardless of
The `cmake/XrplPackaging.cmake` module defines the target only if at least one
of `rpmbuild` / `dpkg-buildpackage` is present; `build_pkg.sh` then infers the
package format from the host's package manager. The packaging script installs
to FHS-standard paths (`/usr/bin`, `/etc/xrpld`, etc.) regardless of
`CMAKE_INSTALL_PREFIX`.
The package version is not a CMake input on this path: `build_pkg.sh` derives it
from the just-built `xrpld` binary's `xrpld --version` output. The package
release defaults to 1 and is overridable with `-Dpkg_release=N`.
## How `build_pkg.sh` works
`build_pkg.sh` derives the `xrpld` software version from
`${BUILD_DIR}/xrpld --version` in both package formats.
`build_pkg.sh` accepts long-form flags, each of which can also be set via an
environment variable. Flags override env vars; env vars override the built-in
defaults. Run `./package/build_pkg.sh --help` for the same table:
The binary's version is already SemVer-validated by `BuildInfo`.
`build_pkg.sh` converts pre-release versions such as `3.2.0-b1` or
`3.2.0-rc1` from `-` to `~` for package metadata so pre-releases sort before
the final release. If that normalized package version still contains `-`,
packaging fails because RPM forbids `-` in `Version`, and Debian uses `-` as
the upstream/revision separator.
`pkg_version` is the normalized package metadata version derived inside
`build_pkg.sh` from the binary-reported `xrpld` version (`-` pre-release
separator converted to `~`). It is not a separate user input.
`PKG_RELEASE` is a different value: the package release iteration for that
`xrpld` version. RPM receives the normalized `pkg_version` and `PKG_RELEASE` as
the `pkg_version` and `pkg_release` macros for its `Version` and `Release`
values; DEB writes them as `${pkg_version}-${PKG_RELEASE}` in
`debian/changelog`.
With `PKG_RELEASE=1`, the package metadata becomes:
| Input version | RPM version/release | Debian version |
| ------------------ | ---------------------------- | -------------------- |
| `3.2.0` | `3.2.0-1%{?dist}` | `3.2.0-1` |
| `3.2.0-b0+abc1234` | `3.2.0~b0+abc1234-1%{?dist}` | `3.2.0~b0+abc1234-1` |
| `3.2.0-b1` | `3.2.0~b1-1%{?dist}` | `3.2.0~b1-1` |
| `3.2.0-rc1` | `3.2.0~rc1-1%{?dist}` | `3.2.0~rc1-1` |
The Debian changelog entry carries the repository component: final releases use
`stable`, `b0` builds, including `b0+metadata`, use `develop`, and `bN`/`rcN`
pre-releases use `unstable`.
Build metadata on a final release, such as `3.2.0+abc123`, is rejected.
The RPM path intentionally uses `~` in `Version`, matching the Debian
pre-release ordering convention, so RPM filenames/NVRs begin with forms like
`xrpld-3.2.0~b1-...` and `xrpld-3.2.0~rc1-...` instead of encoding
pre-releases with an older `0.<release>.<suffix>` RPM `Release` value.
| Flag | Env var | Default | Purpose |
| -------------------------- | ------------------- | ----------------------------- | ----------------------------------- |
| `--src-dir DIR` | `SRC_DIR` | `$PWD` | repo root |
| `--build-dir DIR` | `BUILD_DIR` | `$PWD/build` | directory holding pre-built `xrpld` |
| `--pkg-version STR` | `PKG_VERSION` | parsed from `xrpld --version` | version string, e.g. `3.2.0-b1` |
| `--pkg-release N` | `PKG_RELEASE` | `1` | package release number |
| `--source-date-epoch SECS` | `SOURCE_DATE_EPOCH` | latest git commit ctime | reproducibility timestamp |
The package format (`deb` or `rpm`) is inferred from the host's package
manager (`apt-get` -> deb, `dnf`/`yum` -> rpm). Hosts without one of those
fail early.
Flags are for explicit invocation; environment variables are intended for
CMake/CI integration. The CI workflow and the CMake `package` target both invoke
`build_pkg.sh` with no flags; CMake supplies `SRC_DIR`, `BUILD_DIR`, and
`PKG_RELEASE` via env, while CI supplies `BUILD_DIR` and `PKG_RELEASE` via env
and lets the script use defaults for the rest.
CMake/systemd/CI integration. The CI workflow and the CMake `package` target
both invoke `build_pkg.sh` with no flags, configuring it entirely via env
(see `cmake/XrplPackaging.cmake`).
It resolves `SRC_DIR` and `BUILD_DIR` to absolute paths, then calls
`stage_common()` to copy the binary, config files, and shared support files
@@ -162,32 +134,18 @@ into the staging area, and invokes the platform build tool.
### RPM
1. Creates the standard `rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}` tree inside the build directory.
2. Copies `xrpld.spec` and all shared source files (binary, configs, service files) into `SOURCES/`.
3. Runs `rpmbuild -bb`, passing the normalized package metadata version as the
`pkg_version` RPM macro and `PKG_RELEASE` as the `pkg_release` RPM macro.
The spec uses manual `install` commands to place files, disables `dwz`, and
writes uncompressed RPM payloads while generating debuginfo packages.
2. Copies `xrpld.spec` and all source files (binary, configs, service files) into `SOURCES/`.
3. Runs `rpmbuild -bb --define "xrpld_version ..." --define "pkg_release ..."`. The spec uses manual `install` commands to place files.
4. Output: `rpmbuild/RPMS/x86_64/xrpld-*.rpm`
The uncompressed RPM payload setting is intentionally unconditional for
generated RPMs. It trades larger RPM artifacts for much shorter package
build/validation time, which keeps RPM package validation in the same rough time
class as Debian package validation.
RPM upgrades intentionally do not restart a running `xrpld` service. The spec
uses `%systemd_postun`, matching Debian's `dh_installsystemd
--no-stop-on-upgrade` behavior; operators pick up the new binary on the next
service restart.
### DEB
1. Creates a staging source tree at `debbuild/source/` inside the build directory.
2. Stages the binary, configs, `README.md`, and `LICENSE.md`.
3. Copies `package/debian/` control files into `debbuild/source/debian/`.
4. Copies shared service/sysusers/tmpfiles into `debian/` where `dh_installsystemd`, `dh_installsysusers`, and `dh_installtmpfiles` pick them up automatically.
5. Generates a minimal `debian/changelog` using `${pkg_version}-${PKG_RELEASE}`,
where `pkg_version` is derived from the binary-reported `xrpld` version.
6. Runs `dpkg-buildpackage -b --no-sign -d` (`-d` skips the build-dependency check, since the binary is already built). `debian/rules` uses manual `install` commands.
5. Generates a minimal `debian/changelog` (pre-release versions use `~` instead of `-`).
6. Runs `dpkg-buildpackage -b --no-sign`. `debian/rules` uses manual `install` commands.
7. Output: `debbuild/*.deb` and `debbuild/*.ddeb` (dbgsym package)
## Post-build verification
@@ -203,14 +161,11 @@ rpm -qlp rpmbuild/RPMS/x86_64/*.rpm
## Reproducibility
`build_pkg.sh` already defaults `SOURCE_DATE_EPOCH` to the latest git commit
time, or the current time outside a git tree, and exports it (override with
`--source-date-epoch` / `SOURCE_DATE_EPOCH`); the RPM spec clamps file
modification times to it via `%build_mtime_policy`. The remaining variables
below further improve reproducibility but are _not_ set by the script — export
them yourself if needed:
The following environment variables improve build reproducibility. They are not
set automatically by `build_pkg.sh`; set them manually if needed:
```bash
export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)
export TZ=UTC
export LC_ALL=C.UTF-8
export GZIP=-n

View File

@@ -3,18 +3,20 @@ set -euo pipefail
# Build an RPM or Debian package from a pre-built xrpld binary.
#
# Flags override env vars; env vars override defaults.
# Flags override env vars; env vars override defaults. Env vars are intended
# for CMake/systemd/CI integration; flags are for explicit invocation.
usage() {
cat <<'EOF'
Usage: build_pkg.sh [options]
Options (each can also be set via the env var shown):
--src-dir DIR repo root [SRC_DIR; default: ${PWD}]
--build-dir DIR directory holding xrpld [BUILD_DIR; default: ${PWD}/build]
--pkg-release N package release iteration [PKG_RELEASE; default: 1]
--source-date-epoch SECS reproducibility timestamp [SOURCE_DATE_EPOCH; latest git ctime; fallback: current time]
-h, --help show this help and exit
--src-dir DIR repo root [SRC_DIR; default: $PWD]
--build-dir DIR directory holding xrpld [BUILD_DIR; default: $PWD/build]
--pkg-version STR version, e.g. 3.2.0-b1 [PKG_VERSION; default: parsed from xrpld --version]
--pkg-release N package release number [PKG_RELEASE; default: 1]
--source-date-epoch SECS reproducibility timestamp [SOURCE_DATE_EPOCH; default: latest git commit ctime]
-h, --help show this help and exit
EOF
}
@@ -28,7 +30,8 @@ need_arg() {
# Seed from env. CLI parsing below overrides these directly.
SRC_DIR="${SRC_DIR:-}"
BUILD_DIR="${BUILD_DIR:-}"
PKG_RELEASE="${PKG_RELEASE:-1}"
PKG_VERSION="${PKG_VERSION:-}"
PKG_RELEASE="${PKG_RELEASE:-}"
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-}"
while [[ $# -gt 0 ]]; do
@@ -43,6 +46,11 @@ while [[ $# -gt 0 ]]; do
BUILD_DIR="$2"
shift 2
;;
--pkg-version)
need_arg "$@"
PKG_VERSION="$2"
shift 2
;;
--pkg-release)
need_arg "$@"
PKG_RELEASE="$2"
@@ -66,61 +74,19 @@ while [[ $# -gt 0 ]]; do
done
SRC_DIR="$(cd "${SRC_DIR:-${PWD}}" && pwd)"
BUILD_DIR="${BUILD_DIR:-${PWD}/build}"
if [[ ! -d "${BUILD_DIR}" ]]; then
echo "build_pkg.sh: build directory not found: ${BUILD_DIR}" >&2
echo "Build xrpld before packaging, or set BUILD_DIR to the directory containing xrpld." >&2
exit 1
fi
BUILD_DIR="$(cd "${BUILD_DIR}" && pwd)"
BUILD_DIR="$(cd "${BUILD_DIR:-${PWD}/build}" && pwd)"
PKG_RELEASE="${PKG_RELEASE:-1}"
xrpld_binary="${BUILD_DIR}/xrpld"
if [[ ! -x "${xrpld_binary}" ]]; then
echo "build_pkg.sh: expected executable xrpld binary at ${xrpld_binary}." >&2
echo "Build xrpld before packaging, or set BUILD_DIR to the directory containing xrpld." >&2
if [[ -z "${PKG_VERSION}" ]]; then
PKG_VERSION="$("${BUILD_DIR}/xrpld" --version | awk 'NR==1 {print $3; exit}')"
fi
if [[ -z "${PKG_VERSION}" ]]; then
echo "PKG_VERSION is empty (not provided and could not be derived)." >&2
exit 1
fi
xrpld_version="$("${xrpld_binary}" --version | awk 'NR == 1 { print $3 }')"
if [[ -z "${xrpld_version}" ]]; then
echo "build_pkg.sh: unable to derive xrpld version from ${xrpld_binary} --version." >&2
exit 1
fi
# The version as the package formats consume it: identical to xrpld_version
# except a pre-release uses '~' (3.2.0-b1 -> 3.2.0~b1), which also sorts before
# the final 3.2.0; a no-op for a final release. Lowercase = derived internally,
# not an input (cf. pkg_type).
pkg_version="${xrpld_version}"
pre_release=""
if [[ "${xrpld_version}" == *-* ]]; then
pre_release="${xrpld_version#*-}"
pkg_version="${xrpld_version%%-*}~${pre_release}"
fi
# BuildInfo already SemVer-validates the binary's version. Packaging adds one
# narrower constraint: after pre-release normalization, the package version must
# not contain '-' because RPM forbids it in Version and Debian uses it as the
# upstream/revision separator.
if [[ "${pkg_version}" == *-* ]]; then
echo "build_pkg.sh: unsupported xrpld version '${xrpld_version}'." >&2
echo "Package version '${pkg_version}' cannot contain '-'." >&2
echo "Use a single-token pre-release like 3.2.0-b1 or 3.2.0-rc2." >&2
exit 1
fi
if [[ -z "${pre_release}" && "${xrpld_version}" == *+* ]]; then
echo "build_pkg.sh: unsupported xrpld version '${xrpld_version}'." >&2
echo "Build metadata is only supported on bN/rcN pre-releases." >&2
exit 1
fi
if [[ -n "${pre_release}" && ! "${pre_release}" =~ ^(b0|b[1-9][0-9]*|rc[0-9]+)(\+.*)?$ ]]; then
echo "build_pkg.sh: unsupported xrpld pre-release '${pre_release}'." >&2
echo "Use bN or rcN, e.g. 3.2.0-b1 or 3.2.0-rc2." >&2
exit 1
fi
VERSION="${PKG_VERSION}"
if command -v apt-get >/dev/null 2>&1; then
pkg_type=deb
@@ -132,15 +98,32 @@ else
fi
if [[ -z "${SOURCE_DATE_EPOCH}" ]]; then
if git -C "${SRC_DIR}" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
SOURCE_DATE_EPOCH="$(git -C "${SRC_DIR}" log -1 --format=%ct)"
if git -C "$SRC_DIR" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
SOURCE_DATE_EPOCH="$(git -C "$SRC_DIR" log -1 --format=%ct)"
else
SOURCE_DATE_EPOCH="$(date +%s)"
fi
fi
export SOURCE_DATE_EPOCH
CHANGELOG_DATE="$(date -u -R -d "@${SOURCE_DATE_EPOCH}")"
CHANGELOG_DATE="$(date -u -R -d "@$SOURCE_DATE_EPOCH")"
# Split VERSION at the first '-' into base and optional pre-release suffix.
# Examples: "3.2.0" -> ("3.2.0", ""); "3.2.0-b1" -> ("3.2.0", "b1").
VER_BASE="${VERSION%%-*}"
VER_SUFFIX="${VERSION#*-}"
[[ "${VER_SUFFIX}" == "${VERSION}" ]] && VER_SUFFIX=""
# Reject multi-segment suffixes (e.g. "beta-1", "rc1-15-gabc123"). Neither an
# RPM Version nor a Debian upstream version may contain '-' (it's the NVR /
# version-revision separator), and the convention here is single-token
# suffixes like b1 or rc2. Fail early with a clear message rather than letting
# the package tooling blow up or silently mangle dashes.
if [[ "${VER_SUFFIX}" == *-* ]]; then
echo "build_pkg.sh: multi-segment pre-release in VERSION='${VERSION}' (suffix '${VER_SUFFIX}')." >&2
echo "Use single-token suffixes like 3.2.0-b1 or 3.2.0-rc2." >&2
exit 1
fi
SHARED="${SRC_DIR}/package/shared"
DEBIAN_DIR="${SRC_DIR}/package/debian"
@@ -160,6 +143,7 @@ stage_common() {
cp "${SHARED}/xrpld.sysusers" "${dest}/xrpld.sysusers"
cp "${SHARED}/xrpld.tmpfiles" "${dest}/xrpld.tmpfiles"
cp "${SHARED}/xrpld.logrotate" "${dest}/xrpld.logrotate"
cp "${SHARED}/50-xrpld.preset" "${dest}/50-xrpld.preset"
}
build_rpm() {
@@ -170,11 +154,18 @@ build_rpm() {
cp "${SRC_DIR}/package/rpm/xrpld.spec" "${topdir}/SPECS/xrpld.spec"
stage_common "${topdir}/SOURCES"
# Pre-releases use the modern rpm '~' convention (rpm >= 4.10): the suffix
# goes in Version (e.g. 3.2.0~b1), which rpmvercmp sorts *before* the final
# 3.2.0 — identical semantics to Debian's '~'. Release is just the package
# release number. This replaces the older "0.<release>.<suffix>" Release
# hack and keeps the RPM and DEB version strings symmetric.
local rpm_version="${VER_BASE}${VER_SUFFIX:+~${VER_SUFFIX}}"
set -x
rpmbuild -bb \
--define "_topdir ${topdir}" \
--define "pkg_version ${pkg_version}" \
--define "pkg_release ${PKG_RELEASE}" \
--define "xrpld_version ${rpm_version}" \
--define "xrpld_release ${PKG_RELEASE}" \
"${topdir}/SPECS/xrpld.spec"
}
@@ -191,26 +182,23 @@ build_deb() {
cp "${staging}/xrpld.tmpfiles" "${staging}/debian/xrpld.tmpfiles"
cp "${staging}/xrpld.logrotate" "${staging}/debian/xrpld.logrotate"
# Choose the Debian repository component for this package.
# 3.2.0 -> stable, *-b0[+metadata] -> develop,
# bN/rcN pre-releases -> unstable.
local deb_component
if [[ -z "${pre_release}" ]]; then
deb_component="stable"
elif [[ "${pre_release}" =~ ^b0(\+.*)?$ ]]; then
deb_component="develop"
elif [[ "${pre_release}" =~ ^(b[1-9][0-9]*|rc[0-9]+)(\+.*)?$ ]]; then
deb_component="unstable"
else
echo "build_pkg.sh: unsupported xrpld pre-release '${pre_release}'." >&2
echo "Use bN or rcN, e.g. 3.2.0-b1 or 3.2.0-rc2." >&2
exit 1
fi
# Debian '~' marks a pre-release; 3.2.0~b1 sorts before 3.2.0.
local deb_full_version="${VER_BASE}${VER_SUFFIX:+~${VER_SUFFIX}}-${PKG_RELEASE}"
# Derive release channel from the version suffix:
# (none) -> stable (tagged release)
# b0 -> develop (develop-branch build)
# b<N>, rc<N> -> unstable (pre-release)
local deb_distribution
case "${VER_SUFFIX}" in
"") deb_distribution="stable" ;;
b0) deb_distribution="develop" ;;
*) deb_distribution="unstable" ;;
esac
# Debian version is <upstream>[~<pre>]-<pkg release>.
cat >"${staging}/debian/changelog" <<EOF
xrpld (${pkg_version}-${PKG_RELEASE}) ${deb_component}; urgency=medium
* Release ${xrpld_version}.
xrpld (${deb_full_version}) ${deb_distribution}; urgency=medium
* Release ${VERSION}.
-- XRPL Foundation <contact@xrplf.org> ${CHANGELOG_DATE}
EOF

View File

@@ -1,14 +1,6 @@
%if "%{?pkg_version}" == ""
%{error:pkg_version must be defined}
%endif
%if "%{?pkg_release}" == ""
%{error:pkg_release must be defined}
%endif
Name: xrpld
Version: %{pkg_version}
Release: %{pkg_release}%{?dist}
Version: %{xrpld_version}
Release: %{xrpld_release}%{?dist}
Summary: XRP Ledger daemon
License: ISC
@@ -19,9 +11,6 @@ BuildRequires: systemd-rpm-macros
%undefine _debugsource_packages
%debug_package
# Intentionally trade larger RPM artifacts for faster package validation.
%global _binary_payload w.ufdio
%global _find_debuginfo_dwz_opts %{nil}
%build_mtime_policy clamp_to_source_date_epoch
@@ -48,10 +37,7 @@ install -Dm0644 %{_sourcedir}/validators.txt %{buildroot}%{_sysconfdir}/%{
install -Dm0644 %{_sourcedir}/xrpld.service %{buildroot}%{_unitdir}/xrpld.service
install -Dm0644 %{_sourcedir}/xrpld.sysusers %{buildroot}%{_sysusersdir}/xrpld.conf
install -Dm0644 %{_sourcedir}/xrpld.tmpfiles %{buildroot}%{_tmpfilesdir}/xrpld.conf
install -Dm0644 /dev/null %{buildroot}%{_presetdir}/50-xrpld.preset
cat >%{buildroot}%{_presetdir}/50-xrpld.preset <<'EOF'
enable xrpld.service
EOF
install -Dm0644 %{_sourcedir}/50-xrpld.preset %{buildroot}%{_presetdir}/50-xrpld.preset
# Logrotate config
install -Dm0644 %{_sourcedir}/xrpld.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/%{name}
@@ -76,7 +62,7 @@ systemd-tmpfiles --create %{_tmpfilesdir}/xrpld.conf || :
%systemd_preun xrpld.service
%postun
%systemd_postun xrpld.service
%systemd_postun_with_restart xrpld.service
%files
%license %{_docdir}/%{name}/LICENSE.md

View File

@@ -0,0 +1,2 @@
# /usr/lib/systemd/system-preset/50-xrpld.preset
enable xrpld.service

View File

@@ -132,7 +132,7 @@ ValueConstIterator::ValueConstIterator(Value::ObjectValues::iterator const& curr
}
ValueConstIterator&
ValueConstIterator::operator=(SelfType const& other)
ValueConstIterator::operator=(ValueIteratorBase const& other)
{
copy(other);
return *this;

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