mirror of
https://github.com/Xahau/xahaud.git
synced 2026-01-12 10:45:15 +00:00
Compare commits
4 Commits
featRNG
...
HookAdmini
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0825bddd87 | ||
|
|
07008da032 | ||
|
|
90b009d63c | ||
|
|
19e2036115 |
@@ -192,6 +192,7 @@
|
||||
#define sfNFTokenMinter ((8U << 16U) + 9U)
|
||||
#define sfEmitCallback ((8U << 16U) + 10U)
|
||||
#define sfHookAccount ((8U << 16U) + 16U)
|
||||
#define sfHookAdministrator ((8U << 16U) + 98U)
|
||||
#define sfInform ((8U << 16U) + 99U)
|
||||
#define sfIndexes ((19U << 16U) + 1U)
|
||||
#define sfHashes ((19U << 16U) + 2U)
|
||||
|
||||
@@ -267,6 +267,9 @@ DeleteAccount::preclaim(PreclaimContext const& ctx)
|
||||
if (sleAccount->isFieldPresent(sfHookNamespaces) ||
|
||||
sleAccount->isFieldPresent(sfHooks))
|
||||
return tecHAS_OBLIGATIONS;
|
||||
|
||||
if (sleAccount->isFieldPresent(sfHookAdministrator))
|
||||
return tecHAS_OBLIGATIONS;
|
||||
}
|
||||
|
||||
// When fixNFTokenRemint is enabled, we don't allow an account to be
|
||||
|
||||
@@ -897,7 +897,9 @@ ValidNewAccountRoot::finalize(
|
||||
}
|
||||
|
||||
if ((tt == ttPAYMENT || tt == ttIMPORT || tt == ttGENESIS_MINT ||
|
||||
tt == ttREMIT) &&
|
||||
tt == ttREMIT ||
|
||||
(tt == ttHOOK_SET &&
|
||||
view.rules().enabled(featureHookAdministrator))) &&
|
||||
isTesSuccess(result))
|
||||
{
|
||||
std::uint32_t const startingSeq{
|
||||
|
||||
@@ -628,6 +628,21 @@ SetHook::calculateBaseFee(ReadView const& view, STTx const& tx)
|
||||
TER
|
||||
SetHook::preclaim(ripple::PreclaimContext const& ctx)
|
||||
{
|
||||
if (ctx.tx.isFieldPresent(sfHookAdministrator))
|
||||
{
|
||||
auto const& administrator = ctx.tx.getAccountID(sfHookAdministrator);
|
||||
auto const& sle = ctx.view.read(keylet::account(administrator));
|
||||
if (!sle)
|
||||
return tecNO_DST;
|
||||
|
||||
if (!sle->isFieldPresent(sfHookAdministrator))
|
||||
return tecNO_PERMISSION;
|
||||
|
||||
if (sle->getAccountID(sfHookAdministrator) !=
|
||||
ctx.tx.getAccountID(sfAccount))
|
||||
return tecNO_PERMISSION;
|
||||
}
|
||||
|
||||
auto const& hookSets = ctx.tx.getFieldArray(sfHooks);
|
||||
|
||||
for (auto const& hookSetObj : hookSets)
|
||||
@@ -667,12 +682,46 @@ SetHook::preflight(PreflightContext const& ctx)
|
||||
return ret;
|
||||
|
||||
if (ctx.rules.enabled(fixInvalidTxFlags) &&
|
||||
ctx.tx.getFlags() & tfUniversalMask)
|
||||
ctx.tx.getFlags() & tfSetHookMask)
|
||||
{
|
||||
JLOG(ctx.j.trace()) << "SetHook: Invalid flags set.";
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
if (ctx.tx.isFlag(tfNewAccount) &&
|
||||
!ctx.rules.enabled(featureHookAdministrator))
|
||||
{
|
||||
JLOG(ctx.j.trace()) << "SetHook: New account flag set but hook "
|
||||
"administrator amendment is not enabled.";
|
||||
return temDISABLED;
|
||||
}
|
||||
|
||||
if (ctx.tx.isFieldPresent(sfDestination))
|
||||
{
|
||||
if (!ctx.rules.enabled(featureHookAdministrator))
|
||||
{
|
||||
JLOG(ctx.j.trace())
|
||||
<< "HookSet: Hook administrator amendment not enabled.";
|
||||
return temDISABLED;
|
||||
}
|
||||
|
||||
if (ctx.tx.isFlag(tfNewAccount))
|
||||
{
|
||||
JLOG(ctx.j.trace())
|
||||
<< "HookSet: Both new account flag and destination set. "
|
||||
"New account flag and destination cannot be set at the same "
|
||||
"time.";
|
||||
return temMALFORMED;
|
||||
}
|
||||
|
||||
if (ctx.tx.getAccountID(sfDestination) ==
|
||||
ctx.tx.getAccountID(sfAccount))
|
||||
{
|
||||
JLOG(ctx.j.trace()) << "HookSet: Redundant hook administrator.";
|
||||
return temREDUNDANT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ctx.tx.isFieldPresent(sfHooks))
|
||||
{
|
||||
JLOG(ctx.j.trace())
|
||||
@@ -1183,6 +1232,23 @@ struct KeyletComparator
|
||||
}
|
||||
};
|
||||
|
||||
AccountID
|
||||
randomAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey)
|
||||
{
|
||||
// This number must not be changed without an amendment
|
||||
constexpr std::uint16_t maxAccountAttempts = 256;
|
||||
for (std::uint16_t i = 0; i < maxAccountAttempts; ++i)
|
||||
{
|
||||
ripesha_hasher rsh;
|
||||
auto const hash = sha512Half(i, view.info().parentHash, pseudoOwnerKey);
|
||||
rsh(hash.data(), hash.size());
|
||||
AccountID const ret{static_cast<ripesha_hasher::result_type>(rsh)};
|
||||
if (!view.read(keylet::account(ret)))
|
||||
return ret;
|
||||
}
|
||||
return beast::zero;
|
||||
}
|
||||
|
||||
TER
|
||||
SetHook::setHook()
|
||||
{
|
||||
@@ -1202,11 +1268,69 @@ SetHook::setHook()
|
||||
.app = ctx_.app,
|
||||
.rules = ctx_.view().rules()};
|
||||
|
||||
const int blobMax = hook::maxHookWasmSize();
|
||||
auto const accountKeylet = keylet::account(account_);
|
||||
auto const hookKeylet = keylet::hook(account_);
|
||||
auto targetAccount = ctx.tx[~sfDestination].value_or(account_);
|
||||
if (ctx_.tx.isFlag(tfNewAccount))
|
||||
{
|
||||
// create the new account
|
||||
auto const newAccount = randomAccountAddress(ctx_.view(), uint256{});
|
||||
if (newAccount == beast::zero)
|
||||
return tecDUPLICATE;
|
||||
|
||||
auto accountSLE = view().peek(accountKeylet);
|
||||
auto sleNewAccount = std::make_shared<SLE>(keylet::account(newAccount));
|
||||
sleNewAccount->setAccountID(sfAccount, newAccount);
|
||||
sleNewAccount->setFieldAmount(sfBalance, STAmount{});
|
||||
sleNewAccount->setFieldU32(sfOwnerCount, 1); // ltHook
|
||||
std::uint32_t const seqno{
|
||||
ctx_.view().rules().enabled(featureXahauGenesis)
|
||||
? ctx_.view().info().parentCloseTime.time_since_epoch().count()
|
||||
: ctx_.view().rules().enabled(featureDeletableAccounts)
|
||||
? ctx_.view().seq()
|
||||
: 1};
|
||||
sleNewAccount->setFieldU32(sfSequence, seqno);
|
||||
sleNewAccount->setFieldU32(sfFlags, lsfDisableMaster);
|
||||
|
||||
sleNewAccount->setAccountID(sfHookAdministrator, account_);
|
||||
|
||||
auto sleFees = view().peek(keylet::fees());
|
||||
if (sleFees && view().rules().enabled(featureXahauGenesis))
|
||||
{
|
||||
auto actIdx = sleFees->isFieldPresent(sfAccountCount)
|
||||
? sleFees->getFieldU64(sfAccountCount)
|
||||
: 0;
|
||||
sleNewAccount->setFieldU64(sfAccountIndex, actIdx);
|
||||
sleFees->setFieldU64(sfAccountCount, actIdx + 1);
|
||||
view().update(sleFees);
|
||||
}
|
||||
|
||||
// fund AccountReserve + ObjectReserve (ltHook)
|
||||
auto const requiredDrops = ctx_.view().fees().accountReserve(1);
|
||||
|
||||
auto sourceSle = ctx_.view().peek(keylet::account(account_));
|
||||
if (!sourceSle)
|
||||
return tefINTERNAL;
|
||||
|
||||
auto const sourceCurrentReserve = ctx_.view().fees().accountReserve(
|
||||
sourceSle->getFieldU32(sfOwnerCount));
|
||||
|
||||
auto const sourceBalance = sourceSle->getFieldAmount(sfBalance).xrp();
|
||||
|
||||
if (sourceBalance < sourceCurrentReserve + requiredDrops)
|
||||
return tecUNFUNDED;
|
||||
|
||||
sourceSle->setFieldAmount(sfBalance, sourceBalance - requiredDrops);
|
||||
ctx_.view().update(sourceSle);
|
||||
|
||||
sleNewAccount->setFieldAmount(sfBalance, requiredDrops);
|
||||
ctx_.view().insert(sleNewAccount);
|
||||
|
||||
targetAccount = newAccount;
|
||||
}
|
||||
|
||||
const int blobMax = hook::maxHookWasmSize();
|
||||
|
||||
auto const hookKeylet = keylet::hook(targetAccount);
|
||||
|
||||
auto accountSLE = view().peek(keylet::account(targetAccount));
|
||||
|
||||
ripple::STArray newHooks{sfHooks, 8};
|
||||
auto newHookSLE = std::make_shared<SLE>(hookKeylet);
|
||||
|
||||
@@ -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 = 90;
|
||||
static constexpr std::size_t numFeatures = 91;
|
||||
|
||||
/** Amendments that this server supports and the default voting behavior.
|
||||
Whether they are enabled depends on the Rules defined in the validated
|
||||
@@ -378,6 +378,7 @@ extern uint256 const fixInvalidTxFlags;
|
||||
extern uint256 const featureExtendedHookState;
|
||||
extern uint256 const fixCronStacking;
|
||||
extern uint256 const fixHookAPI20251128;
|
||||
extern uint256 const featureHookAdministrator;
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
|
||||
@@ -563,6 +563,7 @@ extern SF_ACCOUNT const sfEmitCallback;
|
||||
extern SF_ACCOUNT const sfHookAccount;
|
||||
extern SF_ACCOUNT const sfNFTokenMinter;
|
||||
extern SF_ACCOUNT const sfInform;
|
||||
extern SF_ACCOUNT const sfHookAdministrator;
|
||||
|
||||
// path set
|
||||
extern SField const sfPaths;
|
||||
|
||||
@@ -184,6 +184,11 @@ constexpr std::uint32_t const tfNFTokenCancelOfferMask = ~(tfUniversal);
|
||||
// NFTokenAcceptOffer flags:
|
||||
constexpr std::uint32_t const tfNFTokenAcceptOfferMask = ~tfUniversal;
|
||||
|
||||
enum SetHookFlags : uint32_t {
|
||||
tfNewAccount = 0x00000001,
|
||||
};
|
||||
constexpr std::uint32_t const tfSetHookMask = ~(tfUniversal | tfNewAccount);
|
||||
|
||||
// URIToken mask
|
||||
constexpr std::uint32_t const tfURITokenMintMask = ~(tfUniversal | tfBurnable);
|
||||
constexpr std::uint32_t const tfURITokenNonMintMask = ~tfUniversal;
|
||||
|
||||
@@ -484,6 +484,7 @@ REGISTER_FIX (fixInvalidTxFlags, Supported::yes, VoteBehavior::De
|
||||
REGISTER_FEATURE(ExtendedHookState, Supported::yes, VoteBehavior::DefaultNo);
|
||||
REGISTER_FIX (fixCronStacking, Supported::yes, VoteBehavior::DefaultYes);
|
||||
REGISTER_FIX (fixHookAPI20251128, Supported::yes, VoteBehavior::DefaultYes);
|
||||
REGISTER_FEATURE(HookAdministrator, Supported::yes, VoteBehavior::DefaultNo);
|
||||
|
||||
// The following amendments are obsolete, but must remain supported
|
||||
// because they could potentially get enabled.
|
||||
|
||||
@@ -70,6 +70,7 @@ LedgerFormats::LedgerFormats()
|
||||
{sfTouchCount, soeOPTIONAL},
|
||||
{sfHookStateScale, soeOPTIONAL},
|
||||
{sfCron, soeOPTIONAL},
|
||||
{sfHookAdministrator, soeOPTIONAL},
|
||||
},
|
||||
commonFields);
|
||||
|
||||
|
||||
@@ -315,6 +315,7 @@ CONSTRUCT_TYPED_SFIELD(sfEmitCallback, "EmitCallback", ACCOUNT,
|
||||
|
||||
// account (uncommon)
|
||||
CONSTRUCT_TYPED_SFIELD(sfHookAccount, "HookAccount", ACCOUNT, 16);
|
||||
CONSTRUCT_TYPED_SFIELD(sfHookAdministrator, "HookAdministrator", ACCOUNT, 98);
|
||||
CONSTRUCT_TYPED_SFIELD(sfInform, "Inform", ACCOUNT, 99);
|
||||
|
||||
// vector of 256-bit
|
||||
|
||||
@@ -324,6 +324,7 @@ TxFormats::TxFormats()
|
||||
{
|
||||
{sfHooks, soeREQUIRED},
|
||||
{sfTicketSequence, soeOPTIONAL},
|
||||
{sfDestination, soeOPTIONAL},
|
||||
},
|
||||
commonFields);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user