add sfHookNamespaces array to account root

This commit is contained in:
Richard Holland
2022-03-11 13:02:10 +00:00
parent 918472fa47
commit 46130fe14f
6 changed files with 96 additions and 39 deletions

View File

@@ -1467,11 +1467,13 @@ SetHook::destroyNamespace(
SetHookCtx& ctx, SetHookCtx& ctx,
ApplyView& view, ApplyView& view,
const AccountID& account, const AccountID& account,
const Keylet & dirKeylet // the keylet of the namespace directory uint256 ns
) { ) {
JLOG(ctx.j.trace()) JLOG(ctx.j.trace())
<< "HookSet[" << HS_ACC() << "]: DeleteState " << "HookSet[" << HS_ACC() << "]: DeleteState "
<< "Destroying Hook Namespace for " << account << " namespace keylet " << dirKeylet.key; << "Destroying Hook Namespace for " << account << " namespace " << ns;
Keylet dirKeylet = keylet::hookStateDir(account, ns);
std::shared_ptr<SLE const> sleDirNode{}; std::shared_ptr<SLE const> sleDirNode{};
unsigned int uDirEntry{0}; unsigned int uDirEntry{0};
@@ -1506,7 +1508,7 @@ SetHook::destroyNamespace(
uint32_t stateCount =sleAccount->getFieldU32(sfHookStateCount); uint32_t stateCount =sleAccount->getFieldU32(sfHookStateCount);
uint32_t oldStateCount = stateCount; uint32_t oldStateCount = stateCount;
std::vector<std::optional<uint256>> toDelete {sleDir->getFieldV256(sfIndexes).size()}; std::vector<uint256> toDelete {sleDir->getFieldV256(sfIndexes).size()};
do do
{ {
// Make sure any directory node types that we find are the kind // Make sure any directory node types that we find are the kind
@@ -1535,7 +1537,8 @@ SetHook::destroyNamespace(
return tefBAD_LEDGER; return tefBAD_LEDGER;
} }
toDelete.push_back(uint256::fromVoidChecked(itemKeylet.key));
toDelete.push_back(uint256::fromVoid(itemKeylet.key.data()));
} while (cdirNext(view, dirKeylet.key, sleDirNode, uDirEntry, dirEntry)); } while (cdirNext(view, dirKeylet.key, sleDirNode, uDirEntry, dirEntry));
@@ -1543,30 +1546,20 @@ SetHook::destroyNamespace(
// delete it! // delete it!
for (auto const& itemKey: toDelete) for (auto const& itemKey: toDelete)
{ {
// should never happen
if (!itemKey)
{
JLOG(ctx.j.fatal())
<< "HookSet[" << HS_ACC() << "]: DeleteState "
<< "directory entry in ledger " << view.seq() << " "
<< "was invalid key fromVoidChecked.";
return tefBAD_LEDGER;
}
auto const& sleItem = view.peek({ltHOOK_STATE, *itemKey});
auto const& sleItem = view.peek({ltHOOK_STATE, itemKey});
if (!sleItem) if (!sleItem)
{ {
JLOG(ctx.j.warn()) JLOG(ctx.j.warn())
<< "HookSet[" << HS_ACC() << "]: DeleteState " << "HookSet[" << HS_ACC() << "]: DeleteState "
<< "Namespace ltHOOK_STATE entry was not found in ledger: " << "Namespace ltHOOK_STATE entry was not found in ledger: "
<< *itemKey; << itemKey;
continue; continue;
} }
auto const hint = (*sleItem)[sfOwnerNode]; auto const hint = (*sleItem)[sfOwnerNode];
if (!itemKey || !view.dirRemove(dirKeylet, hint, *itemKey, false)) if (!view.dirRemove(dirKeylet, hint, itemKey, false))
{ {
JLOG(ctx.j.fatal()) JLOG(ctx.j.fatal())
<< "HookSet[" << HS_ACC() << "]: DeleteState " << "HookSet[" << HS_ACC() << "]: DeleteState "
@@ -1589,6 +1582,24 @@ SetHook::destroyNamespace(
sleAccount->setFieldU32(sfHookStateCount, stateCount); sleAccount->setFieldU32(sfHookStateCount, stateCount);
STVector256 const& vec = sleAccount->getFieldV256(sfHookNamespaces);
if (vec.size() - 1 == 0)
{
sleAccount->makeFieldAbsent(sfHookNamespaces);
}
else
{
std::vector<uint256> nv { vec.size() - 1 };
for (uint256 u : vec.value())
if (u != ns)
nv.push_back(u);
sleAccount->setFieldV256(sfHookNamespaces, STVector256 { std::move(nv) } );
}
view.update(sleAccount);
return tesSUCCESS; return tesSUCCESS;
} }
@@ -1648,7 +1659,7 @@ createOrReuseNamespace(ripple::Keylet& newDirKeylet)
return tesSUSCCESS; return tesSUSCCESS;
} }
//if (oldDirSLE) //if (oldDirSLE)
// reduceReferenceCount(oldDirSLE, (flag & hsoNSDELETE) ? dirsToDestroy : std::nullopt); // reduceReferenceCount(oldDirSLE, (flag & hsoNSDELETE) ? namespacesToDestroy : std::nullopt);
*/ */
TER TER
@@ -1768,7 +1779,7 @@ SetHook::setHook()
} }
std::set<ripple::Keylet, KeyletComparator> defsToDestroy {}; std::set<ripple::Keylet, KeyletComparator> defsToDestroy {};
std::set<ripple::Keylet, KeyletComparator> dirsToDestroy {}; std::set<uint256> namespacesToDestroy {};
int hookSetNumber = -1; int hookSetNumber = -1;
auto const& hookSets = ctx.tx.getFieldArray(sfHooks); auto const& hookSets = ctx.tx.getFieldArray(sfHooks);
@@ -1888,12 +1899,12 @@ SetHook::setHook()
else if(op == hsoNSDELETE && newDirKeylet) else if(op == hsoNSDELETE && newDirKeylet)
{ {
printf("Marking a namespace for destruction.... NSDELETE\n"); printf("Marking a namespace for destruction.... NSDELETE\n");
dirsToDestroy.emplace(*newDirKeylet); namespacesToDestroy.emplace(*newNamespace);
} }
else if (oldDirKeylet) else if (oldDirKeylet)
{ {
printf("Marking a namespace for destruction.... non-NSDELETE\n"); printf("Marking a namespace for destruction.... non-NSDELETE\n");
dirsToDestroy.emplace(*oldDirKeylet); namespacesToDestroy.emplace(*oldNamespace);
} }
else else
{ {
@@ -2165,16 +2176,8 @@ SetHook::setHook()
{ {
// clean up any Namespace directories marked for deletion and any zero reference Hook Definitions // clean up any Namespace directories marked for deletion and any zero reference Hook Definitions
for (auto const& ns : namespacesToDestroy)
// dirs destroyNamespace(ctx, view(), account_, ns);
for (auto const& p : dirsToDestroy)
{
auto const& sle = view().peek(p);
if (!sle)
continue;
printf("==>> Destroying namespace\n");
destroyNamespace(ctx, view(), account_, p);
}
// defs // defs

View File

@@ -87,7 +87,7 @@ private:
SetHookCtx& ctx, SetHookCtx& ctx,
ApplyView& view, ApplyView& view,
const AccountID& account, const AccountID& account,
const Keylet & dirKeylet // the keylet of the namespace directory uint256 ns
); );
TER TER

View File

@@ -313,7 +313,7 @@ bool hook::canHook(ripple::TxType txType, uint64_t hookOn) {
} }
// Update HookState ledger objects for the hook... only called after accept() or reject() // Update HookState ledger objects for the hook... only called after accept() or rollback()
// assumes the specified acc has already been checked for authoriation (hook grants) // assumes the specified acc has already been checked for authoriation (hook grants)
TER TER
hook::setHookState( hook::setHookState(
@@ -357,11 +357,12 @@ hook::setHookState(
return tefBAD_LEDGER; return tefBAD_LEDGER;
auto const hint = (*hookState)[sfOwnerNode]; auto const hint = (*hookState)[sfOwnerNode];
// Remove the node from the namespace directory // Remove the node from the namespace directory
if (!view.dirRemove(hookStateDirKeylet, hint, hookStateKeylet.key, false)) if (!view.dirRemove(hookStateDirKeylet, hint, hookStateKeylet.key, false))
return tefBAD_LEDGER; return tefBAD_LEDGER;
bool nsDestroyed = !view.peek(hookStateDirKeylet);
// remove the actual hook state obj // remove the actual hook state obj
view.erase(hookState); view.erase(hookState);
@@ -374,7 +375,35 @@ hook::setHookState(
adjustOwnerCount(view, sleAccount, -1, j); adjustOwnerCount(view, sleAccount, -1, j);
sleAccount->setFieldU32(sfHookStateCount, stateCount); sleAccount->setFieldU32(sfHookStateCount, stateCount);
if (nsDestroyed)
{
STVector256 const& vec = sleAccount->getFieldV256(sfHookNamespaces);
if (vec.size() - 1 == 0)
sleAccount->makeFieldAbsent(sfHookNamespaces);
else
{
std::vector<uint256> nv { vec.size() - 1 };
for (uint256 u : vec.value())
if (u != ns)
nv.push_back(u);
sleAccount->setFieldV256(sfHookNamespaces, STVector256{std::move(nv)});
}
}
view.update(sleAccount); view.update(sleAccount);
/*
// if the root page of this namespace was removed then also remove the root page
// from the owner directory
if (!view.peek(hookStateDirKeylet) && rootHint)
{
if (!view.dirRemove(keylet::ownerDir(acc), *rootHint, hookStateDirKeylet.key, false))
return tefBAD_LEDGER;
}
*/
return tesSUCCESS; return tesSUCCESS;
} }
@@ -418,12 +447,12 @@ hook::setHookState(
if (createNew) if (createNew)
{ {
// Add the hook to the account's directory if it wasn't there already bool nsExists = !!view.peek(hookStateDirKeylet);
auto const page = view.dirInsert( auto const page = view.dirInsert(
hookStateDirKeylet, hookStateDirKeylet,
hookStateKeylet.key, hookStateKeylet.key,
describeOwnerDir(acc)); describeOwnerDir(acc));
if (!page) if (!page)
return tecDIR_FULL; return tecDIR_FULL;
@@ -431,9 +460,30 @@ hook::setHookState(
// add new data to ledger // add new data to ledger
view.insert(hookState); view.insert(hookState);
// update namespace vector where necessary
if (!nsExists)
{
if (!sleAccount->isFieldPresent(sfHookNamespaces))
{
sleAccount->setFieldV256(sfHookNamespaces, STVector256{std::vector<uint256>{ns}});
view.update(sleAccount);
} }
else else
{
STVector256 const& vec = sleAccount->getFieldV256(sfHookNamespaces);
std::vector<uint256> nv { vec.value() };
nv.push_back(ns);
sleAccount->setFieldV256(sfHookNamespaces, STVector256{std::move(nv)});
view.update(sleAccount);
}
}
}
else
{
view.update(hookState); view.update(hookState);
}
return tesSUCCESS; return tesSUCCESS;
} }

View File

@@ -531,6 +531,7 @@ extern SF_VECTOR256 const sfIndexes;
extern SF_VECTOR256 const sfHashes; extern SF_VECTOR256 const sfHashes;
extern SF_VECTOR256 const sfAmendments; extern SF_VECTOR256 const sfAmendments;
extern SF_VECTOR256 const sfTokenOffers; extern SF_VECTOR256 const sfTokenOffers;
extern SF_VECTOR256 const sfHookNamespaces;
// inner object // inner object
// OBJECT/1 is reserved for end of object // OBJECT/1 is reserved for end of object

View File

@@ -54,7 +54,8 @@ LedgerFormats::LedgerFormats()
{sfDomain, soeOPTIONAL}, {sfDomain, soeOPTIONAL},
{sfTickSize, soeOPTIONAL}, {sfTickSize, soeOPTIONAL},
{sfTicketCount, soeOPTIONAL}, {sfTicketCount, soeOPTIONAL},
{sfHookStateCount, soeOPTIONAL} {sfHookStateCount, soeOPTIONAL},
{sfHookNamespaces, soeOPTIONAL}
}, },
commonFields); commonFields);
@@ -68,6 +69,7 @@ LedgerFormats::LedgerFormats()
{sfTakerGetsIssuer, soeOPTIONAL}, // for order book directories {sfTakerGetsIssuer, soeOPTIONAL}, // for order book directories
{sfExchangeRate, soeOPTIONAL}, // for order book directories {sfExchangeRate, soeOPTIONAL}, // for order book directories
{sfReferenceCount, soeOPTIONAL}, // for hook state directories {sfReferenceCount, soeOPTIONAL}, // for hook state directories
{sfOwnerNode, soeOPTIONAL}, // for directories that are members of other directories
{sfIndexes, soeREQUIRED}, {sfIndexes, soeREQUIRED},
{sfRootIndex, soeREQUIRED}, {sfRootIndex, soeREQUIRED},
{sfIndexNext, soeOPTIONAL}, {sfIndexNext, soeOPTIONAL},

View File

@@ -280,6 +280,7 @@ CONSTRUCT_TYPED_SFIELD(sfIndexes, "Indexes", VECTOR25
CONSTRUCT_TYPED_SFIELD(sfHashes, "Hashes", VECTOR256, 2); CONSTRUCT_TYPED_SFIELD(sfHashes, "Hashes", VECTOR256, 2);
CONSTRUCT_TYPED_SFIELD(sfAmendments, "Amendments", VECTOR256, 3); CONSTRUCT_TYPED_SFIELD(sfAmendments, "Amendments", VECTOR256, 3);
CONSTRUCT_TYPED_SFIELD(sfTokenOffers, "TokenOffers", VECTOR256, 4); CONSTRUCT_TYPED_SFIELD(sfTokenOffers, "TokenOffers", VECTOR256, 4);
CONSTRUCT_TYPED_SFIELD(sfHookNamespaces, "HookNamespaces", VECTOR256, 5);
// path set // path set
CONSTRUCT_UNTYPED_SFIELD(sfPaths, "Paths", PATHSET, 1); CONSTRUCT_UNTYPED_SFIELD(sfPaths, "Paths", PATHSET, 1);