From db0371a5680539e760b6e5ec4c29cd0bfafa551c Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Tue, 23 Jun 2026 17:13:43 -0400 Subject: [PATCH 1/9] refactor: Move reserve checks from preclaim to doApply where relevant --- .../tx/transactors/oracle/OracleSet.cpp | 56 ++++++++++++++++--- .../payment_channel/PaymentChannelCreate.cpp | 23 ++++++++ 2 files changed, 71 insertions(+), 8 deletions(-) diff --git a/src/libxrpl/tx/transactors/oracle/OracleSet.cpp b/src/libxrpl/tx/transactors/oracle/OracleSet.cpp index 779d312e3b3..93d8bda0256 100644 --- a/src/libxrpl/tx/transactors/oracle/OracleSet.cpp +++ b/src/libxrpl/tx/transactors/oracle/OracleSet.cpp @@ -181,14 +181,17 @@ OracleSet::preclaim(PreclaimContext const& ctx) if (pairs.size() > kMaxOracleDataSeries) return tecARRAY_TOO_LARGE; - auto const& balance = sleSetter->getFieldAmount(sfBalance); - auto const sponsorSle = getTxReserveSponsor(ctx.view, ctx.tx); - if (!sponsorSle) - return sponsorSle.error(); // LCOV_EXCL_LINE - if (auto const ret = checkInsufficientReserve( - ctx.view, ctx.tx, sleSetter, balance, *sponsorSle, adjustReserve, 0, ctx.j); - !isTesSuccess(ret)) - return ret; + if (!ctx.view.rules().enabled(featureSponsor)) + { + auto const& balance = sleSetter->getFieldAmount(sfBalance); + auto const sponsorSle = getTxReserveSponsor(ctx.view, ctx.tx); + if (!sponsorSle) + return sponsorSle.error(); // LCOV_EXCL_LINE + if (auto const ret = checkInsufficientReserve( + ctx.view, ctx.tx, sleSetter, balance, *sponsorSle, adjustReserve, 0, ctx.j); + !isTesSuccess(ret)) + return ret; + } return tesSUCCESS; } @@ -276,6 +279,28 @@ OracleSet::doApply() if (!accountSle) return tefINTERNAL; // LCOV_EXCL_LINE + if (ctx_.view().rules().enabled(featureSponsor)) + { + auto const sponsorSle = getTxReserveSponsor(ctx_.view(), ctx_.tx); + if (!sponsorSle) + return sponsorSle.error(); // LCOV_EXCL_LINE + auto const delta = (getLedgerEntryReserveSponsorAccountID(sle) == + getTxReserveSponsorAccountID(ctx_.tx)) + ? adjust + : static_cast(newCount); + if (auto const ret = checkInsufficientReserve( + ctx_.view(), + ctx_.tx, + accountSle, + STAmount{preFeeBalance_}, + *sponsorSle, + delta, + 0, + j_); + !isTesSuccess(ret)) + return ret; + } + if (adjust > 0) { // To continue receiving sponsorship from the same account after the @@ -354,6 +379,21 @@ OracleSet::doApply() if (!accountSle) return tefINTERNAL; // LCOV_EXCL_LINE + if (ctx_.view().rules().enabled(featureSponsor)) + { + if (auto const ret = checkInsufficientReserve( + ctx_.view(), + ctx_.tx, + accountSle, + STAmount{preFeeBalance_}, + *sponsorSle, + count, + 0, + j_); + !isTesSuccess(ret)) + return ret; + } + adjustOwnerCount(ctx_.view(), accountSle, *sponsorSle, count, ctx_.journal); addSponsorToLedgerEntry(sle, *sponsorSle); diff --git a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp index 04d8e6280b9..e7c87a1af1c 100644 --- a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp +++ b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp @@ -78,6 +78,7 @@ PaymentChannelCreate::preclaim(PreclaimContext const& ctx) return terNO_ACCOUNT; // Check reserve and funds availability + if (!ctx.view.rules().enabled(featureSponsor)) { auto const balance = (*sle)[sfBalance]; auto const sponsorSle = getTxReserveSponsor(ctx.view, ctx.tx); @@ -137,6 +138,28 @@ PaymentChannelCreate::doApply() return tecEXPIRED; } + if (ctx_.view().rules().enabled(featureSponsor)) + { + auto const sponsorSle = getTxReserveSponsor(ctx_.view(), ctx_.tx); + if (!sponsorSle) + return sponsorSle.error(); // LCOV_EXCL_LINE + if (auto const ret = checkInsufficientReserve( + ctx_.view(), ctx_.tx, sle, STAmount{preFeeBalance_}, *sponsorSle, 1, 0, j_); + !isTesSuccess(ret)) + return ret; + if (auto const ret = checkInsufficientReserve( + ctx_.view(), + ctx_.tx, + sle, + STAmount{preFeeBalance_ - ctx_.tx[sfAmount].xrp()}, + *sponsorSle, + 1, + 0, + j_); + !isTesSuccess(ret)) + return tecUNFUNDED; + } + auto const dst = ctx_.tx[sfDestination]; // Create PayChan in ledger. From 49735d196296f6812b803a137359c3041fbe77c9 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Wed, 24 Jun 2026 10:30:25 -0400 Subject: [PATCH 2/9] remove sponsor from pre-sponsor block --- .../transactors/payment_channel/PaymentChannelCreate.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp index e7c87a1af1c..2199fce70c2 100644 --- a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp +++ b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp @@ -140,11 +140,8 @@ PaymentChannelCreate::doApply() if (ctx_.view().rules().enabled(featureSponsor)) { - auto const sponsorSle = getTxReserveSponsor(ctx_.view(), ctx_.tx); - if (!sponsorSle) - return sponsorSle.error(); // LCOV_EXCL_LINE if (auto const ret = checkInsufficientReserve( - ctx_.view(), ctx_.tx, sle, STAmount{preFeeBalance_}, *sponsorSle, 1, 0, j_); + ctx_.view(), ctx_.tx, sle, STAmount{preFeeBalance_}, {}, 1, 0, j_); !isTesSuccess(ret)) return ret; if (auto const ret = checkInsufficientReserve( @@ -152,7 +149,7 @@ PaymentChannelCreate::doApply() ctx_.tx, sle, STAmount{preFeeBalance_ - ctx_.tx[sfAmount].xrp()}, - *sponsorSle, + {}, 1, 0, j_); From 0c7aa43490b6253448f46c38e2e46ddefc83fea2 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Thu, 25 Jun 2026 22:26:40 -0500 Subject: [PATCH 3/9] fix it better --- src/libxrpl/tx/transactors/oracle/OracleSet.cpp | 13 ++++++------- .../payment_channel/PaymentChannelCreate.cpp | 16 ++++++---------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/libxrpl/tx/transactors/oracle/OracleSet.cpp b/src/libxrpl/tx/transactors/oracle/OracleSet.cpp index 93d8bda0256..8384f90158c 100644 --- a/src/libxrpl/tx/transactors/oracle/OracleSet.cpp +++ b/src/libxrpl/tx/transactors/oracle/OracleSet.cpp @@ -183,14 +183,13 @@ OracleSet::preclaim(PreclaimContext const& ctx) if (!ctx.view.rules().enabled(featureSponsor)) { + auto const fees = ctx.view.fees(); + auto const reserve = + fees.reserve + fees.increment * (sleSetter->getFieldU32(sfOwnerCount) + adjustReserve); auto const& balance = sleSetter->getFieldAmount(sfBalance); - auto const sponsorSle = getTxReserveSponsor(ctx.view, ctx.tx); - if (!sponsorSle) - return sponsorSle.error(); // LCOV_EXCL_LINE - if (auto const ret = checkInsufficientReserve( - ctx.view, ctx.tx, sleSetter, balance, *sponsorSle, adjustReserve, 0, ctx.j); - !isTesSuccess(ret)) - return ret; + + if (balance < reserve) + return tecINSUFFICIENT_RESERVE; } return tesSUCCESS; diff --git a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp index 2199fce70c2..768c2be3502 100644 --- a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp +++ b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp @@ -81,17 +81,13 @@ PaymentChannelCreate::preclaim(PreclaimContext const& ctx) if (!ctx.view.rules().enabled(featureSponsor)) { auto const balance = (*sle)[sfBalance]; - auto const sponsorSle = getTxReserveSponsor(ctx.view, ctx.tx); - if (!sponsorSle) - return sponsorSle.error(); // LCOV_EXCL_LINE - if (auto const ret = - checkInsufficientReserve(ctx.view, ctx.tx, sle, balance, *sponsorSle, 1, 0, ctx.j); - !isTesSuccess(ret)) - return ret; + auto const fees = ctx.view.fees(); + auto const reserve = fees.reserve + fees.increment * ((*sle)[sfOwnerCount] + 1); - if (auto const ret = checkInsufficientReserve( - ctx.view, ctx.tx, sle, balance - ctx.tx[sfAmount], *sponsorSle, 1, 0, ctx.j); - !isTesSuccess(ret)) + if (balance < reserve) + return tecINSUFFICIENT_RESERVE; + + if (balance < reserve + ctx.tx[sfAmount]) return tecUNFUNDED; } From 2ed9a69cb998c7055bc5a0b586c92f367f523da3 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Thu, 25 Jun 2026 23:21:34 -0500 Subject: [PATCH 4/9] fix build --- src/libxrpl/tx/transactors/oracle/OracleSet.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/libxrpl/tx/transactors/oracle/OracleSet.cpp b/src/libxrpl/tx/transactors/oracle/OracleSet.cpp index 307bc75e83c..1ffd398b8fa 100644 --- a/src/libxrpl/tx/transactors/oracle/OracleSet.cpp +++ b/src/libxrpl/tx/transactors/oracle/OracleSet.cpp @@ -207,6 +207,11 @@ TER OracleSet::doApply() { auto const oracleID = keylet::oracle(accountID_, ctx_.tx[sfOracleDocumentID]); + SLE::pointer accountSle = view().peek(keylet::account(accountID_)); + auto const sponsorSleExpected = getTxReserveSponsor(ctx_.view(), ctx_.tx); + if (!sponsorSleExpected) + return sponsorSleExpected.error(); // LCOV_EXCL_LINE + auto const& sponsorSle = *sponsorSleExpected; auto populatePriceData = [](STObject& priceData, STObject const& entry) { setPriceDataInnerObjTemplate(priceData); @@ -279,9 +284,6 @@ OracleSet::doApply() if (ctx_.view().rules().enabled(featureSponsor)) { - auto const sponsorSle = getTxReserveSponsor(ctx_.view(), ctx_.tx); - if (!sponsorSle) - return sponsorSle.error(); // LCOV_EXCL_LINE auto const delta = (getLedgerEntryReserveSponsorAccountID(sle) == getTxReserveSponsorAccountID(ctx_.tx)) ? adjust @@ -291,7 +293,7 @@ OracleSet::doApply() ctx_.tx, accountSle, STAmount{preFeeBalance_}, - *sponsorSle, + sponsorSle, delta, 0, j_); @@ -353,7 +355,7 @@ OracleSet::doApply() ctx_.tx, accountSle, STAmount{preFeeBalance_}, - *sponsorSle, + sponsorSle, count, 0, j_); From 2185a1e30fff73a8ba62352f6a5a8090cc1029cc Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Thu, 25 Jun 2026 23:23:57 -0500 Subject: [PATCH 5/9] fix build --- src/libxrpl/tx/transactors/oracle/OracleSet.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libxrpl/tx/transactors/oracle/OracleSet.cpp b/src/libxrpl/tx/transactors/oracle/OracleSet.cpp index 1ffd398b8fa..483eb49ae12 100644 --- a/src/libxrpl/tx/transactors/oracle/OracleSet.cpp +++ b/src/libxrpl/tx/transactors/oracle/OracleSet.cpp @@ -279,9 +279,6 @@ OracleSet::doApply() auto const newCount = calculateOracleReserve(pairs.size()); int32_t const adjust = newCount - oldCount; - if (adjust != 0 && !adjustOwnerCount(ctx_, adjust)) - return tefINTERNAL; // LCOV_EXCL_LINE - if (ctx_.view().rules().enabled(featureSponsor)) { auto const delta = (getLedgerEntryReserveSponsorAccountID(sle) == @@ -301,6 +298,9 @@ OracleSet::doApply() return ret; } + if (adjust != 0 && !adjustOwnerCount(ctx_, adjust)) + return tefINTERNAL; // LCOV_EXCL_LINE + ctx_.view().update(sle); } else From 3c64c3ce52bb4f61fd1b6702c7f12119a297ac3c Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Thu, 25 Jun 2026 23:46:47 -0500 Subject: [PATCH 6/9] fix tests, whoops --- .../tx/transactors/payment_channel/PaymentChannelCreate.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp index 768c2be3502..a6c1d176bb6 100644 --- a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp +++ b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp @@ -136,8 +136,11 @@ PaymentChannelCreate::doApply() if (ctx_.view().rules().enabled(featureSponsor)) { + auto const sponsorSle = getTxReserveSponsor(ctx_.view(), ctx_.tx); + if (!sponsorSle) + return sponsorSle.error(); if (auto const ret = checkInsufficientReserve( - ctx_.view(), ctx_.tx, sle, STAmount{preFeeBalance_}, {}, 1, 0, j_); + ctx_.view(), ctx_.tx, sle, STAmount{preFeeBalance_}, *sponsorSle, 1, 0, j_); !isTesSuccess(ret)) return ret; if (auto const ret = checkInsufficientReserve( From f4cfe0b1b1b7dcdffc96f273bfc354b09ff0ad09 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Fri, 26 Jun 2026 11:18:52 -0500 Subject: [PATCH 7/9] fix clang-tidy issues --- src/libxrpl/tx/transactors/oracle/OracleSet.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libxrpl/tx/transactors/oracle/OracleSet.cpp b/src/libxrpl/tx/transactors/oracle/OracleSet.cpp index 483eb49ae12..e02794a49f3 100644 --- a/src/libxrpl/tx/transactors/oracle/OracleSet.cpp +++ b/src/libxrpl/tx/transactors/oracle/OracleSet.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -207,7 +208,7 @@ TER OracleSet::doApply() { auto const oracleID = keylet::oracle(accountID_, ctx_.tx[sfOracleDocumentID]); - SLE::pointer accountSle = view().peek(keylet::account(accountID_)); + SLE::pointer const accountSle = view().peek(keylet::account(accountID_)); auto const sponsorSleExpected = getTxReserveSponsor(ctx_.view(), ctx_.tx); if (!sponsorSleExpected) return sponsorSleExpected.error(); // LCOV_EXCL_LINE From a5040349b9e95f81ab114739c030543e22e00cd7 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Mon, 29 Jun 2026 15:47:30 -0400 Subject: [PATCH 8/9] roll back OracleSet changes --- .../tx/transactors/oracle/OracleSet.cpp | 115 ++++++++---------- 1 file changed, 53 insertions(+), 62 deletions(-) diff --git a/src/libxrpl/tx/transactors/oracle/OracleSet.cpp b/src/libxrpl/tx/transactors/oracle/OracleSet.cpp index e02794a49f3..779d312e3b3 100644 --- a/src/libxrpl/tx/transactors/oracle/OracleSet.cpp +++ b/src/libxrpl/tx/transactors/oracle/OracleSet.cpp @@ -154,7 +154,18 @@ OracleSet::preclaim(PreclaimContext const& ctx) auto const oldCount = calculateOracleReserve(sle->getFieldArray(sfPriceDataSeries).size()); auto const newCount = calculateOracleReserve(pairs.size()); - adjustReserve = newCount - oldCount; + // if different sponsors, check with newCount + auto const currentSponsor = getLedgerEntryReserveSponsorAccountID(sle); + auto const newSponsor = getTxReserveSponsorAccountID(ctx.tx); + if ((!currentSponsor && !newSponsor) || + (currentSponsor && newSponsor && *currentSponsor == *newSponsor)) + { + adjustReserve = newCount - oldCount; + } + else + { + adjustReserve = newCount; + } } else { @@ -170,32 +181,18 @@ OracleSet::preclaim(PreclaimContext const& ctx) if (pairs.size() > kMaxOracleDataSeries) return tecARRAY_TOO_LARGE; - if (!ctx.view.rules().enabled(featureSponsor)) - { - auto const fees = ctx.view.fees(); - auto const reserve = - fees.reserve + fees.increment * (sleSetter->getFieldU32(sfOwnerCount) + adjustReserve); - auto const& balance = sleSetter->getFieldAmount(sfBalance); - - if (balance < reserve) - return tecINSUFFICIENT_RESERVE; - } + auto const& balance = sleSetter->getFieldAmount(sfBalance); + auto const sponsorSle = getTxReserveSponsor(ctx.view, ctx.tx); + if (!sponsorSle) + return sponsorSle.error(); // LCOV_EXCL_LINE + if (auto const ret = checkInsufficientReserve( + ctx.view, ctx.tx, sleSetter, balance, *sponsorSle, adjustReserve, 0, ctx.j); + !isTesSuccess(ret)) + return ret; return tesSUCCESS; } -static bool -adjustOwnerCount(ApplyContext& ctx, int count) -{ - if (auto const sleAccount = ctx.view().peek(keylet::account(ctx.tx[sfAccount]))) - { - adjustOwnerCount(ctx.view(), sleAccount, {}, count, ctx.journal); - return true; - } - - return false; // LCOV_EXCL_LINE -} - static void setPriceDataInnerObjTemplate(STObject& obj) { @@ -208,11 +205,6 @@ TER OracleSet::doApply() { auto const oracleID = keylet::oracle(accountID_, ctx_.tx[sfOracleDocumentID]); - SLE::pointer const accountSle = view().peek(keylet::account(accountID_)); - auto const sponsorSleExpected = getTxReserveSponsor(ctx_.view(), ctx_.tx); - if (!sponsorSleExpected) - return sponsorSleExpected.error(); // LCOV_EXCL_LINE - auto const& sponsorSle = *sponsorSleExpected; auto populatePriceData = [](STObject& priceData, STObject const& entry) { setPriceDataInnerObjTemplate(priceData); @@ -280,27 +272,33 @@ OracleSet::doApply() auto const newCount = calculateOracleReserve(pairs.size()); int32_t const adjust = newCount - oldCount; - if (ctx_.view().rules().enabled(featureSponsor)) + auto const accountSle = ctx_.view().peek(keylet::account(ctx_.tx[sfAccount])); + if (!accountSle) + return tefINTERNAL; // LCOV_EXCL_LINE + + if (adjust > 0) { - auto const delta = (getLedgerEntryReserveSponsorAccountID(sle) == - getTxReserveSponsorAccountID(ctx_.tx)) - ? adjust - : static_cast(newCount); - if (auto const ret = checkInsufficientReserve( - ctx_.view(), - ctx_.tx, - accountSle, - STAmount{preFeeBalance_}, - sponsorSle, - delta, - 0, - j_); - !isTesSuccess(ret)) - return ret; + // To continue receiving sponsorship from the same account after the + // OwnerCount increases from 1 to 2, it is necessary to sign with + // the sponsor decrease current sponsored owner count. + // Otherwise, the sponsorship will be deleted. + + auto const newSponsorSle = getTxReserveSponsor(ctx_.view(), ctx_.tx); + if (!newSponsorSle) + return newSponsorSle.error(); // LCOV_EXCL_LINE + + // decrease current sponsored owner count + adjustOwnerCountObj(ctx_.view(), accountSle, sle, -oldCount, ctx_.journal); + removeSponsorFromLedgerEntry(sle); + // increase new owner count + adjustOwnerCount(ctx_.view(), accountSle, *newSponsorSle, newCount, ctx_.journal); + addSponsorToLedgerEntry(sle, *newSponsorSle); + } + else if (adjust < 0) + { + // decrease owner count + adjustOwnerCountObj(ctx_.view(), accountSle, sle, adjust, ctx_.journal); } - - if (adjust != 0 && !adjustOwnerCount(ctx_, adjust)) - return tefINTERNAL; // LCOV_EXCL_LINE ctx_.view().update(sle); } @@ -349,23 +347,16 @@ OracleSet::doApply() (*sle)[sfOwnerNode] = *page; auto const count = calculateOracleReserve(series.size()); - if (ctx_.view().rules().enabled(featureSponsor)) - { - if (auto const ret = checkInsufficientReserve( - ctx_.view(), - ctx_.tx, - accountSle, - STAmount{preFeeBalance_}, - sponsorSle, - count, - 0, - j_); - !isTesSuccess(ret)) - return ret; - } - if (!adjustOwnerCount(ctx_, count)) + auto const sponsorSle = getTxReserveSponsor(view(), ctx_.tx); + if (!sponsorSle) + return sponsorSle.error(); // LCOV_EXCL_LINE + auto const accountSle = ctx_.view().peek(keylet::account(ctx_.tx[sfAccount])); + if (!accountSle) return tefINTERNAL; // LCOV_EXCL_LINE + adjustOwnerCount(ctx_.view(), accountSle, *sponsorSle, count, ctx_.journal); + addSponsorToLedgerEntry(sle, *sponsorSle); + ctx_.view().insert(sle); } From 8bb462aa1b0a21398a10555f2c18ef2b9a4e1268 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Mon, 29 Jun 2026 15:48:46 -0400 Subject: [PATCH 9/9] whoops --- .../tx/transactors/oracle/OracleSet.cpp | 73 +++++-------------- 1 file changed, 19 insertions(+), 54 deletions(-) diff --git a/src/libxrpl/tx/transactors/oracle/OracleSet.cpp b/src/libxrpl/tx/transactors/oracle/OracleSet.cpp index 779d312e3b3..dd5bcbb117b 100644 --- a/src/libxrpl/tx/transactors/oracle/OracleSet.cpp +++ b/src/libxrpl/tx/transactors/oracle/OracleSet.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -154,18 +153,7 @@ OracleSet::preclaim(PreclaimContext const& ctx) auto const oldCount = calculateOracleReserve(sle->getFieldArray(sfPriceDataSeries).size()); auto const newCount = calculateOracleReserve(pairs.size()); - // if different sponsors, check with newCount - auto const currentSponsor = getLedgerEntryReserveSponsorAccountID(sle); - auto const newSponsor = getTxReserveSponsorAccountID(ctx.tx); - if ((!currentSponsor && !newSponsor) || - (currentSponsor && newSponsor && *currentSponsor == *newSponsor)) - { - adjustReserve = newCount - oldCount; - } - else - { - adjustReserve = newCount; - } + adjustReserve = newCount - oldCount; } else { @@ -181,18 +169,27 @@ OracleSet::preclaim(PreclaimContext const& ctx) if (pairs.size() > kMaxOracleDataSeries) return tecARRAY_TOO_LARGE; + auto const reserve = accountReserve(ctx.view, sleSetter, ctx.j, adjustReserve); auto const& balance = sleSetter->getFieldAmount(sfBalance); - auto const sponsorSle = getTxReserveSponsor(ctx.view, ctx.tx); - if (!sponsorSle) - return sponsorSle.error(); // LCOV_EXCL_LINE - if (auto const ret = checkInsufficientReserve( - ctx.view, ctx.tx, sleSetter, balance, *sponsorSle, adjustReserve, 0, ctx.j); - !isTesSuccess(ret)) - return ret; + + if (balance < reserve) + return tecINSUFFICIENT_RESERVE; return tesSUCCESS; } +static bool +adjustOwnerCount(ApplyContext& ctx, int count) +{ + if (auto const sleAccount = ctx.view().peek(keylet::account(ctx.tx[sfAccount]))) + { + adjustOwnerCount(ctx.view(), sleAccount, {}, count, ctx.journal); + return true; + } + + return false; // LCOV_EXCL_LINE +} + static void setPriceDataInnerObjTemplate(STObject& obj) { @@ -272,34 +269,9 @@ OracleSet::doApply() auto const newCount = calculateOracleReserve(pairs.size()); int32_t const adjust = newCount - oldCount; - auto const accountSle = ctx_.view().peek(keylet::account(ctx_.tx[sfAccount])); - if (!accountSle) + if (adjust != 0 && !adjustOwnerCount(ctx_, adjust)) return tefINTERNAL; // LCOV_EXCL_LINE - if (adjust > 0) - { - // To continue receiving sponsorship from the same account after the - // OwnerCount increases from 1 to 2, it is necessary to sign with - // the sponsor decrease current sponsored owner count. - // Otherwise, the sponsorship will be deleted. - - auto const newSponsorSle = getTxReserveSponsor(ctx_.view(), ctx_.tx); - if (!newSponsorSle) - return newSponsorSle.error(); // LCOV_EXCL_LINE - - // decrease current sponsored owner count - adjustOwnerCountObj(ctx_.view(), accountSle, sle, -oldCount, ctx_.journal); - removeSponsorFromLedgerEntry(sle); - // increase new owner count - adjustOwnerCount(ctx_.view(), accountSle, *newSponsorSle, newCount, ctx_.journal); - addSponsorToLedgerEntry(sle, *newSponsorSle); - } - else if (adjust < 0) - { - // decrease owner count - adjustOwnerCountObj(ctx_.view(), accountSle, sle, adjust, ctx_.journal); - } - ctx_.view().update(sle); } else @@ -347,16 +319,9 @@ OracleSet::doApply() (*sle)[sfOwnerNode] = *page; auto const count = calculateOracleReserve(series.size()); - auto const sponsorSle = getTxReserveSponsor(view(), ctx_.tx); - if (!sponsorSle) - return sponsorSle.error(); // LCOV_EXCL_LINE - auto const accountSle = ctx_.view().peek(keylet::account(ctx_.tx[sfAccount])); - if (!accountSle) + if (!adjustOwnerCount(ctx_, count)) return tefINTERNAL; // LCOV_EXCL_LINE - adjustOwnerCount(ctx_.view(), accountSle, *sponsorSle, count, ctx_.journal); - addSponsorToLedgerEntry(sle, *sponsorSle); - ctx_.view().insert(sle); }