From 03d4e3037838eebcb364b71935a2ce0241cbafe5 Mon Sep 17 00:00:00 2001 From: yinyiqian1 Date: Thu, 25 Jun 2026 18:21:54 -0400 Subject: [PATCH] Cut ticket scope (#7621) --- .../tx/transactors/system/TicketCreate.cpp | 13 +- src/test/app/Sponsor_test.cpp | 115 ++++-------------- src/test/rpc/AccountTx_test.cpp | 23 ++-- 3 files changed, 38 insertions(+), 113 deletions(-) diff --git a/src/libxrpl/tx/transactors/system/TicketCreate.cpp b/src/libxrpl/tx/transactors/system/TicketCreate.cpp index 3d301ebd77..e8483998d9 100644 --- a/src/libxrpl/tx/transactors/system/TicketCreate.cpp +++ b/src/libxrpl/tx/transactors/system/TicketCreate.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -76,13 +75,8 @@ TicketCreate::doApply() // check the starting balance because we want to allow dipping into the // reserve to pay fees. std::uint32_t const ticketCount = ctx_.tx[sfTicketCount]; - auto const sponsorSle = getTxReserveSponsor(view(), ctx_.tx); - if (!sponsorSle) - return sponsorSle.error(); // LCOV_EXCL_LINE - if (auto const ret = checkInsufficientReserve( - view(), ctx_.tx, sleAccountRoot, preFeeBalance_, *sponsorSle, ticketCount, 0, j_); - !isTesSuccess(ret)) - return ret; + if (preFeeBalance_ < accountReserve(view(), sleAccountRoot, j_, ticketCount)) + return tecINSUFFICIENT_RESERVE; beast::Journal const viewJ{ctx_.registry.get().getJournal("View")}; @@ -119,7 +113,6 @@ TicketCreate::doApply() return tecDIR_FULL; // LCOV_EXCL_LINE sleTicket->setFieldU64(sfOwnerNode, *page); - addSponsorToLedgerEntry(sleTicket, *sponsorSle); } // Update the record of the number of Tickets this account owns. @@ -128,7 +121,7 @@ TicketCreate::doApply() sleAccountRoot->setFieldU32(sfTicketCount, oldTicketCount + ticketCount); // Every added Ticket counts against the creator's reserve. - adjustOwnerCount(view(), sleAccountRoot, *sponsorSle, ticketCount, viewJ); + adjustOwnerCount(view(), accountID_, {}, ticketCount, viewJ); // TicketCreate is the only transaction that can cause an account root's // Sequence field to increase by more than one. October 2018. diff --git a/src/test/app/Sponsor_test.cpp b/src/test/app/Sponsor_test.cpp index cb4192ddb2..d8c6b46290 100644 --- a/src/test/app/Sponsor_test.cpp +++ b/src/test/app/Sponsor_test.cpp @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -40,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -55,7 +53,6 @@ #include #include #include -#include namespace xrpl::test { @@ -681,12 +678,13 @@ public: testcase("PreFund and Cosign"); using namespace test::jtx; Account const alice("alice"); + Account const bob("bob"); Account const sponsor("sponsor"); { // both pre-funded and co-signed,pre-funded value is used Env env{*this, testableAmendments()}; - env.fund(XRP(10000), alice, sponsor); + env.fund(XRP(10000), alice, bob, sponsor); env.close(); env(sponsor::set(sponsor, 0, 100, XRP(100), XRP(1)), @@ -694,8 +692,8 @@ public: Ter(tesSUCCESS)); env.close(); - auto const ticketSeq = env.seq(alice); - env(ticket::create(alice, 1), + auto const checkSeq = env.seq(alice); + env(check::create(alice, bob, XRP(1)), sponsor::As(sponsor, spfSponsorReserve | spfSponsorFee), Sig(sfSponsorSignature, sponsor), Fee(XRP(1)), @@ -707,7 +705,7 @@ public: BEAST_EXPECT(sle->at(sfRemainingOwnerCount) == 99); BEAST_EXPECT(sle->at(sfFeeAmount) == XRP(99)); - env(noop(alice), ticket::Use(ticketSeq + 1), Ter(tesSUCCESS)); + env(check::cancel(alice, keylet::check(alice, checkSeq).key), Ter(tesSUCCESS)); env.close(); sle = env.le(keylet::sponsorship(sponsor, alice)); @@ -719,7 +717,7 @@ public: { // if pre-funded value is not enough, error Env env{*this, testableAmendments()}; - env.fund(XRP(10000), alice, sponsor); + env.fund(XRP(10000), alice, bob, sponsor); env.close(); env(sponsor::set(sponsor, 0, 10, XRP(10), XRP(100)), @@ -728,15 +726,18 @@ public: env.close(); // Fee insufficient - env(ticket::create(alice, 1), + env(check::create(alice, bob, XRP(1)), sponsor::As(sponsor, spfSponsorReserve | spfSponsorFee), Sig(sfSponsorSignature, sponsor), Fee(XRP(11)), Ter(terINSUF_FEE_B)); env.close(); + env(sponsor::set_reserve(sponsor, 0, 0), sponsor::SponseeAcc(alice), Ter(tesSUCCESS)); + env.close(); + // reserve insufficient - env(ticket::create(alice, 11), + env(check::create(alice, bob, XRP(1)), sponsor::As(sponsor, spfSponsorReserve | spfSponsorFee), Sig(sfSponsorSignature, sponsor), Fee(XRP(1)), @@ -2002,25 +2003,26 @@ public: using namespace test::jtx; Env env{*this, testableAmendments()}; Account const alice("alice"); + Account const bob("bob"); Account const sponsor("sponsor"); - env.fund(XRP(10000), alice, sponsor); + env.fund(XRP(10000), alice, bob, sponsor); env.close(); // test Sufficient sponsor balance if (cosigning) { - adjustAccountXRPBalance(env, sponsor, reserve(env, 99)); + adjustAccountXRPBalance(env, sponsor, reserve(env, 1) - drops(1)); - env(ticket::create(alice, 100), + env(check::create(alice, bob, XRP(100)), sponsor::As(sponsor, spfSponsorReserve), Sig(sfSponsorSignature, sponsor), Ter(tecINSUFFICIENT_RESERVE)); env.close(); - adjustAccountXRPBalance(env, sponsor, reserve(env, 100)); + adjustAccountXRPBalance(env, sponsor, reserve(env, 1)); - env(ticket::create(alice, 100), + env(check::create(alice, bob, XRP(100)), sponsor::As(sponsor, spfSponsorReserve), Sig(sfSponsorSignature, sponsor), Ter(tesSUCCESS)); @@ -2031,16 +2033,16 @@ public: env(sponsor::set_reserve(sponsor, 0, 250), sponsor::SponseeAcc(alice)); env.close(); - adjustAccountXRPBalance(env, sponsor, reserve(env, 99 + 1 /* sponsor object*/)); + adjustAccountXRPBalance(env, sponsor, reserve(env, 2) - drops(1)); - env(ticket::create(alice, 100), + env(check::create(alice, bob, XRP(100)), sponsor::As(sponsor, spfSponsorReserve), Ter(tecINSUFFICIENT_RESERVE)); env.close(); - adjustAccountXRPBalance(env, sponsor, reserve(env, 100 + 1 /* sponsor object*/)); + adjustAccountXRPBalance(env, sponsor, reserve(env, 2)); - env(ticket::create(alice, 100), + env(check::create(alice, bob, XRP(100)), sponsor::As(sponsor, spfSponsorReserve), Ter(tesSUCCESS)); env.close(); @@ -2332,75 +2334,6 @@ public: } } - void - testTicket(bool cosigning) - { - testcase("Ticket"); - using namespace test::jtx; - Account const alice("alice"); - Account const sponsor("sponsor"); - Account const sponsor2("sponsor2"); - - { - Env env{*this, testableAmendments()}; - env.fund(XRP(1000000), alice, sponsor, sponsor2); - env.close(); - - // TicketCreate - uint32_t ticketSeq = 0; - - testEachSponsorship( - env, - cosigning, - sponsor, - alice, - 250, - 250, - tecINSUFFICIENT_RESERVE, - [&](Env& env, auto const& submit) { - ticketSeq = env.seq(alice) + 1; - submit(ticket::create(alice, 250)); - }); - - auto const keylet = keylet::TicketT()(alice, ticketSeq); - BEAST_EXPECT(env.le(keylet)->getAccountID(sfSponsor) == sponsor.id()); - - // transfer sponsor - if (cosigning) - { - env(sponsor::transfer(alice, tfSponsorshipReassign, keylet.key), - sponsor::As(sponsor2, spfSponsorReserve), - Sig(sfSponsorSignature, sponsor2)); - env.close(); - } - else - { - env(sponsor::set_reserve(sponsor2, 0, 1), sponsor::SponseeAcc(alice)); - env.close(); - - env(sponsor::transfer(alice, tfSponsorshipReassign, keylet.key), - sponsor::As(sponsor2, spfSponsorReserve)); - env.close(); - } - - BEAST_EXPECT(ownerCount(env, alice) == 250); - BEAST_EXPECT(sponsoredOwnerCount(env, alice) == 250); - BEAST_EXPECT(sponsoringOwnerCount(env, sponsor) == 249); - BEAST_EXPECT(sponsoringOwnerCount(env, sponsor2) == 1); - - BEAST_EXPECT(env.le(keylet)->getAccountID(sfSponsor) == sponsor2.id()); - - // use a Ticket - env(noop(alice), ticket::Use(ticketSeq)); - env.close(); - - BEAST_EXPECT(ownerCount(env, alice) == 249); - BEAST_EXPECT(sponsoredOwnerCount(env, alice) == 249); - BEAST_EXPECT(sponsoringOwnerCount(env, sponsor) == 249); - BEAST_EXPECT(sponsoringOwnerCount(env, sponsor2) == 0); - } - } - void testDelegate(bool cosigning) { @@ -3697,7 +3630,8 @@ public: BEAST_EXPECT(env.balance(sponsor) == XRP(900)); auto jt = env.jtnofill( - ticket::create(alice, 1), sponsor::As(sponsor, spfSponsorReserve | spfSponsorFee)); + check::create(alice, bob, XRP(1)), + sponsor::As(sponsor, spfSponsorReserve | spfSponsorFee)); // remove txn signature since it is filled by env.jtnofill() jt.jv.removeMember(jss::TxnSignature); @@ -3731,7 +3665,7 @@ public: env.close(); auto jt = env.jtnofill( - ticket::create(alice, 1), + check::create(alice, bob, XRP(1)), sponsor::As(sponsor, spfSponsorReserve | spfSponsorFee), Sig(sfSponsorSignature, sponsor)); // remove txn signature since it is filled by env.jtnofill() @@ -3764,7 +3698,6 @@ public: testRequireFlag(); testSponsorReserveSimple(cosigning); testCheck(cosigning); - testTicket(cosigning); testDelegate(cosigning); testDepositPreauth(cosigning); testEscrow(cosigning); diff --git a/src/test/rpc/AccountTx_test.cpp b/src/test/rpc/AccountTx_test.cpp index 8f41bb230e..9310bf384a 100644 --- a/src/test/rpc/AccountTx_test.cpp +++ b/src/test/rpc/AccountTx_test.cpp @@ -933,15 +933,15 @@ class AccountTx_test : public beast::unit_test::Suite checkTx(alice, jss::SponsorshipSet); checkTx(sponsor, jss::SponsorshipSet); - // create a ticket with sponsor - auto const seq = env.seq(alice); - env(ticket::create(alice, 1), sponsor::As(sponsor, spfSponsorReserve)); + // create an object with sponsor + auto const checkId = keylet::check(alice, env.seq(alice)).key; + env(check::create(alice, sponsor, XRP(1)), sponsor::As(sponsor, spfSponsorReserve)); env.close(); - checkTx(alice, jss::TicketCreate); - checkTx(sponsor, jss::TicketCreate); + checkTx(alice, jss::CheckCreate); + checkTx(sponsor, jss::CheckCreate); // transfer object sponsorship - env(sponsor::transfer(alice, tfSponsorshipReassign, keylet::TicketT()(alice, seq + 1).key), + env(sponsor::transfer(alice, tfSponsorshipReassign, checkId), sponsor::As(sponsor2, spfSponsorReserve), Sig(sfSponsorSignature, sponsor2)); env.close(); @@ -949,15 +949,14 @@ class AccountTx_test : public beast::unit_test::Suite checkTx(sponsor, jss::SponsorshipTransfer); checkTx(sponsor2, jss::SponsorshipTransfer); - // use a ticket - env(noop(alice), - ticket::Use(seq + 1), + // delete the sponsored object + env(check::cancel(alice, checkId), sponsor::As(sponsor, spfSponsorFee), Sig(sfSponsorSignature, sponsor)); env.close(); - checkTx(alice, jss::AccountSet); - checkTx(sponsor, jss::AccountSet); - checkTx(sponsor2, jss::AccountSet); + checkTx(alice, jss::CheckCancel); + checkTx(sponsor, jss::CheckCancel); + checkTx(sponsor2, jss::CheckCancel); // account sponsorship env(sponsor::transfer(alice, tfSponsorshipCreate),