Skip to content

refactor: Move reserve checks from preclaim to doApply where relevant#7607

Merged
mvadari merged 11 commits into
xrplf/sponsorfrom
mvadari/sponsor/preclaim
Jun 29, 2026
Merged

refactor: Move reserve checks from preclaim to doApply where relevant#7607
mvadari merged 11 commits into
xrplf/sponsorfrom
mvadari/sponsor/preclaim

Conversation

@mvadari

@mvadari mvadari commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

High Level Overview of Change

This PR moves reserve checks in PaymentChannelCreate and OracleSet from preclaim to doApply, and incorporates preFeeBalance_ into the calculations instead of sfBalance.

Context of Change

Having reserve checks in preclaim is an anti-pattern - see #6599 for a full explanation

API Impact

N/A

@xrplf-ai-reviewer xrplf-ai-reviewer Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues.

Review by Claude Sonnet 4.6 · Prompt: V15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to standardize reserve enforcement for PaymentChannelCreate and OracleSet by shifting reserve checks away from preclaim() (which uses SLE pre-fee balance reads) into doApply() using preFeeBalance_, aligning these transactors with the dominant reserve-check pattern described in issue #6599.

Changes:

  • Gate the existing preclaim() reserve checks so they only run when featureSponsor is not enabled.
  • Add doApply()-time reserve checks (using preFeeBalance_) when featureSponsor is enabled for PaymentChannelCreate and OracleSet.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp Gated preclaim reserve checks and added doApply reserve/funding checks under featureSponsor.
src/libxrpl/tx/transactors/oracle/OracleSet.cpp Gated preclaim reserve checks and added doApply reserve checks under featureSponsor for both create/update paths.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +146 to +160
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;
Comment thread src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp
Comment thread src/libxrpl/tx/transactors/oracle/OracleSet.cpp Outdated
Comment thread src/libxrpl/tx/transactors/oracle/OracleSet.cpp Outdated
Comment thread src/libxrpl/tx/transactors/oracle/OracleSet.cpp Outdated
@codecov

codecov Bot commented Jun 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 71.42857% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.1%. Comparing base (494391b) to head (8bb462a).
⚠️ Report is 15 commits behind head on xrplf/sponsor.

Files with missing lines Patch % Lines
...ansactors/payment_channel/PaymentChannelCreate.cpp 71.4% 6 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@               Coverage Diff               @@
##           xrplf/sponsor   #7607     +/-   ##
===============================================
- Coverage           82.2%   82.1%   -0.1%     
===============================================
  Files               1016    1016             
  Lines              78375   78209    -166     
  Branches            8996    9006     +10     
===============================================
- Hits               64438   64243    -195     
- Misses             13928   13957     +29     
  Partials               9       9             
Files with missing lines Coverage Δ
...ansactors/payment_channel/PaymentChannelCreate.cpp 86.5% <71.4%> (-8.3%) ⬇️

... and 11 files with indirect coverage changes

Impacted file tree graph

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread src/libxrpl/tx/transactors/oracle/OracleSet.cpp Outdated

@xrplf-ai-reviewer xrplf-ai-reviewer Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues.

Review by Claude Sonnet 4.6 · Prompt: V15

Comment thread src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp
@github-actions

Copy link
Copy Markdown

This PR has conflicts, please resolve them in order for the PR to be reviewed.

@github-actions

Copy link
Copy Markdown

All conflicts have been resolved. Assigned reviewers can now start or resume their review.

@xrplf-ai-reviewer xrplf-ai-reviewer Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two correctness bugs flagged inline: a compile error (undeclared sponsorSle) in the OracleSet create branch, and a mutation-before-check ordering issue in the update branch. An unsigned underflow risk is also flagged in PaymentChannelCreate.

Review by Claude Sonnet 4.6 · Prompt: V15

Comment thread src/libxrpl/tx/transactors/oracle/OracleSet.cpp Outdated
Comment thread src/libxrpl/tx/transactors/oracle/OracleSet.cpp Outdated
ctx_.view(),
ctx_.tx,
sle,
STAmount{preFeeBalance_ - ctx_.tx[sfAmount].xrp()},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsigned underflow: subtraction can wrap if sfAmount > preFeeBalance_. Guard before subtracting:

        if (ctx_.tx[sfAmount].xrp() > preFeeBalance_)
            return tecUNFUNDED;
        if (auto const ret = checkInsufficientReserve(
                ctx_.view(),
                ctx_.tx,
                sle,
                STAmount{preFeeBalance_ - ctx_.tx[sfAmount].xrp()},
                {},
                1,
                0,
                j_);

Comment thread src/libxrpl/tx/transactors/oracle/OracleSet.cpp Outdated
Comment thread src/libxrpl/tx/transactors/oracle/OracleSet.cpp Outdated

@xrplf-ai-reviewer xrplf-ai-reviewer Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reserve sponsor SLE is never retrieved in PaymentChannelCreate::doApply — both checkInsufficientReserve calls silently ignore any sponsor, which can cause a valid sponsored transaction to fail with tecINSUFFICIENT_RESERVE. See inline.

Review by Claude Sonnet 4.6 · Prompt: V15

if (ctx_.view().rules().enabled(featureSponsor))
{
if (auto const ret = checkInsufficientReserve(
ctx_.view(), ctx_.tx, sle, STAmount{preFeeBalance_}, {}, 1, 0, j_);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing sponsor SLE — both checkInsufficientReserve calls pass {}, silently dropping any reserve sponsor. Mirror OracleSet::doApply: retrieve the sponsor SLE via getTxReserveSponsor and forward it to both calls.

        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_}, *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;

@xrplf-ai-reviewer xrplf-ai-reviewer Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

Review by Claude Sonnet 4.6 · Prompt: V15

@xrplf-ai-reviewer xrplf-ai-reviewer Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean refactor. No issues.

Review by Claude Sonnet 4.6 · Prompt: V15

auto const sponsorSle = getTxReserveSponsor(ctx_.view(), ctx_.tx);
if (!sponsorSle)
return sponsorSle.error();
if (auto const ret = checkInsufficientReserve(

@Tapanito Tapanito Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mehod name checkInsufficientReserve is a little bit confusing. The reserve can either be sufficient or insufficient, and what the method is doing is determining which one it is. What do you think about calling it checkAccountReserve? Doesn't have to be part of this PR though.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would consider that out of scope of this PR but I'll take note of it

@xrplf-ai-reviewer xrplf-ai-reviewer Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took a pass through this

Sponsored-transaction reserve check uses inconsistent sponsor argument — flagged inline.


Review by ReviewBot 🤖

Review by Claude Sonnet 4.6 · Prompt: V15

ctx_.tx,
sle,
STAmount{preFeeBalance_ - ctx_.tx[sfAmount].xrp()},
{},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Second checkInsufficientReserve passes {} (no sponsor) but the first passes *sponsorSle — inconsistent reserve baseline for sponsored transactions may produce wrong tecUNFUNDED results.

        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 count = calculateOracleReserve(series.size());
if (ctx_.view().rules().enabled(featureSponsor))
{
if (auto const ret = checkInsufficientReserve(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought oracleSet is out of scope for reserve sponsor?

@mvadari mvadari requested a review from PeterChen13579 June 29, 2026 19:49

@xrplf-ai-reviewer xrplf-ai-reviewer Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible sponsor argument mismatch in the second reserve check — see inline.

Review by Claude Sonnet 4.6 · Prompt: V15

ctx_.tx,
sle,
STAmount{preFeeBalance_ - ctx_.tx[sfAmount].xrp()},
{},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Second checkInsufficientReserve passes {} for sponsor, but the first call (line 143) uses *sponsorSle. If intentional, add a comment explaining why the sponsor is excluded from the funding check; if accidental, fix to match the original semantics:

                *sponsorSle,

@PeterChen13579 PeterChen13579 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@mvadari mvadari merged commit 35e1a6e into xrplf/sponsor Jun 29, 2026
39 checks passed
@mvadari mvadari deleted the mvadari/sponsor/preclaim branch June 29, 2026 20:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants