mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-04 18:55:49 +00:00
add startafter to corn
This commit is contained in:
@@ -51,55 +51,87 @@ SetCron::preflight(PreflightContext const& ctx)
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
// DelaySeconds (D), RepeatCount (R)
|
||||
// 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) / with
|
||||
// StartAfter(s) DelaySeconds (D), RepeatCount (R)
|
||||
|
||||
// SDR - Set Cron with After, Delay and Repeat
|
||||
// SD- - Invalid, if repeat count isn't included then only start or delay
|
||||
// S-R - Invalid
|
||||
// S-- - Set Cron with After for a once off execution
|
||||
|
||||
// -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) / with
|
||||
// tfCronUnset flag set
|
||||
|
||||
bool const hasStart = tx.isFieldPresent(sfStartAfter);
|
||||
bool const hasDelay = tx.isFieldPresent(sfDelaySeconds);
|
||||
bool const hasRepeat = tx.isFieldPresent(sfRepeatCount);
|
||||
|
||||
// unset is a special case, handle first
|
||||
if (tx.isFlag(tfCronUnset))
|
||||
{
|
||||
if (hasDelay || hasRepeat)
|
||||
if (hasDelay || hasRepeat || hasStart)
|
||||
{
|
||||
JLOG(j.debug()) << "SetCron: tfCronUnset flag cannot be used with "
|
||||
"DelaySeconds or RepeatCount.";
|
||||
return temMALFORMED;
|
||||
}
|
||||
|
||||
return preflight2(ctx);
|
||||
}
|
||||
else
|
||||
|
||||
if (hasStart)
|
||||
{
|
||||
if (!hasDelay)
|
||||
if (hasRepeat && hasDelay)
|
||||
{
|
||||
JLOG(j.debug()) << "SetCron: DelaySeconds must be "
|
||||
"specified to create a cron.";
|
||||
// valid, this is a fully specified cron
|
||||
// fall through to validate other fields
|
||||
}
|
||||
else if (!hasRepeat && !hasDelay)
|
||||
{
|
||||
// valid this is a once off cron
|
||||
// no other fields to validate, done
|
||||
return preflight2(ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
// invalid, must specify both or neither repeat and delay count with
|
||||
// startafter
|
||||
JLOG(j.debug()) << "SetCron: StartAfter can only be used with "
|
||||
"either both or neither of "
|
||||
"DelaySeconds and RepeatCount.";
|
||||
return temMALFORMED;
|
||||
}
|
||||
}
|
||||
|
||||
// check delay is not too high
|
||||
auto delay = tx.getFieldU32(sfDelaySeconds);
|
||||
if (delay > 31536000UL /* 365 days in seconds */)
|
||||
if (!hasDelay)
|
||||
{
|
||||
JLOG(j.debug()) << "SetCron: DelaySeconds or StartAfter must be "
|
||||
"specified to create a cron.";
|
||||
return temMALFORMED;
|
||||
}
|
||||
|
||||
// check delay is not too high
|
||||
auto delay = tx.getFieldU32(sfDelaySeconds);
|
||||
if (delay > 31536000UL /* 365 days in seconds */)
|
||||
{
|
||||
JLOG(j.debug()) << "SetCron: DelaySeconds was too high. (max 365 "
|
||||
"days in seconds).";
|
||||
return temMALFORMED;
|
||||
}
|
||||
|
||||
// check repeat is not too high
|
||||
if (hasRepeat)
|
||||
{
|
||||
auto recur = tx.getFieldU32(sfRepeatCount);
|
||||
if (recur > 256)
|
||||
{
|
||||
JLOG(j.debug()) << "SetCron: DelaySeconds was too high. (max 365 "
|
||||
"days in seconds).";
|
||||
JLOG(j.debug())
|
||||
<< "SetCron: RepeatCount too high. Limit is 256. Issue "
|
||||
"new SetCron to increase.";
|
||||
return temMALFORMED;
|
||||
}
|
||||
|
||||
// check repeat is not too high
|
||||
if (hasRepeat)
|
||||
{
|
||||
auto recur = tx.getFieldU32(sfRepeatCount);
|
||||
if (recur > 256)
|
||||
{
|
||||
JLOG(j.debug())
|
||||
<< "SetCron: RepeatCount too high. Limit is 256. Issue "
|
||||
"new SetCron to increase.";
|
||||
return temMALFORMED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return preflight2(ctx);
|
||||
@@ -108,6 +140,32 @@ SetCron::preflight(PreflightContext const& ctx)
|
||||
TER
|
||||
SetCron::preclaim(PreclaimContext const& ctx)
|
||||
{
|
||||
if (ctx.tx.isFieldPresent(sfStartAfter))
|
||||
{
|
||||
uint32_t currentTime =
|
||||
ctx.view.parentCloseTime().time_since_epoch().count();
|
||||
uint32_t afterTime = ctx.tx.getFieldU32(sfStartAfter);
|
||||
|
||||
if (afterTime <= currentTime)
|
||||
{
|
||||
// we'll pass this as though they meant execute asap, similar to a
|
||||
// delay of 0
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
uint32_t waitSeconds = afterTime - currentTime;
|
||||
|
||||
if (waitSeconds > afterTime)
|
||||
return tefINTERNAL;
|
||||
|
||||
if (waitSeconds >> 31536000UL /* 365 days in seconds */)
|
||||
{
|
||||
JLOG(ctx.j.debug())
|
||||
<< "SetCron: DelaySeconds was too high. (max 365 "
|
||||
"days in seconds).";
|
||||
return tecSTART_AFTER_TOO_HIGH;
|
||||
}
|
||||
}
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
@@ -123,6 +181,7 @@ SetCron::doApply()
|
||||
// ledger.
|
||||
uint32_t delay{0};
|
||||
uint32_t recur{0};
|
||||
uint32_t after{0};
|
||||
|
||||
if (!isDelete)
|
||||
{
|
||||
@@ -137,7 +196,10 @@ SetCron::doApply()
|
||||
// do all this sanity checking before we modify the ledger...
|
||||
// even for a delete operation this will fall through without incident
|
||||
|
||||
uint32_t afterTime = currentTime + delay;
|
||||
uint32_t afterTime = tx.isFieldPresent(sfStartAfter)
|
||||
? tx.getFieldU32(sfStartAfter)
|
||||
: currentTime + delay;
|
||||
|
||||
if (afterTime < currentTime)
|
||||
return tefINTERNAL;
|
||||
|
||||
|
||||
@@ -412,6 +412,7 @@ extern SF_UINT32 const sfImportSequence;
|
||||
extern SF_UINT32 const sfXahauActivationLgrSeq;
|
||||
extern SF_UINT32 const sfDelaySeconds;
|
||||
extern SF_UINT32 const sfRepeatCount;
|
||||
extern SF_UINT32 const sfStartAfter;
|
||||
|
||||
// 64-bit integers (common)
|
||||
extern SF_UINT64 const sfIndexNext;
|
||||
|
||||
@@ -343,6 +343,7 @@ enum TECcodes : TERUnderlyingType {
|
||||
tecINSUF_RESERVE_SELLER = 187,
|
||||
tecIMMUTABLE = 188,
|
||||
tecTOO_MANY_REMARKS = 189,
|
||||
tecSTART_AFTER_TOO_HIGH = 190,
|
||||
tecLAST_POSSIBLE_ENTRY = 255,
|
||||
};
|
||||
|
||||
|
||||
@@ -157,6 +157,7 @@ CONSTRUCT_TYPED_SFIELD(sfLockCount, "LockCount", UINT32,
|
||||
|
||||
CONSTRUCT_TYPED_SFIELD(sfFirstNFTokenSequence, "FirstNFTokenSequence", UINT32, 50);
|
||||
|
||||
CONSTRUCT_TYPED_SFIELD(sfStartAfter, "StartAfter", UINT32, 93);
|
||||
CONSTRUCT_TYPED_SFIELD(sfRepeatCount, "RepeatCount", UINT32, 94);
|
||||
CONSTRUCT_TYPED_SFIELD(sfDelaySeconds, "DelaySeconds", UINT32, 95);
|
||||
CONSTRUCT_TYPED_SFIELD(sfXahauActivationLgrSeq, "XahauActivationLgrSeq",UINT32, 96);
|
||||
|
||||
@@ -94,6 +94,7 @@ transResults()
|
||||
MAKE_ERROR(tecINSUF_RESERVE_SELLER, "The seller of an object has insufficient reserves, and thus cannot complete the sale."),
|
||||
MAKE_ERROR(tecIMMUTABLE, "The remark is marked immutable on the object, and therefore cannot be updated."),
|
||||
MAKE_ERROR(tecTOO_MANY_REMARKS, "The number of remarks on the object would exceed the limit of 32."),
|
||||
MAKE_ERROR(tecSTART_AFTER_TOO_HIGH, "The proposed StartAfter time is greater than one year away."),
|
||||
MAKE_ERROR(tefALREADY, "The exact transaction was already in this ledger."),
|
||||
MAKE_ERROR(tefBAD_ADD_AUTH, "Not authorized to add account."),
|
||||
MAKE_ERROR(tefBAD_AUTH, "Transaction's public key is not authorized."),
|
||||
|
||||
@@ -486,6 +486,7 @@ TxFormats::TxFormats()
|
||||
{
|
||||
{sfDelaySeconds, soeOPTIONAL},
|
||||
{sfRepeatCount, soeOPTIONAL},
|
||||
{sfStartAfter, soeOPTIONAL},
|
||||
},
|
||||
commonFields);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user