mirror of
https://github.com/Xahau/xahaud.git
synced 2026-06-13 13:46:43 +00:00
Compare commits
25 Commits
dev
...
HookAdmini
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5fdae6d74 | ||
|
|
9ffd130e2e | ||
|
|
60bb552780 | ||
|
|
8cfd5c3eec | ||
|
|
cd00ed72d8 | ||
|
|
05a3e04f2d | ||
|
|
66f7294120 | ||
|
|
7f6ac75617 | ||
|
|
4150f0383c | ||
|
|
25123b370a | ||
|
|
f90ed41802 | ||
|
|
8c4c158d3a | ||
|
|
2d2951875d | ||
|
|
9bfca63574 | ||
|
|
1ba444ae7f | ||
|
|
f96d9b6e51 | ||
|
|
8cfee6c8a3 | ||
|
|
8673599d2b | ||
|
|
ec65e622aa | ||
|
|
65837f49e1 | ||
|
|
e5b21f026e | ||
|
|
0825bddd87 | ||
|
|
07008da032 | ||
|
|
90b009d63c | ||
|
|
19e2036115 |
@@ -242,6 +242,7 @@
|
||||
#define sfLockingChainDoor ((8U << 16U) + 22U)
|
||||
#define sfIssuingChainDoor ((8U << 16U) + 23U)
|
||||
#define sfSubject ((8U << 16U) + 24U)
|
||||
#define sfHookAdministrator ((8U << 16U) + 98U)
|
||||
#define sfInform ((8U << 16U) + 99U)
|
||||
#define sfIndexes ((19U << 16U) + 1U)
|
||||
#define sfHashes ((19U << 16U) + 2U)
|
||||
|
||||
@@ -100,6 +100,10 @@ enum NFTokenCreateOfferFlags : uint32_t {
|
||||
tfSellNFToken = 0x00000001,
|
||||
};
|
||||
|
||||
enum SetHookFlags : uint32_t {
|
||||
tfNewAccount = 0x00000001,
|
||||
};
|
||||
|
||||
enum ClaimRewardFlags : uint32_t {
|
||||
tfOptOut = 0x00000001,
|
||||
};
|
||||
|
||||
@@ -223,6 +223,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;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
// If you add an amendment here, then do not forget to increment `numFeatures`
|
||||
// in include/xrpl/protocol/Feature.h.
|
||||
|
||||
XRPL_FEATURE(HookAdministrator, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (GuardDepth32, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(NamedHooks, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(IOURewardClaim, Supported::yes, VoteBehavior::DefaultNo)
|
||||
|
||||
@@ -262,6 +262,7 @@ LEDGER_ENTRY(ltACCOUNT_ROOT, 0x0061, AccountRoot, account, ({
|
||||
{sfHookStateScale, soeOPTIONAL},
|
||||
{sfCron, soeOPTIONAL},
|
||||
{sfAMMID, soeOPTIONAL},
|
||||
{sfHookAdministrator, soeOPTIONAL},
|
||||
}))
|
||||
|
||||
/** A ledger object which contains a list of object identifiers.
|
||||
|
||||
@@ -319,6 +319,7 @@ TYPED_SFIELD(sfAttestationRewardAccount, ACCOUNT, 21)
|
||||
TYPED_SFIELD(sfLockingChainDoor, ACCOUNT, 22)
|
||||
TYPED_SFIELD(sfIssuingChainDoor, ACCOUNT, 23)
|
||||
TYPED_SFIELD(sfSubject, ACCOUNT, 24)
|
||||
TYPED_SFIELD(sfHookAdministrator, ACCOUNT, 98)
|
||||
TYPED_SFIELD(sfInform, ACCOUNT, 99)
|
||||
|
||||
// vector of 256-bit
|
||||
|
||||
@@ -195,6 +195,7 @@ TRANSACTION(ttACCOUNT_DELETE, 21, AccountDelete, ({
|
||||
/** This transaction type installs a hook. */
|
||||
TRANSACTION(ttHOOK_SET, 22, SetHook, ({
|
||||
{sfHooks, soeREQUIRED},
|
||||
{sfDestination, soeOPTIONAL},
|
||||
}))
|
||||
|
||||
/** This transaction mints a new NFT. */
|
||||
|
||||
@@ -330,6 +330,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
|
||||
|
||||
@@ -1037,7 +1037,9 @@ ValidNewAccountRoot::finalize(
|
||||
if ((tt == ttPAYMENT || tt == ttIMPORT || tt == ttGENESIS_MINT ||
|
||||
tt == ttREMIT || tt == ttAMM_CREATE ||
|
||||
tt == ttXCHAIN_ADD_CLAIM_ATTESTATION ||
|
||||
tt == ttXCHAIN_ADD_ACCOUNT_CREATE_ATTESTATION) &&
|
||||
tt == ttXCHAIN_ADD_ACCOUNT_CREATE_ATTESTATION ||
|
||||
(tt == ttHOOK_SET &&
|
||||
view.rules().enabled(featureHookAdministrator))) &&
|
||||
isTesSuccess(result))
|
||||
{
|
||||
std::uint32_t const startingSeq{
|
||||
|
||||
@@ -704,6 +704,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)
|
||||
@@ -743,12 +758,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())
|
||||
@@ -1288,6 +1337,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()
|
||||
{
|
||||
@@ -1307,11 +1373,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);
|
||||
|
||||
Reference in New Issue
Block a user