mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-27 09:00:32 +00:00
fix: crash in reset (#7675)
This commit is contained in:
@@ -640,7 +640,28 @@ Transactor::payFee()
|
||||
if (!sle)
|
||||
return tefINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
auto const feeAmountAfter = sle->getFieldAmount(feePayer.balanceField) - feePaid;
|
||||
if (feePaid == beast::kZero)
|
||||
return tesSUCCESS;
|
||||
|
||||
XRPAmount balance = beast::kZero;
|
||||
if (sle->isFieldPresent(feePayer.balanceField))
|
||||
{
|
||||
balance = sle->getFieldAmount(feePayer.balanceField).xrp();
|
||||
}
|
||||
else if (feePayer.balanceField != sfFeeAmount)
|
||||
{
|
||||
return tefINTERNAL; // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
if (feePaid > balance)
|
||||
{
|
||||
if ((balance > beast::kZero) && !view().open())
|
||||
return tecINSUFF_FEE;
|
||||
|
||||
return terINSUF_FEE_B;
|
||||
}
|
||||
|
||||
auto const feeAmountAfter = balance - feePaid;
|
||||
|
||||
if (feeAmountAfter == beast::kZero && feePayer.balanceField == sfFeeAmount)
|
||||
{
|
||||
@@ -1302,7 +1323,15 @@ Transactor::reset(XRPAmount fee)
|
||||
if (!payerSle)
|
||||
return {tefINTERNAL, beast::kZero}; // LCOV_EXCL_LINE
|
||||
|
||||
auto const balance = payerSle->getFieldAmount(feePayer.balanceField).xrp();
|
||||
XRPAmount balance = beast::kZero;
|
||||
if (payerSle->isFieldPresent(feePayer.balanceField))
|
||||
{
|
||||
balance = payerSle->getFieldAmount(feePayer.balanceField).xrp();
|
||||
}
|
||||
else if (feePayer.balanceField != sfFeeAmount)
|
||||
{
|
||||
return {tefINTERNAL, beast::kZero}; // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
if (feePayer.type == FeePayerType::SponsorPreFunded && payerSle->isFieldPresent(sfMaxFee))
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <test/jtx/escrow.h>
|
||||
#include <test/jtx/fee.h>
|
||||
#include <test/jtx/flags.h>
|
||||
#include <test/jtx/ledgerStateFix.h>
|
||||
#include <test/jtx/mpt.h>
|
||||
#include <test/jtx/multisign.h>
|
||||
#include <test/jtx/noop.h>
|
||||
@@ -51,6 +52,7 @@
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
#include <xrpl/tx/apply.h>
|
||||
#include <xrpl/tx/applySteps.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
@@ -1835,6 +1837,66 @@ public:
|
||||
BEAST_EXPECT(sle->getFieldAmount(sfFeeAmount) == drops(990)); // 1000 - MaxFee(10)
|
||||
}
|
||||
|
||||
// LedgerStateFix charges an owner-reserve fee and can claim that fee
|
||||
// while returning tecFAILED_PROCESSING. That path must be safe when the
|
||||
// fee is pre-funded by a sponsorship object.
|
||||
{
|
||||
Env env{*this, testableAmendments()};
|
||||
Account const alice("alice");
|
||||
Account const sponsor("sponsor");
|
||||
env.fund(XRP(1000), alice, sponsor);
|
||||
env.close();
|
||||
|
||||
auto const fixFee = drops(env.current()->fees().increment);
|
||||
env(sponsor::set_fee(sponsor, 0, fixFee), sponsor::SponseeAcc(alice));
|
||||
env.close();
|
||||
|
||||
env(ledgerStateFix::nftPageLinks(alice, alice),
|
||||
Fee(fixFee),
|
||||
sponsor::As(sponsor, spfSponsorFee),
|
||||
Ter(tecFAILED_PROCESSING));
|
||||
|
||||
if (auto const sle = env.le(keylet::sponsorship(sponsor, alice)); BEAST_EXPECT(sle))
|
||||
BEAST_EXPECT(!sle->isFieldPresent(sfFeeAmount));
|
||||
}
|
||||
|
||||
// If preclaim saw spendable sponsored FeeAmount but the apply view no
|
||||
// longer has it, the fee path should fail cleanly instead of throwing.
|
||||
{
|
||||
Env env{*this, testableAmendments()};
|
||||
Account const alice("alice");
|
||||
Account const sponsor("sponsor");
|
||||
env.fund(XRP(1000), alice, sponsor);
|
||||
env.close();
|
||||
|
||||
auto const fixFee = drops(env.current()->fees().increment);
|
||||
env(sponsor::set_fee(sponsor, 0, fixFee), sponsor::SponseeAcc(alice));
|
||||
env.close();
|
||||
|
||||
OpenView overlay(&*env.closed());
|
||||
auto jt = env.jt(
|
||||
ledgerStateFix::nftPageLinks(alice, alice),
|
||||
Fee(fixFee),
|
||||
sponsor::As(sponsor, spfSponsorFee));
|
||||
|
||||
auto const pf = preflight(env.app(), overlay.rules(), *jt.stx, TapNone, env.journal);
|
||||
BEAST_EXPECT(isTesSuccess(pf.ter));
|
||||
auto const pc = preclaim(pf, env.app(), overlay);
|
||||
BEAST_EXPECT(isTesSuccess(pc.ter));
|
||||
|
||||
auto const original = overlay.read(keylet::sponsorship(sponsor, alice));
|
||||
if (BEAST_EXPECT(original))
|
||||
{
|
||||
auto sle = std::make_shared<SLE>(*original);
|
||||
sle->makeFieldAbsent(sfFeeAmount);
|
||||
overlay.rawReplace(sle);
|
||||
}
|
||||
|
||||
auto const result = doApply(pc, env.app(), overlay);
|
||||
BEAST_EXPECT(result.ter == terINSUF_FEE_B);
|
||||
BEAST_EXPECT(!result.applied);
|
||||
}
|
||||
|
||||
// test lsfSponsorshipRequireSignForFee
|
||||
{
|
||||
Env env{*this, testableAmendments()};
|
||||
|
||||
Reference in New Issue
Block a user