mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-19 01:55:48 +00:00
whoops
This commit is contained in:
@@ -444,6 +444,7 @@ target_sources (rippled PRIVATE
|
||||
src/ripple/app/tx/impl/CreateCheck.cpp
|
||||
src/ripple/app/tx/impl/CreateOffer.cpp
|
||||
src/ripple/app/tx/impl/CreateTicket.cpp
|
||||
src/ripple/app/tx/impl/Cron.cpp
|
||||
src/ripple/app/tx/impl/DeleteAccount.cpp
|
||||
src/ripple/app/tx/impl/DepositPreauth.cpp
|
||||
src/ripple/app/tx/impl/Escrow.cpp
|
||||
@@ -461,6 +462,7 @@ target_sources (rippled PRIVATE
|
||||
src/ripple/app/tx/impl/Payment.cpp
|
||||
src/ripple/app/tx/impl/Remit.cpp
|
||||
src/ripple/app/tx/impl/SetAccount.cpp
|
||||
src/ripple/app/tx/impl/SetCron.cpp
|
||||
src/ripple/app/tx/impl/SetHook.cpp
|
||||
src/ripple/app/tx/impl/SetRemarks.cpp
|
||||
src/ripple/app/tx/impl/SetRegularKey.cpp
|
||||
|
||||
@@ -75,6 +75,11 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
|
||||
|
||||
switch (tt)
|
||||
{
|
||||
case ttCRON: {
|
||||
ADD_TSH(tx.getAccountID(sfOwner), tshWEAK);
|
||||
break;
|
||||
}
|
||||
|
||||
case ttREMIT: {
|
||||
if (destAcc)
|
||||
ADD_TSH(*destAcc, tshSTRONG);
|
||||
@@ -1051,8 +1056,8 @@ hook::getHookCanEmit(
|
||||
(hookObj.isFieldPresent(sfHookCanEmit)
|
||||
? hookObj.getFieldH256(sfHookCanEmit)
|
||||
: hookDef->isFieldPresent(sfHookCanEmit)
|
||||
? hookDef->getFieldH256(sfHookCanEmit)
|
||||
: defaultHookCanEmit);
|
||||
? hookDef->getFieldH256(sfHookCanEmit)
|
||||
: defaultHookCanEmit);
|
||||
return hookCanEmit;
|
||||
}
|
||||
|
||||
@@ -2938,10 +2943,10 @@ DEFINE_HOOK_FUNCTION(
|
||||
ripple::Keylet kl = keylet_type == keylet_code::CHILD
|
||||
? ripple::keylet::child(id)
|
||||
: keylet_type == keylet_code::EMITTED_TXN
|
||||
? ripple::keylet::emittedTxn(id)
|
||||
: keylet_type == keylet_code::HOOK_DEFINITION
|
||||
? ripple::keylet::hookDefinition(id)
|
||||
: ripple::keylet::unchecked(id);
|
||||
? ripple::keylet::emittedTxn(id)
|
||||
: keylet_type == keylet_code::HOOK_DEFINITION
|
||||
? ripple::keylet::hookDefinition(id)
|
||||
: ripple::keylet::unchecked(id);
|
||||
|
||||
return serialize_keylet(kl, memory, write_ptr, write_len);
|
||||
}
|
||||
@@ -2970,10 +2975,10 @@ DEFINE_HOOK_FUNCTION(
|
||||
ripple::Keylet kl = keylet_type == keylet_code::HOOK
|
||||
? ripple::keylet::hook(id)
|
||||
: keylet_type == keylet_code::SIGNERS
|
||||
? ripple::keylet::signers(id)
|
||||
: keylet_type == keylet_code::OWNER_DIR
|
||||
? ripple::keylet::ownerDir(id)
|
||||
: ripple::keylet::account(id);
|
||||
? ripple::keylet::signers(id)
|
||||
: keylet_type == keylet_code::OWNER_DIR
|
||||
? ripple::keylet::ownerDir(id)
|
||||
: ripple::keylet::account(id);
|
||||
|
||||
return serialize_keylet(kl, memory, write_ptr, write_len);
|
||||
}
|
||||
@@ -3013,10 +3018,10 @@ DEFINE_HOOK_FUNCTION(
|
||||
ripple::Keylet kl = keylet_type == keylet_code::CHECK
|
||||
? ripple::keylet::check(id, seq)
|
||||
: keylet_type == keylet_code::ESCROW
|
||||
? ripple::keylet::escrow(id, seq)
|
||||
: keylet_type == keylet_code::NFT_OFFER
|
||||
? ripple::keylet::nftoffer(id, seq)
|
||||
: ripple::keylet::offer(id, seq);
|
||||
? ripple::keylet::escrow(id, seq)
|
||||
: keylet_type == keylet_code::NFT_OFFER
|
||||
? ripple::keylet::nftoffer(id, seq)
|
||||
: ripple::keylet::offer(id, seq);
|
||||
|
||||
return serialize_keylet(kl, memory, write_ptr, write_len);
|
||||
}
|
||||
@@ -3134,13 +3139,11 @@ DEFINE_HOOK_FUNCTION(
|
||||
WRITE_WASM_MEMORY_AND_RETURN(
|
||||
write_ptr,
|
||||
write_len,
|
||||
keylet_type == keylet_code::AMENDMENTS
|
||||
? cAmendments.data()
|
||||
: keylet_type == keylet_code::FEES
|
||||
? cFees.data()
|
||||
: keylet_type == keylet_code::NEGATIVE_UNL
|
||||
? cNegativeUNL.data()
|
||||
: cEmittedDir.data(),
|
||||
keylet_type == keylet_code::AMENDMENTS ? cAmendments.data()
|
||||
: keylet_type == keylet_code::FEES ? cFees.data()
|
||||
: keylet_type == keylet_code::NEGATIVE_UNL
|
||||
? cNegativeUNL.data()
|
||||
: cEmittedDir.data(),
|
||||
34,
|
||||
memory,
|
||||
memory_length);
|
||||
@@ -6001,9 +6004,9 @@ DEFINE_HOOK_FUNCTION(
|
||||
|
||||
size_t free_count = hook_api::max_slots - hookCtx.slot.size();
|
||||
|
||||
size_t needed_count = slot_into_tx == 0 && slot_into_meta == 0
|
||||
? 2
|
||||
: slot_into_tx != 0 && slot_into_meta != 0 ? 0 : 1;
|
||||
size_t needed_count = slot_into_tx == 0 && slot_into_meta == 0 ? 2
|
||||
: slot_into_tx != 0 && slot_into_meta != 0 ? 0
|
||||
: 1;
|
||||
|
||||
if (free_count < needed_count)
|
||||
return NO_FREE_SLOTS;
|
||||
|
||||
@@ -1477,6 +1477,63 @@ TxQ::accept(Application& app, OpenView& view)
|
||||
}
|
||||
}
|
||||
|
||||
// Inject cron transactions, if any
|
||||
if (view.rules().enabled(featureCron))
|
||||
{
|
||||
uint32_t currentTime =
|
||||
view.parentCloseTime().time_since_epoch().count();
|
||||
uint256 klStart = keylet::cron(0, AccountID(beast::zero)).key;
|
||||
uint256 const klEnd =
|
||||
keylet::cron(currentTime + 1, AccountID(beast::zero)).key;
|
||||
|
||||
std::set<AccountID> cronAccs;
|
||||
|
||||
auto counter = 0;
|
||||
while (++counter < 128 && klStart < klEnd)
|
||||
{
|
||||
std::optional<uint256 const> next = view.succ(klStart, klEnd);
|
||||
if (!next.has_value())
|
||||
break;
|
||||
|
||||
Keylet kl{ltANY, *next};
|
||||
|
||||
if (view.exists(kl))
|
||||
{
|
||||
auto sle = view.read(kl);
|
||||
if (safe_cast<TxType>(sle->getFieldU16(sfLedgerEntryType)) ==
|
||||
ltCRON)
|
||||
{
|
||||
// valid cron object, add it to the list
|
||||
cronAccs.emplace(sle->getAccountID(sfOwner));
|
||||
}
|
||||
}
|
||||
|
||||
klStart = *next;
|
||||
}
|
||||
|
||||
auto const seq = view.info().seq;
|
||||
|
||||
// insert Cron pseudos for each of the accs we need to ping
|
||||
for (AccountID const& id : cronAccs)
|
||||
{
|
||||
STTx cronTx(ttCRON, [=](auto& obj) {
|
||||
obj[sfAccount] = AccountID();
|
||||
obj[sfLedgerSequence] = seq;
|
||||
obj[sfOwner] = id;
|
||||
});
|
||||
|
||||
uint256 txID = cronTx.getTransactionID();
|
||||
|
||||
auto s = std::make_shared<ripple::Serializer>();
|
||||
cronTx.add(*s);
|
||||
|
||||
app.getHashRouter().setFlags(txID, SF_PRIVATE2);
|
||||
app.getHashRouter().setFlags(txID, SF_EMITTED);
|
||||
view.rawTxInsert(txID, std::move(s), nullptr);
|
||||
ledgerChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Inject emitted transactions if any
|
||||
if (view.rules().enabled(featureHooks))
|
||||
do
|
||||
|
||||
@@ -36,7 +36,6 @@ Cron::makeTxConsequences(PreflightContext const& ctx)
|
||||
return TxConsequences{ctx.tx, TxConsequences::normal};
|
||||
}
|
||||
|
||||
|
||||
NotTEC
|
||||
Cron::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
@@ -76,10 +75,9 @@ Cron::preflight(PreflightContext const& ctx)
|
||||
return temBAD_SEQUENCE;
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
|
||||
TER
|
||||
Cron::preclaim(PreclaimContext const& ctx)
|
||||
{
|
||||
@@ -112,7 +110,7 @@ Cron::doApply()
|
||||
}
|
||||
|
||||
uint256 ptr = sle->getFieldH256(sfCron);
|
||||
Keylet klOld {ltCRON, ptr};
|
||||
Keylet klOld{ltCRON, ptr};
|
||||
auto sleCron = view.peek(klOld);
|
||||
if (!sleCron)
|
||||
{
|
||||
@@ -122,7 +120,7 @@ Cron::doApply()
|
||||
|
||||
uint32_t delay = sleCron->getFieldU32(sfDelaySeconds);
|
||||
uint32_t recur = sleCron->getFieldU32(sfRepeatCount);
|
||||
|
||||
|
||||
uint32_t currentTime = view.parentCloseTime().time_since_epoch().count();
|
||||
|
||||
// do all this sanity checking before we modify the ledger...
|
||||
@@ -134,11 +132,12 @@ Cron::doApply()
|
||||
// if there are further crons to do then a new one is created at the next
|
||||
// time point
|
||||
|
||||
if (!view.dirRemove(keylet::ownerDir(id), (*sleCron)[sfOwnerNode], klOld, false))
|
||||
if (!view.dirRemove(
|
||||
keylet::ownerDir(id), (*sleCron)[sfOwnerNode], klOld, false))
|
||||
return tefBAD_LEDGER;
|
||||
|
||||
view.erase(sleCron);
|
||||
|
||||
|
||||
if (recur == 0)
|
||||
{
|
||||
// already at last execution, stop here
|
||||
@@ -151,9 +150,11 @@ Cron::doApply()
|
||||
// more executions remain, so create a new object
|
||||
|
||||
Keylet klCron = keylet::cron(afterTime, id);
|
||||
|
||||
// insert into owner dir, we don't need to check reserve because we've just deleted an object
|
||||
auto const page = view.dirInsert(keylet::ownerDir(id), klCron, describeOwnerDir(id));
|
||||
|
||||
// insert into owner dir, we don't need to check reserve because we've just
|
||||
// deleted an object
|
||||
auto const page =
|
||||
view.dirInsert(keylet::ownerDir(id), klCron, describeOwnerDir(id));
|
||||
if (!page)
|
||||
return tecDIR_FULL;
|
||||
|
||||
@@ -164,7 +165,7 @@ Cron::doApply()
|
||||
sleCron->setAccountID(sfOwner, id);
|
||||
|
||||
sle->setFieldH256(sfCron, klCron.key);
|
||||
|
||||
|
||||
view.insert(sleCron);
|
||||
view.update(sle);
|
||||
|
||||
|
||||
@@ -50,7 +50,6 @@ public:
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
@@ -36,7 +36,6 @@ SetCron::makeTxConsequences(PreflightContext const& ctx)
|
||||
return TxConsequences{ctx.tx, TxConsequences::normal};
|
||||
}
|
||||
|
||||
|
||||
NotTEC
|
||||
SetCron::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
@@ -60,17 +59,17 @@ SetCron::preflight(PreflightContext const& ctx)
|
||||
// D- - Set Cron (once off) with Delay only (repat implicitly 0)
|
||||
// -R - Invalid
|
||||
// -- - Clear any existing cron (succeeds even if there isn't one)
|
||||
|
||||
|
||||
if (tx.isFieldPresent(sfRepeatCount) && !tx.isFieldPresent(sfDelaySeconds))
|
||||
{
|
||||
JLOG(j.warn()) << "SetCron: DelaySeconds must also be specified when RepeatCount is present.";
|
||||
JLOG(j.warn()) << "SetCron: DelaySeconds must also be specified when "
|
||||
"RepeatCount is present.";
|
||||
return temMALFORMED;
|
||||
}
|
||||
|
||||
return preflight2(ctx);
|
||||
}
|
||||
|
||||
|
||||
TER
|
||||
SetCron::preclaim(PreclaimContext const& ctx)
|
||||
{
|
||||
@@ -103,17 +102,19 @@ SetCron::preclaim(PreclaimContext const& ctx)
|
||||
auto delay = ctx.tx.getFieldU32(sfDelaySeconds);
|
||||
if (delay > 1209600UL /* 14 days in seconds */)
|
||||
{
|
||||
JLOG(j.debug()) << "SetCron: DelaySeconds was too high. (max 14 days in seconds).";
|
||||
JLOG(j.debug())
|
||||
<< "SetCron: DelaySeconds was too high. (max 14 days in seconds).";
|
||||
return tecDELAY_OR_REPEAT_COUNT_TOO_LARGE;
|
||||
}
|
||||
|
||||
if (!hasRepeat)
|
||||
return tesSUCCESS;
|
||||
|
||||
|
||||
auto recur = ctx.tx.getFieldU32(sfRepeatCount);
|
||||
if (recur > 256)
|
||||
{
|
||||
JLOG(j.debug()) << "SetCron: RepeatCount too high. Limit is 256. Issue new SetCron to increase.";
|
||||
JLOG(j.debug()) << "SetCron: RepeatCount too high. Limit is 256. Issue "
|
||||
"new SetCron to increase.";
|
||||
return tecDELAY_OR_REPEAT_COUNT_TOO_LARGE;
|
||||
}
|
||||
|
||||
@@ -131,10 +132,11 @@ SetCron::doApply()
|
||||
if (isDelete && tx.isFieldPresent(sfRepeatCount))
|
||||
return tefINTERNAL;
|
||||
|
||||
// delay can be zero, in which case the cron will usually execute next ledger.
|
||||
uint32_t delay {0};
|
||||
uint32_t recur {0};
|
||||
|
||||
// delay can be zero, in which case the cron will usually execute next
|
||||
// ledger.
|
||||
uint32_t delay{0};
|
||||
uint32_t recur{0};
|
||||
|
||||
if (!isDelete)
|
||||
{
|
||||
delay = tx.getFieldU32(sfDelaySeconds);
|
||||
@@ -150,7 +152,6 @@ SetCron::doApply()
|
||||
if (afterTime < currentTime)
|
||||
return tefINTERNAL;
|
||||
|
||||
|
||||
AccountID const& id = tx.getAccountID(sfAccount);
|
||||
auto sle = view.peek(keylet::account(id));
|
||||
if (!sle)
|
||||
@@ -161,7 +162,7 @@ SetCron::doApply()
|
||||
|
||||
if (sle->isFieldPresent(sfCron))
|
||||
{
|
||||
Keylet klOld {ltCRON, sle->getFieldH256(sfCron)};
|
||||
Keylet klOld{ltCRON, sle->getFieldH256(sfCron)};
|
||||
|
||||
auto sleCron = view.peek(klOld);
|
||||
if (!sleCron)
|
||||
@@ -169,14 +170,16 @@ SetCron::doApply()
|
||||
JLOG(j_.warn()) << "SetCron: Cron object didn't exist.";
|
||||
return tefBAD_LEDGER;
|
||||
}
|
||||
|
||||
if (safe_cast<TxType>(sleCron->getFieldU16(sfLedgerEntryType)) != ltCRON)
|
||||
|
||||
if (safe_cast<TxType>(sleCron->getFieldU16(sfLedgerEntryType)) !=
|
||||
ltCRON)
|
||||
{
|
||||
JLOG(j_.warn()) << "SetCron: sfCron pointed to non-cron object!!";
|
||||
return tefBAD_LEDGER;
|
||||
}
|
||||
|
||||
if (!view.dirRemove(keylet::ownerDir(id), (*sleCron)[sfOwnerNode], klOld, false))
|
||||
if (!view.dirRemove(
|
||||
keylet::ownerDir(id), (*sleCron)[sfOwnerNode], klOld, false))
|
||||
{
|
||||
JLOG(j_.warn()) << "SetCron: Ownerdir bad. " << id;
|
||||
return tefBAD_LEDGER;
|
||||
@@ -187,15 +190,16 @@ SetCron::doApply()
|
||||
sle->makeFieldAbsent(sfCron);
|
||||
}
|
||||
|
||||
// if the operation is a delete (no delay or recur specified then stop here.)
|
||||
// if the operation is a delete (no delay or recur specified then stop
|
||||
// here.)
|
||||
if (isDelete)
|
||||
{
|
||||
view.update(sle);
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
// execution to here means we're creating a new Cron object and adding it to the
|
||||
// user's owner dir
|
||||
// execution to here means we're creating a new Cron object and adding it to
|
||||
// the user's owner dir
|
||||
|
||||
Keylet klCron = keylet::cron(afterTime, id);
|
||||
|
||||
@@ -211,26 +215,26 @@ SetCron::doApply()
|
||||
|
||||
if (afterFee > mPriorBalance || afterFee < reserve)
|
||||
return tecINSUFFICIENT_RESERVE;
|
||||
|
||||
|
||||
// add to owner dir
|
||||
auto const page = view.dirInsert(keylet::ownerDir(id), klCron, describeOwnerDir(id));
|
||||
auto const page =
|
||||
view.dirInsert(keylet::ownerDir(id), klCron, describeOwnerDir(id));
|
||||
if (!page)
|
||||
return tecDIR_FULL;
|
||||
|
||||
|
||||
adjustOwnerCount(view, sle, 1, j_);
|
||||
}
|
||||
|
||||
std::shared_ptr<SLE> sleCron = alreadyExists
|
||||
? view.peek(klCron)
|
||||
: std::make_shared<SLE>(klCron);
|
||||
|
||||
// set the fields
|
||||
std::shared_ptr<SLE> sleCron =
|
||||
alreadyExists ? view.peek(klCron) : std::make_shared<SLE>(klCron);
|
||||
|
||||
// set the fields
|
||||
sleCron->setFieldU32(sfDelaySeconds, delay);
|
||||
sleCron->setFieldU32(sfRepeatCount, recur);
|
||||
sleCron->setAccountID(sfOwner, id);
|
||||
|
||||
sle->setFieldH256(sfCron, klCron.key);
|
||||
|
||||
|
||||
view.update(sle);
|
||||
|
||||
if (alreadyExists)
|
||||
|
||||
@@ -50,7 +50,6 @@ public:
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <ripple/app/tx/impl/CreateCheck.h>
|
||||
#include <ripple/app/tx/impl/CreateOffer.h>
|
||||
#include <ripple/app/tx/impl/CreateTicket.h>
|
||||
#include <ripple/app/tx/impl/Cron.h>
|
||||
#include <ripple/app/tx/impl/DeleteAccount.h>
|
||||
#include <ripple/app/tx/impl/DepositPreauth.h>
|
||||
#include <ripple/app/tx/impl/Escrow.h>
|
||||
@@ -43,6 +44,7 @@
|
||||
#include <ripple/app/tx/impl/Payment.h>
|
||||
#include <ripple/app/tx/impl/Remit.h>
|
||||
#include <ripple/app/tx/impl/SetAccount.h>
|
||||
#include <ripple/app/tx/impl/SetCron.h>
|
||||
#include <ripple/app/tx/impl/SetHook.h>
|
||||
#include <ripple/app/tx/impl/SetRegularKey.h>
|
||||
#include <ripple/app/tx/impl/SetRemarks.h>
|
||||
@@ -181,6 +183,8 @@ invoke_preflight(PreflightContext const& ctx)
|
||||
case ttURITOKEN_CREATE_SELL_OFFER:
|
||||
case ttURITOKEN_CANCEL_SELL_OFFER:
|
||||
return invoke_preflight_helper<URIToken>(ctx);
|
||||
case ttCRON_SET:
|
||||
return invoke_preflight_helper<SetCron>(ctx);
|
||||
default:
|
||||
assert(false);
|
||||
return {temUNKNOWN, TxConsequences{temUNKNOWN}};
|
||||
@@ -306,6 +310,8 @@ invoke_preclaim(PreclaimContext const& ctx)
|
||||
case ttURITOKEN_CREATE_SELL_OFFER:
|
||||
case ttURITOKEN_CANCEL_SELL_OFFER:
|
||||
return invoke_preclaim<URIToken>(ctx);
|
||||
case ttCRON_SET:
|
||||
return invoke_preclaim<SetCron>(ctx);
|
||||
default:
|
||||
assert(false);
|
||||
return temUNKNOWN;
|
||||
@@ -393,6 +399,8 @@ invoke_calculateBaseFee(ReadView const& view, STTx const& tx)
|
||||
case ttURITOKEN_CREATE_SELL_OFFER:
|
||||
case ttURITOKEN_CANCEL_SELL_OFFER:
|
||||
return URIToken::calculateBaseFee(view, tx);
|
||||
case ttCRON_SET:
|
||||
return SetCron::calculateBaseFee(view, tx);
|
||||
default:
|
||||
return XRPAmount{0};
|
||||
}
|
||||
@@ -586,6 +594,10 @@ invoke_apply(ApplyContext& ctx)
|
||||
URIToken p(ctx);
|
||||
return p();
|
||||
}
|
||||
case ttCRON_SET: {
|
||||
SetCron p(ctx);
|
||||
return p();
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
return {temUNKNOWN, false};
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace detail {
|
||||
// Feature.cpp. Because it's only used to reserve storage, and determine how
|
||||
// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
|
||||
// the actual number of amendments. A LogicError on startup will verify this.
|
||||
static constexpr std::size_t numFeatures = 85;
|
||||
static constexpr std::size_t numFeatures = 86;
|
||||
|
||||
/** Amendments that this server supports and the default voting behavior.
|
||||
Whether they are enabled depends on the Rules defined in the validated
|
||||
@@ -373,6 +373,7 @@ extern uint256 const fixProvisionalDoubleThreading;
|
||||
extern uint256 const featureClawback;
|
||||
extern uint256 const featureDeepFreeze;
|
||||
extern uint256 const featureIOUIssuerWeakTSH;
|
||||
extern uint256 const featureCron;
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
|
||||
@@ -297,6 +297,9 @@ import_vlseq(PublicKey const& key) noexcept;
|
||||
Keylet
|
||||
uritoken(AccountID const& issuer, Blob const& uri);
|
||||
|
||||
Keylet
|
||||
cron(uint32_t timestamp, AccountID const& id);
|
||||
|
||||
} // namespace keylet
|
||||
|
||||
// Everything below is deprecated and should be removed in favor of keylets:
|
||||
|
||||
@@ -58,6 +58,12 @@ enum LedgerEntryType : std::uint16_t
|
||||
*/
|
||||
ltACCOUNT_ROOT = 0x0061,
|
||||
|
||||
/** A ledger object representing a scheduled cron execution on an account.
|
||||
|
||||
\sa keylet::cron
|
||||
*/
|
||||
ltCRON = 0x0041,
|
||||
|
||||
/** A ledger object which contains a list of object identifiers.
|
||||
|
||||
\sa keylet::page, keylet::quality, keylet::book, keylet::next and
|
||||
|
||||
@@ -410,6 +410,8 @@ extern SF_UINT32 const sfRewardLgrLast;
|
||||
extern SF_UINT32 const sfFirstNFTokenSequence;
|
||||
extern SF_UINT32 const sfImportSequence;
|
||||
extern SF_UINT32 const sfXahauActivationLgrSeq;
|
||||
extern SF_UINT32 const sfDelaySeconds;
|
||||
extern SF_UINT32 const sfRepeatCount;
|
||||
|
||||
// 64-bit integers (common)
|
||||
extern SF_UINT64 const sfIndexNext;
|
||||
@@ -486,6 +488,7 @@ extern SF_UINT256 const sfURITokenID;
|
||||
extern SF_UINT256 const sfGovernanceFlags;
|
||||
extern SF_UINT256 const sfGovernanceMarks;
|
||||
extern SF_UINT256 const sfEmittedTxnID;
|
||||
extern SF_UINT256 const sfCron;
|
||||
|
||||
// currency amount (common)
|
||||
extern SF_AMOUNT const sfAmount;
|
||||
|
||||
@@ -343,6 +343,7 @@ enum TECcodes : TERUnderlyingType {
|
||||
tecINSUF_RESERVE_SELLER = 187,
|
||||
tecIMMUTABLE = 188,
|
||||
tecTOO_MANY_REMARKS = 189,
|
||||
tecDELAY_OR_REPEAT_COUNT_TOO_LARGE = 200,
|
||||
tecLAST_POSSIBLE_ENTRY = 255,
|
||||
};
|
||||
|
||||
|
||||
@@ -149,6 +149,12 @@ enum TxType : std::uint16_t
|
||||
ttURITOKEN_CREATE_SELL_OFFER = 48,
|
||||
ttURITOKEN_CANCEL_SELL_OFFER = 49,
|
||||
|
||||
/* A pseudo-txn alarm signal for invoking a hook, emitted by validators after alarm set conditions are met */
|
||||
ttCRON = 92,
|
||||
|
||||
/* Sechedule an alarm for later */
|
||||
ttCRON_SET = 93,
|
||||
|
||||
/* A note attaching transactor that allows the owner or issuer (on a object by object basis) to attach remarks */
|
||||
ttREMARKS_SET = 94,
|
||||
|
||||
|
||||
@@ -479,6 +479,7 @@ REGISTER_FEATURE(Clawback, Supported::yes, VoteBehavior::De
|
||||
REGISTER_FIX (fixProvisionalDoubleThreading, Supported::yes, VoteBehavior::DefaultYes);
|
||||
REGISTER_FEATURE(DeepFreeze, Supported::yes, VoteBehavior::DefaultNo);
|
||||
REGISTER_FEATURE(IOUIssuerWeakTSH, Supported::yes, VoteBehavior::DefaultNo);
|
||||
REGISTER_FEATURE(Cron, Supported::yes, VoteBehavior::DefaultNo);
|
||||
|
||||
// The following amendments are obsolete, but must remain supported
|
||||
// because they could potentially get enabled.
|
||||
|
||||
@@ -72,6 +72,7 @@ enum class LedgerNameSpace : std::uint16_t {
|
||||
URI_TOKEN = 'U',
|
||||
IMPORT_VLSEQ = 'I',
|
||||
UNL_REPORT = 'R',
|
||||
CRON = 'A',
|
||||
|
||||
// No longer used or supported. Left here to reserve the space
|
||||
// to avoid accidental reuse.
|
||||
@@ -443,6 +444,28 @@ uritoken(AccountID const& issuer, Blob const& uri)
|
||||
LedgerNameSpace::URI_TOKEN, issuer, Slice{uri.data(), uri.size()})};
|
||||
}
|
||||
|
||||
Keylet
|
||||
cron(uint32_t timestamp, AccountID const& id)
|
||||
{
|
||||
static const uint256 ns = indexHash(LedgerNameSpace::CRON);
|
||||
|
||||
uint8_t h[32];
|
||||
|
||||
// first 8 bytes are the namespacing
|
||||
std::memcpy(h, ns.data(), 8);
|
||||
|
||||
// next 4 bytes are the timestamp in BE
|
||||
h[8] = static_cast<uint8_t>((timestamp >> 24) & 0xFFU);
|
||||
h[9] = static_cast<uint8_t>((timestamp >> 16) & 0xFFU);
|
||||
h[10] = static_cast<uint8_t>((timestamp >> 8) & 0xFFU);
|
||||
h[11] = static_cast<uint8_t>((timestamp >> 0) & 0xFFU);
|
||||
|
||||
// final 20 bytes are account ID
|
||||
std::memcpy(h + 12, id.data(), 20);
|
||||
|
||||
return {ltCRON, uint256::fromVoid(h)};
|
||||
}
|
||||
|
||||
} // namespace keylet
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
@@ -68,6 +68,7 @@ LedgerFormats::LedgerFormats()
|
||||
{sfGovernanceMarks, soeOPTIONAL},
|
||||
{sfAccountIndex, soeOPTIONAL},
|
||||
{sfTouchCount, soeOPTIONAL},
|
||||
{sfCron, soeOPTIONAL},
|
||||
},
|
||||
commonFields);
|
||||
|
||||
@@ -366,6 +367,15 @@ LedgerFormats::LedgerFormats()
|
||||
},
|
||||
commonFields);
|
||||
|
||||
add(jss::Cron,
|
||||
ltCRON,
|
||||
{
|
||||
{sfOwner, soeREQUIRED},
|
||||
{sfDelaySeconds, soeREQUIRED},
|
||||
{sfRepeatCount, soeREQUIRED}
|
||||
},
|
||||
commonFields);
|
||||
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
|
||||
@@ -157,6 +157,8 @@ CONSTRUCT_TYPED_SFIELD(sfLockCount, "LockCount", UINT32,
|
||||
|
||||
CONSTRUCT_TYPED_SFIELD(sfFirstNFTokenSequence, "FirstNFTokenSequence", UINT32, 50);
|
||||
|
||||
CONSTRUCT_TYPED_SFIELD(sfRepeatCount, "RepeatCount", UINT32, 94);
|
||||
CONSTRUCT_TYPED_SFIELD(sfDelaySeconds, "DelaySeconds", UINT32, 95);
|
||||
CONSTRUCT_TYPED_SFIELD(sfXahauActivationLgrSeq, "XahauActivationLgrSeq",UINT32, 96);
|
||||
CONSTRUCT_TYPED_SFIELD(sfImportSequence, "ImportSequence", UINT32, 97);
|
||||
CONSTRUCT_TYPED_SFIELD(sfRewardTime, "RewardTime", UINT32, 98);
|
||||
@@ -239,6 +241,7 @@ CONSTRUCT_TYPED_SFIELD(sfGovernanceFlags, "GovernanceFlags", UINT256,
|
||||
CONSTRUCT_TYPED_SFIELD(sfGovernanceMarks, "GovernanceMarks", UINT256, 98);
|
||||
CONSTRUCT_TYPED_SFIELD(sfEmittedTxnID, "EmittedTxnID", UINT256, 97);
|
||||
CONSTRUCT_TYPED_SFIELD(sfHookCanEmit, "HookCanEmit", UINT256, 96);
|
||||
CONSTRUCT_TYPED_SFIELD(sfCron, "Cron", UINT256, 95);
|
||||
|
||||
// currency amount (common)
|
||||
CONSTRUCT_TYPED_SFIELD(sfAmount, "Amount", AMOUNT, 1);
|
||||
|
||||
@@ -615,7 +615,7 @@ isPseudoTx(STObject const& tx)
|
||||
|
||||
auto tt = safe_cast<TxType>(*t);
|
||||
return tt == ttAMENDMENT || tt == ttFEE || tt == ttUNL_MODIFY ||
|
||||
tt == ttEMIT_FAILURE || tt == ttUNL_REPORT;
|
||||
tt == ttEMIT_FAILURE || tt == ttUNL_REPORT || tt == ttCRON;
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
@@ -472,6 +472,22 @@ TxFormats::TxFormats()
|
||||
{sfTicketSequence, soeOPTIONAL},
|
||||
},
|
||||
commonFields);
|
||||
|
||||
add(jss::Cron,
|
||||
ttCRON,
|
||||
{
|
||||
{sfOwner, soeREQUIRED},
|
||||
{sfLedgerSequence, soeREQUIRED},
|
||||
},
|
||||
commonFields);
|
||||
|
||||
add(jss::SetCron,
|
||||
ttCRON_SET,
|
||||
{
|
||||
{sfDelaySeconds, soeOPTIONAL},
|
||||
{sfRepeatCount, soeOPTIONAL},
|
||||
},
|
||||
commonFields);
|
||||
}
|
||||
|
||||
TxFormats const&
|
||||
|
||||
@@ -50,15 +50,17 @@ JSS(AccountSet); // transaction type.
|
||||
JSS(Amendments); // ledger type.
|
||||
JSS(Amount); // in: TransactionSign; field.
|
||||
JSS(Authorize); // field
|
||||
JSS(Alarm);
|
||||
JSS(Blob);
|
||||
JSS(Check); // ledger type.
|
||||
JSS(CheckCancel); // transaction type.
|
||||
JSS(CheckCash); // transaction type.
|
||||
JSS(CheckCreate); // transaction type.
|
||||
JSS(ClaimReward); // transaction type.
|
||||
JSS(Clawback); // transaction type.
|
||||
JSS(ClearFlag); // field.
|
||||
JSS(CreateCode); // field.
|
||||
JSS(Check); // ledger type.
|
||||
JSS(CheckCancel); // transaction type.
|
||||
JSS(CheckCash); // transaction type.
|
||||
JSS(CheckCreate); // transaction type.
|
||||
JSS(ClaimReward); // transaction type.
|
||||
JSS(Clawback); // transaction type.
|
||||
JSS(ClearFlag); // field.
|
||||
JSS(CreateCode); // field.
|
||||
JSS(Cron);
|
||||
JSS(DeliverMin); // in: TransactionSign
|
||||
JSS(DepositPreauth); // transaction and ledger type.
|
||||
JSS(Destination); // in: TransactionSign; field.
|
||||
@@ -95,40 +97,42 @@ JSS(isSigningField); // out: RPC server_definitions
|
||||
JSS(isVLEncoded); // out: RPC server_definitions
|
||||
JSS(Import);
|
||||
JSS(ImportVLSequence);
|
||||
JSS(Invalid); //
|
||||
JSS(Invoke); // transaction type
|
||||
JSS(InvoiceID); // field
|
||||
JSS(LastLedgerSequence); // in: TransactionSign; field
|
||||
JSS(LedgerHashes); // ledger type.
|
||||
JSS(LimitAmount); // field.
|
||||
JSS(NetworkID); // field.
|
||||
JSS(NFTokenBurn); // transaction type.
|
||||
JSS(NFTokenMint); // transaction type.
|
||||
JSS(NFTokenOffer); // ledger type.
|
||||
JSS(NFTokenAcceptOffer); // transaction type.
|
||||
JSS(NFTokenCancelOffer); // transaction type.
|
||||
JSS(NFTokenCreateOffer); // transaction type.
|
||||
JSS(NFTokenPage); // ledger type.
|
||||
JSS(Offer); // ledger type.
|
||||
JSS(OfferCancel); // transaction type.
|
||||
JSS(OfferCreate); // transaction type.
|
||||
JSS(OfferSequence); // field.
|
||||
JSS(Paths); // in/out: TransactionSign
|
||||
JSS(PayChannel); // ledger type.
|
||||
JSS(Payment); // transaction type.
|
||||
JSS(PaymentChannelClaim); // transaction type.
|
||||
JSS(PaymentChannelCreate); // transaction type.
|
||||
JSS(PaymentChannelFund); // transaction type.
|
||||
JSS(Remit); // transaction type.
|
||||
JSS(RippleState); // ledger type.
|
||||
JSS(SLE_hit_rate); // out: GetCounts.
|
||||
JSS(SetFee); // transaction type.
|
||||
JSS(SetRemarks); // transaction type
|
||||
JSS(UNLModify); // transaction type.
|
||||
JSS(UNLReport); // transaction type.
|
||||
JSS(SettleDelay); // in: TransactionSign
|
||||
JSS(SendMax); // in: TransactionSign
|
||||
JSS(Sequence); // in/out: TransactionSign; field.
|
||||
JSS(Invalid); //
|
||||
JSS(Invoke); // transaction type
|
||||
JSS(InvoiceID); // field
|
||||
JSS(LastLedgerSequence); // in: TransactionSign; field
|
||||
JSS(LedgerHashes); // ledger type.
|
||||
JSS(LimitAmount); // field.
|
||||
JSS(NetworkID); // field.
|
||||
JSS(NFTokenBurn); // transaction type.
|
||||
JSS(NFTokenMint); // transaction type.
|
||||
JSS(NFTokenOffer); // ledger type.
|
||||
JSS(NFTokenAcceptOffer); // transaction type.
|
||||
JSS(NFTokenCancelOffer); // transaction type.
|
||||
JSS(NFTokenCreateOffer); // transaction type.
|
||||
JSS(NFTokenPage); // ledger type.
|
||||
JSS(Offer); // ledger type.
|
||||
JSS(OfferCancel); // transaction type.
|
||||
JSS(OfferCreate); // transaction type.
|
||||
JSS(OfferSequence); // field.
|
||||
JSS(Paths); // in/out: TransactionSign
|
||||
JSS(PayChannel); // ledger type.
|
||||
JSS(Payment); // transaction type.
|
||||
JSS(PaymentChannelClaim); // transaction type.
|
||||
JSS(PaymentChannelCreate); // transaction type.
|
||||
JSS(PaymentChannelFund); // transaction type.
|
||||
JSS(Remit); // transaction type.
|
||||
JSS(RippleState); // ledger type.
|
||||
JSS(SLE_hit_rate); // out: GetCounts.
|
||||
JSS(SetFee); // transaction type.
|
||||
JSS(SetRemarks); // transaction type
|
||||
JSS(UNLModify); // transaction type.
|
||||
JSS(UNLReport); // transaction type.
|
||||
JSS(SettleDelay); // in: TransactionSign
|
||||
JSS(SendMax); // in: TransactionSign
|
||||
JSS(Sequence); // in/out: TransactionSign; field.
|
||||
JSS(SetAlarm);
|
||||
JSS(SetCron);
|
||||
JSS(SetFlag); // field.
|
||||
JSS(SetRegularKey); // transaction type.
|
||||
JSS(SetHook); // transaction type.
|
||||
|
||||
Reference in New Issue
Block a user