From 88e870b1c64e58674a65e04ed2a620e256a13085 Mon Sep 17 00:00:00 2001 From: tequ Date: Tue, 27 Jan 2026 12:38:01 +0900 Subject: [PATCH] change sfSponsor to STAccount, Sponsor flags as global flags --- include/xrpl/protocol/TxFlags.h | 6 +-- include/xrpl/protocol/detail/sfields.macro | 6 +-- src/libxrpl/ledger/View.cpp | 9 ++-- src/libxrpl/protocol/InnerObjectFormats.cpp | 7 --- src/test/app/Sponsor_test.cpp | 13 +++-- src/test/jtx/impl/sponsor.cpp | 4 +- src/test/rpc/Simulate_test.cpp | 4 +- .../app/tx/detail/SponsorshipTransfer.cpp | 6 +-- src/xrpld/app/tx/detail/Transactor.cpp | 53 ++++++++----------- 9 files changed, 47 insertions(+), 61 deletions(-) diff --git a/include/xrpl/protocol/TxFlags.h b/include/xrpl/protocol/TxFlags.h index 50563036ce..d241abd46a 100644 --- a/include/xrpl/protocol/TxFlags.h +++ b/include/xrpl/protocol/TxFlags.h @@ -40,12 +40,12 @@ namespace xrpl { // Universal Transaction flags: constexpr std::uint32_t tfFullyCanonicalSig = 0x80000000; constexpr std::uint32_t tfInnerBatchTxn = 0x40000000; -constexpr std::uint32_t tfUniversal = tfFullyCanonicalSig | tfInnerBatchTxn; +constexpr std::uint32_t tfSponsorFee = 0x20000000; +constexpr std::uint32_t tfSponsorReserve = 0x10000000; +constexpr std::uint32_t tfUniversal = tfFullyCanonicalSig | tfInnerBatchTxn | tfSponsorFee | tfSponsorReserve; constexpr std::uint32_t tfUniversalMask = ~tfUniversal; // Sponsor flags (Global): -constexpr std::uint32_t tfSponsorFee = 0x00000001; -constexpr std::uint32_t tfSponsorReserve = 0x00000002; constexpr std::uint32_t tfSponsorMask = ~(tfSponsorFee | tfSponsorReserve); // AccountSet flags: diff --git a/include/xrpl/protocol/detail/sfields.macro b/include/xrpl/protocol/detail/sfields.macro index 69216e05ef..dd4aa7c71a 100644 --- a/include/xrpl/protocol/detail/sfields.macro +++ b/include/xrpl/protocol/detail/sfields.macro @@ -334,7 +334,8 @@ TYPED_SFIELD(sfCounterparty, ACCOUNT, 26) TYPED_SFIELD(sfSponsorAccount, ACCOUNT, 27) TYPED_SFIELD(sfHighSponsorAccount, ACCOUNT, 28) TYPED_SFIELD(sfLowSponsorAccount, ACCOUNT, 29) -TYPED_SFIELD(sfSponsee, ACCOUNT, 30) +TYPED_SFIELD(sfSponsor, ACCOUNT, 30) +TYPED_SFIELD(sfSponsee, ACCOUNT, 31) // vector of 256-bit TYPED_SFIELD(sfIndexes, VECTOR256, 1, SField::sMD_Never) @@ -399,8 +400,7 @@ UNTYPED_SFIELD(sfRawTransaction, OBJECT, 34) UNTYPED_SFIELD(sfBatchSigner, OBJECT, 35) UNTYPED_SFIELD(sfBook, OBJECT, 36) UNTYPED_SFIELD(sfCounterpartySignature, OBJECT, 37, SField::sMD_Default, SField::notSigning) -UNTYPED_SFIELD(sfSponsor, OBJECT, 38) -UNTYPED_SFIELD(sfSponsorSignature, OBJECT, 39, SField::sMD_Default, SField::notSigning) +UNTYPED_SFIELD(sfSponsorSignature, OBJECT, 38, SField::sMD_Default, SField::notSigning) // array of objects (common) // ARRAY/1 is reserved for end of array diff --git a/src/libxrpl/ledger/View.cpp b/src/libxrpl/ledger/View.cpp index 608c0e3ab7..ce75d80a6d 100644 --- a/src/libxrpl/ledger/View.cpp +++ b/src/libxrpl/ledger/View.cpp @@ -1118,8 +1118,7 @@ calculateReserve(std::shared_ptr const& sle, Fees const& fees) bool isReserveSponsored(STTx const& tx) { - auto const sponsor = tx.getFieldObject(sfSponsor); - return sponsor.isFlag(tfSponsorReserve); + return tx.isFlag(tfSponsorReserve); } bool @@ -1201,11 +1200,9 @@ checkInsufficientReserve( std::optional getTxReserveSponsorAccountID(STTx const& tx) { - if (tx.isFieldPresent(sfSponsor)) + if (tx.isFieldPresent(sfSponsor) && tx.isFlag(tfSponsorReserve)) { - auto const sponsorObj = tx.getFieldObject(sfSponsor); - if (sponsorObj.isFlag(tfSponsorReserve)) - return sponsorObj.getAccountID(sfAccount); + return tx.getAccountID(sfSponsor); } return {}; } diff --git a/src/libxrpl/protocol/InnerObjectFormats.cpp b/src/libxrpl/protocol/InnerObjectFormats.cpp index 071f6b53f5..dabe7a47cd 100644 --- a/src/libxrpl/protocol/InnerObjectFormats.cpp +++ b/src/libxrpl/protocol/InnerObjectFormats.cpp @@ -162,13 +162,6 @@ InnerObjectFormats::InnerObjectFormats() {sfSigners, soeOPTIONAL}, }); - add(sfSponsor.jsonName.c_str(), - sfSponsor.getCode(), - { - {sfAccount, soeREQUIRED}, - {sfFlags, soeREQUIRED}, - }); - add(sfSponsorSignature.jsonName.c_str(), sfSponsorSignature.getCode(), { diff --git a/src/test/app/Sponsor_test.cpp b/src/test/app/Sponsor_test.cpp index 5992cc48dc..5a63dcb70c 100644 --- a/src/test/app/Sponsor_test.cpp +++ b/src/test/app/Sponsor_test.cpp @@ -7,6 +7,7 @@ #include #include +#include "test/jtx/envconfig.h" #include "test/jtx/sponsor.h" namespace xrpl { @@ -62,12 +63,19 @@ public: Account const sponsor("sponsor"); env.fund(XRP(10000), alice, sponsor); + // check Sponsor field env(noop(alice), fee(XRP(1)), sponsor::as(sponsor), sig(sfSponsorSignature, sponsor), ter(temDISABLED)); + // check Sponsor flags + for (auto flag : + {tfSponsorFee, tfSponsorReserve, tfSponsorFee | tfSponsorReserve}) + env(noop(alice), fee(XRP(1)), txflags(flag), ter(temINVALID_FLAG)); + + // check Sponsor transactions env(sponsor::transfer(alice), ter(temDISABLED)); env(sponsor::set(sponsor, 0), ter(temDISABLED)); } @@ -226,7 +234,7 @@ public: // Signature doesn't exist auto tx = noop(alice); - tx[sfSponsor.jsonName][sfAccount.jsonName] = sponsor.human(); + tx[sfSponsor.jsonName] = sponsor.human(); tx[sfSponsorSignature.jsonName][sfSigningPubKey.jsonName] = strHex(sponsor.pk().slice()); @@ -350,9 +358,6 @@ public: // Invalid Flags env(noop(alice), sponsor::as(sponsor, 4), ter(temINVALID_FLAG)); - env(noop(alice), - sponsor::as(sponsor, tfSponsorMask), - ter(temINVALID_FLAG)); } void diff --git a/src/test/jtx/impl/sponsor.cpp b/src/test/jtx/impl/sponsor.cpp index bbf42198a7..d5931e32e8 100644 --- a/src/test/jtx/impl/sponsor.cpp +++ b/src/test/jtx/impl/sponsor.cpp @@ -96,8 +96,8 @@ sponseeAcc::operator()(Env& env, JTx& jt) const void as::operator()(Env& env, JTx& jt) const { - jt.jv[sfSponsor.jsonName][sfAccount.jsonName] = sponsor_.human(); - jt.jv[sfSponsor.jsonName][sfFlags.jsonName] = flags; + jt.jv[sfSponsor.jsonName] = sponsor_.human(); + jt.jv[sfFlags.jsonName] = jt.jv[sfFlags.jsonName].asUInt() | flags; } Json::Value diff --git a/src/test/rpc/Simulate_test.cpp b/src/test/rpc/Simulate_test.cpp index 258c8790f4..9a5c194abe 100644 --- a/src/test/rpc/Simulate_test.cpp +++ b/src/test/rpc/Simulate_test.cpp @@ -651,8 +651,8 @@ class Simulate_test : public beast::unit_test::suite tx[jss::Account] = env.master.human(); tx[jss::TransactionType] = jss::AccountSet; tx[sfDomain] = newDomain; - tx[sfSponsor.jsonName][sfAccount.jsonName] = sponsor.human(); - tx[sfSponsor.jsonName][sfFlags.jsonName] = tfSponsorFee; + tx[sfSponsor.jsonName] = sponsor.human(); + tx[sfFlags.jsonName] = tfSponsorFee; tx[sfSponsorSignature.jsonName] = Json::objectValue; // test with autofill diff --git a/src/xrpld/app/tx/detail/SponsorshipTransfer.cpp b/src/xrpld/app/tx/detail/SponsorshipTransfer.cpp index 4044291c55..dbed4dfcaf 100644 --- a/src/xrpld/app/tx/detail/SponsorshipTransfer.cpp +++ b/src/xrpld/app/tx/detail/SponsorshipTransfer.cpp @@ -332,9 +332,8 @@ SponsorshipTransfer::doApply() if (tx.isFieldPresent(sfSponsor)) { - auto const sponsorObj = tx.getFieldObject(sfSponsor); auto const oldSponsor = objSle->getAccountID(sponsorField); - auto const newSponsor = sponsorObj[sfAccount]; + auto const newSponsor = tx.getAccountID(sfSponsor); // decrement old sponsoring count if exists if (auto const oldSponsorSle = view().peek(keylet::account(oldSponsor))) @@ -398,9 +397,8 @@ SponsorshipTransfer::doApply() if (tx.isFieldPresent(sfSponsor)) { // transfer account sponsor - auto const sponsorObj = tx.getFieldObject(sfSponsor); // increment new sponsoring count - auto const newSponsor = sponsorObj[sfAccount]; + auto const newSponsor = tx.getAccountID(sfSponsor); auto const newSponsorSle = view().peek(keylet::account(newSponsor)); setSponsorFieldU32(newSponsorSle, sfSponsoringAccountCount, 1); diff --git a/src/xrpld/app/tx/detail/Transactor.cpp b/src/xrpld/app/tx/detail/Transactor.cpp index 90032470e4..e03f85949b 100644 --- a/src/xrpld/app/tx/detail/Transactor.cpp +++ b/src/xrpld/app/tx/detail/Transactor.cpp @@ -73,6 +73,14 @@ preflight0(PreflightContext const& ctx, std::uint32_t flagMask) return temINVALID_FLAG; } + if (!ctx.rules.enabled(featureSponsor) && + ctx.tx.getFlags() & ~tfSponsorMask) + { + JLOG(ctx.j.debug()) << "preflight0: Sponsor flags set without Sponsor " + "amendment enabled"; + return temINVALID_FLAG; + } + return tesSUCCESS; } @@ -206,20 +214,11 @@ Transactor::preflight1(PreflightContext const& ctx, std::uint32_t flagMask) "Inner batch transaction must have a parent batch ID."); // Sponsor checks - if (hasSponsor) + if (hasSponsor && ctx.tx.getAccountID(sfSponsor) == id) { - auto const sponsor = ctx.tx.getFieldObject(sfSponsor); - if (sponsor[sfAccount] == ctx.tx[sfAccount]) - { - JLOG(ctx.j.debug()) << "preflight1: Sponsor account cannot be the " - "same as the transaction originator"; - return temMALFORMED; - } - if (sponsor.getFlags() & tfSponsorMask) - { - JLOG(ctx.j.debug()) << "preflight1: Invalid sponsor flags"; - return temINVALID_FLAG; - } + JLOG(ctx.j.debug()) << "preflight1: Sponsor account cannot be the " + "same as the transaction originator"; + return temMALFORMED; } return tesSUCCESS; @@ -321,21 +320,18 @@ Transactor::checkSponsor(ReadView const& view, STTx const& tx) if (hasSponsorSignature) return tesSUCCESS; - auto const txSponsor = tx.getFieldObject(sfSponsor); - - auto const sponsorAcc = txSponsor.getAccountID(sfAccount); - auto const sponseeAcc = tx.getAccountID(sfAccount); - auto const sponsorSle = view.read(keylet::sponsor(sponsorAcc, sponseeAcc)); + auto const sponsorSle = view.read(keylet::sponsor( + tx.getAccountID(sfSponsor), tx.getAccountID(sfAccount))); // sponsorship object missing for pre-funded tx if (!sponsorSle) return terNO_SPONSORSHIP; - if (txSponsor.isFlag(tfSponsorFee) && + if (tx.isFlag(tfSponsorFee) && sponsorSle->isFlag(lsfSponsorshipRequireSignForFee)) return terNO_SPONSORSHIP; - if (txSponsor.isFlag(tfSponsorReserve) && + if (tx.isFlag(tfSponsorReserve) && sponsorSle->isFlag(lsfSponsorshipRequireSignForReserve)) return terNO_SPONSORSHIP; @@ -807,8 +803,7 @@ Transactor::checkSign( if (!sigObject.isFieldPresent(sfSponsor)) return tefINTERNAL; // LCOV_EXCL_LINE - auto const sponsorObj = sigObject.getFieldObject(sfSponsor); - auto const sponsorAcc = sponsorObj.getAccountID(sfAccount); + auto const sponsorAcc = sigObject.getAccountID(sfSponsor); auto const sponsorSignature = sigObject.getFieldObject(sfSponsorSignature); if (auto const ret = checkSign( @@ -1247,13 +1242,12 @@ Transactor::reset(XRPAmount fee) FeePayer Transactor::getFeePayer(ReadView const& view, STTx const& tx) { - if (tx.isFieldPresent(sfSponsor) && - tx.getFieldObject(sfSponsor).isFlag(tfSponsorFee)) + auto const id = tx.getAccountID(sfAccount); + if (tx.isFieldPresent(sfSponsor) && tx.isFlag(tfSponsorFee)) { - auto const sponsor = tx.getFieldObject(sfSponsor); + auto const sponsor = tx.getAccountID(sfSponsor); auto const hasSignature = tx.isFieldPresent(sfSponsorSignature); - auto const sponsorKeylet = keylet::sponsor( - sponsor.getAccountID(sfAccount), tx.getAccountID(sfAccount)); + auto const sponsorKeylet = keylet::sponsor(sponsor, id); if (hasSignature) { @@ -1263,8 +1257,7 @@ Transactor::getFeePayer(ReadView const& view, STTx const& tx) sponsorKeylet, sfFeeAmount, FeePayerType::SponsorPreFunded}; // co-signed - auto const sponsorAccountKeylet = - keylet::account(sponsor.getAccountID(sfAccount)); + auto const sponsorAccountKeylet = keylet::account(sponsor); return FeePayer{ sponsorAccountKeylet, sfBalance, FeePayerType::SponsorCoSigned}; } @@ -1281,7 +1274,7 @@ Transactor::getFeePayer(ReadView const& view, STTx const& tx) return FeePayer{delegatorKeylet, sfBalance, FeePayerType::Delegate}; } - auto const accountKeylet = keylet::account(tx.getAccountID(sfAccount)); + auto const accountKeylet = keylet::account(id); return FeePayer{accountKeylet, sfBalance, FeePayerType::Account}; }