Compare commits

...

2 Commits

Author SHA1 Message Date
tequ
1d0b31f85a add LedgerSequence check 2025-11-13 17:42:08 +09:00
tequ
e3863181c5 . 2025-11-13 16:28:16 +09:00

View File

@@ -44,12 +44,15 @@ Cron::preflight(PreflightContext const& ctx)
auto const ret = preflight0(ctx); auto const ret = preflight0(ctx);
if (!isTesSuccess(ret)) if (!isTesSuccess(ret))
{
JLOG(ctx.j.fatal()) << "Cron: preflight failed";
return ret; return ret;
}
auto account = ctx.tx.getAccountID(sfAccount); auto account = ctx.tx.getAccountID(sfAccount);
if (account != beast::zero) if (account != beast::zero)
{ {
JLOG(ctx.j.warn()) << "Cron: Bad source id"; JLOG(ctx.j.fatal()) << "Cron: Bad source id";
return temBAD_SRC_ACCOUNT; return temBAD_SRC_ACCOUNT;
} }
@@ -57,21 +60,21 @@ Cron::preflight(PreflightContext const& ctx)
auto const fee = ctx.tx.getFieldAmount(sfFee); auto const fee = ctx.tx.getFieldAmount(sfFee);
if (!fee.native() || fee != beast::zero) if (!fee.native() || fee != beast::zero)
{ {
JLOG(ctx.j.warn()) << "Cron: invalid fee"; JLOG(ctx.j.fatal()) << "Cron: invalid fee";
return temBAD_FEE; return temBAD_FEE;
} }
if (!ctx.tx.getSigningPubKey().empty() || !ctx.tx.getSignature().empty() || if (!ctx.tx.getSigningPubKey().empty() || !ctx.tx.getSignature().empty() ||
ctx.tx.isFieldPresent(sfSigners)) ctx.tx.isFieldPresent(sfSigners))
{ {
JLOG(ctx.j.warn()) << "Cron: Bad signature"; JLOG(ctx.j.fatal()) << "Cron: Bad signature";
return temBAD_SIGNATURE; return temBAD_SIGNATURE;
} }
if (ctx.tx.getFieldU32(sfSequence) != 0 || if (ctx.tx.getFieldU32(sfSequence) != 0 ||
ctx.tx.isFieldPresent(sfPreviousTxnID)) ctx.tx.isFieldPresent(sfPreviousTxnID))
{ {
JLOG(ctx.j.warn()) << "Cron: Bad sequence"; JLOG(ctx.j.fatal()) << "Cron: Bad sequence";
return temBAD_SEQUENCE; return temBAD_SEQUENCE;
} }
@@ -84,6 +87,12 @@ Cron::preclaim(PreclaimContext const& ctx)
if (!ctx.view.rules().enabled(featureCron)) if (!ctx.view.rules().enabled(featureCron))
return temDISABLED; return temDISABLED;
if (ctx.tx.getFieldU32(sfLedgerSequence) != ctx.view.info().seq)
{
JLOG(ctx.j.fatal()) << "Cron: wrong ledger sequence";
return tefFAILURE;
}
return tesSUCCESS; return tesSUCCESS;
} }
@@ -105,7 +114,7 @@ Cron::doApply()
if (!sle->isFieldPresent(sfCron)) if (!sle->isFieldPresent(sfCron))
{ {
JLOG(j_.warn()) << "Cron: sfCron missing from account " << id; JLOG(j_.fatal()) << "Cron: sfCron missing from account " << id;
return tefINTERNAL; return tefINTERNAL;
} }
@@ -114,7 +123,7 @@ Cron::doApply()
auto sleCron = view.peek(klOld); auto sleCron = view.peek(klOld);
if (!sleCron) if (!sleCron)
{ {
JLOG(j_.warn()) << "Cron: Cron object missing for account " << id; JLOG(j_.fatal()) << "Cron: Cron object missing for account " << id;
return tesSUCCESS; return tesSUCCESS;
} }
@@ -126,7 +135,10 @@ Cron::doApply()
// do all this sanity checking before we modify the ledger... // do all this sanity checking before we modify the ledger...
uint32_t afterTime = lastStartTime + delay; uint32_t afterTime = lastStartTime + delay;
if (afterTime < lastStartTime) if (afterTime < lastStartTime)
{
JLOG(j_.fatal()) << "Cron: afterTime < lastStartTime";
return tefINTERNAL; return tefINTERNAL;
}
// in all circumstances the Cron object is deleted... // in all circumstances the Cron object is deleted...
// if there are further crons to do then a new one is created at the next // if there are further crons to do then a new one is created at the next
@@ -134,7 +146,10 @@ Cron::doApply()
if (!view.dirRemove( if (!view.dirRemove(
keylet::ownerDir(id), (*sleCron)[sfOwnerNode], klOld, false)) keylet::ownerDir(id), (*sleCron)[sfOwnerNode], klOld, false))
{
JLOG(j_.fatal()) << "Cron: Ownerdir bad. " << id;
return tefBAD_LEDGER; return tefBAD_LEDGER;
}
view.erase(sleCron); view.erase(sleCron);
@@ -156,19 +171,22 @@ Cron::doApply()
auto const page = auto const page =
view.dirInsert(keylet::ownerDir(id), klCron, describeOwnerDir(id)); view.dirInsert(keylet::ownerDir(id), klCron, describeOwnerDir(id));
if (!page) if (!page)
{
JLOG(j_.fatal()) << "Cron: Ownerdir full. " << id;
return tecDIR_FULL; return tecDIR_FULL;
}
sleCron = std::make_shared<SLE>(klCron); auto newSleCron = std::make_shared<SLE>(klCron);
sleCron->setFieldU64(sfOwnerNode, *page); newSleCron->setFieldU64(sfOwnerNode, *page);
sleCron->setFieldU32(sfDelaySeconds, delay); newSleCron->setFieldU32(sfDelaySeconds, delay);
sleCron->setFieldU32(sfRepeatCount, recur - 1); newSleCron->setFieldU32(sfRepeatCount, recur - 1);
sleCron->setFieldU32(sfStartTime, afterTime); newSleCron->setFieldU32(sfStartTime, afterTime);
sleCron->setAccountID(sfOwner, id); newSleCron->setAccountID(sfOwner, id);
sle->setFieldH256(sfCron, klCron.key); sle->setFieldH256(sfCron, klCron.key);
view.insert(sleCron); view.insert(newSleCron);
view.update(sle); view.update(sle);
return tesSUCCESS; return tesSUCCESS;