use tfCronUnset to delete Cron

This commit is contained in:
tequ
2025-10-15 21:00:19 +09:00
parent e64692fc8b
commit 9b1f3ebdd7
3 changed files with 50 additions and 12 deletions

View File

@@ -45,7 +45,7 @@ SetCron::preflight(PreflightContext const& ctx)
auto& tx = ctx.tx;
auto& j = ctx.j;
if (tx.getFlags() & tfUniversalMask)
if (tx.getFlags() & tfCronSetMask)
{
JLOG(j.warn()) << "SetCron: Invalid flags set.";
return temINVALID_FLAG;
@@ -55,7 +55,8 @@ SetCron::preflight(PreflightContext const& ctx)
// DR - Set Cron with Delay and Repeat
// D- - Set Cron (once off) with Delay only (repat implicitly 0)
// -R - Invalid
// -- - Clear any existing cron (succeeds even if there isn't one)
// -- - Clear any existing cron (succeeds even if there isn't one) / with
// tfCronUnset flag set
bool const hasDelay = tx.isFieldPresent(sfDelaySeconds);
bool const hasRepeat = tx.isFieldPresent(sfRepeatCount);
@@ -90,12 +91,33 @@ SetCron::preflight(PreflightContext const& ctx)
}
}
if (tx.isFlag(tfCronUnset))
{
if (hasDelay || hasRepeat)
{
JLOG(j.warn()) << "SetCron: tfCronUnset flag cannot be used with "
"DelaySeconds or RepeatCount.";
return temMALFORMED;
}
}
return preflight2(ctx);
}
TER
SetCron::preclaim(PreclaimContext const& ctx)
{
if (ctx.tx.isFlag(tfCronUnset))
{
auto const account = ctx.tx.getAccountID(sfAccount);
auto const sle = ctx.view.read(keylet::account(account));
if (!sle)
return tefINTERNAL;
if (!sle->isFieldPresent(sfCron))
return tecNO_ENTRY;
}
return tesSUCCESS;
}
@@ -105,10 +127,7 @@ SetCron::doApply()
auto& view = ctx_.view();
auto const& tx = ctx_.tx;
bool const isDelete = !tx.isFieldPresent(sfDelaySeconds);
if (isDelete && tx.isFieldPresent(sfRepeatCount))
return tefINTERNAL;
bool const isDelete = tx.isFlag(tfCronUnset);
// delay can be zero, in which case the cron will usually execute next
// ledger.

View File

@@ -200,6 +200,12 @@ constexpr std::uint32_t const tfImmutable = 1;
// Clawback flags:
constexpr std::uint32_t const tfClawbackMask = ~tfUniversal;
// CronSet Flags:
enum CronSetFlags : uint32_t {
tfCronUnset = 0x00000001,
};
constexpr std::uint32_t const tfCronSetMask = ~(tfUniversal | tfCronUnset);
// clang-format on
} // namespace ripple

View File

@@ -140,21 +140,24 @@ struct Cron_test : public beast::unit_test::suite
// Invalid DelaySeconds and RepeatCount combination
// (only RepeatCount specified)
env(cron::set(alice), cron::repeat(256), ter(temMALFORMED));
env.close();
// Invalid DelaySeconds
env(cron::set(alice),
cron::delay(365 * 24 * 60 * 60 + 1),
cron::repeat(256),
ter(temMALFORMED));
env.close();
// Invalid RepeatCount
env(cron::set(alice),
cron::delay(365 * 24 * 60 * 60),
cron::repeat(257),
ter(temMALFORMED));
env.close();
// Invalid tfCronUnset flag
env(cron::set(alice),
cron::delay(365 * 24 * 60 * 60),
txflags(tfCronUnset),
ter(temMALFORMED));
}
}
@@ -165,8 +168,15 @@ struct Cron_test : public beast::unit_test::suite
using namespace test::jtx;
using namespace std::literals;
// no preclaim checks exists
BEAST_EXPECT(true);
auto const alice = Account("alice");
Env env{*this, features | featureCron};
env.fund(XRP(1000), alice);
env.close();
// Cron does not set
env(cron::set(alice), txflags(tfCronUnset), ter(tecNO_ENTRY));
env.close();
}
void
@@ -230,7 +240,10 @@ struct Cron_test : public beast::unit_test::suite
BEAST_EXPECT(cronSle2->getFieldU32(sfRepeatCount) == 10);
// delete cron
env(cron::set(alice), fee(XRP(1)), ter(tesSUCCESS));
env(cron::set(alice),
fee(XRP(1)),
txflags(tfCronUnset),
ter(tesSUCCESS));
env.close();
// owner count decremented