fix create->install fallthrough bug

This commit is contained in:
Richard Holland
2022-02-07 12:52:13 +00:00
parent 7928363c24
commit 249c127890
2 changed files with 33 additions and 20 deletions

View File

@@ -1590,6 +1590,9 @@ SetHook::setHook()
std::optional<uint64_t> newHookOn; std::optional<uint64_t> newHookOn;
std::optional<uint64_t> defHookOn; std::optional<uint64_t> defHookOn;
// when hsoCREATE is invoked it populates this variable in case the hook definition already exists
// and the operation falls through into a hsoINSTALL operation instead
std::optional<ripple::uint256> createHookHash;
/** /**
* This is the primary HookSet loop. We iterate the sfHooks array inside the txn * This is the primary HookSet loop. We iterate the sfHooks array inside the txn
* each entry of this array is available as hookSetObj. * each entry of this array is available as hookSetObj.
@@ -1606,16 +1609,23 @@ SetHook::setHook()
{ {
oldDefKeylet = keylet::hookDefinition(oldHook->get().getFieldH256(sfHookHash)); oldDefKeylet = keylet::hookDefinition(oldHook->get().getFieldH256(sfHookHash));
oldDefSLE = view().peek(*oldDefKeylet); oldDefSLE = view().peek(*oldDefKeylet);
if (oldDefSLE)
defNamespace = oldDefSLE->getFieldH256(sfHookNamespace); defNamespace = oldDefSLE->getFieldH256(sfHookNamespace);
oldNamespace = oldHook->get().isFieldPresent(sfHookNamespace)
? oldHook->get().getFieldH256(sfHookNamespace) if (oldHook->get().isFieldPresent(sfHookNamespace))
: *defNamespace; oldNamespace = oldHook->get().getFieldH256(sfHookNamespace);
else if (defNamespace)
oldNamespace = *defNamespace;
oldDirKeylet = keylet::hookStateDir(account_, *oldNamespace); oldDirKeylet = keylet::hookStateDir(account_, *oldNamespace);
oldDirSLE = view().peek(*oldDirKeylet); oldDirSLE = view().peek(*oldDirKeylet);
if (oldDefSLE)
defHookOn = oldDefSLE->getFieldU64(sfHookOn); defHookOn = oldDefSLE->getFieldU64(sfHookOn);
oldHookOn = oldHook->get().isFieldPresent(sfHookOn)
? oldHook->get().getFieldU64(sfHookOn) if (oldHook->get().isFieldPresent(sfHookOn))
: *defHookOn; oldHookOn = oldHook->get().getFieldU64(sfHookOn);
else if (defHookOn)
oldHookOn = *defHookOn;
} }
@@ -1744,11 +1754,11 @@ SetHook::setHook()
return tecINTERNAL; return tecINTERNAL;
} }
auto hash = ripple::sha512Half_s( createHookHash = ripple::sha512Half_s(
ripple::Slice(wasmBytes.data(), wasmBytes.size()) ripple::Slice(wasmBytes.data(), wasmBytes.size())
); );
auto keylet = ripple::keylet::hookDefinition(hash); auto keylet = ripple::keylet::hookDefinition(*createHookHash);
if (view().exists(keylet)) if (view().exists(keylet))
@@ -1787,7 +1797,7 @@ SetHook::setHook()
} }
auto newHookDef = std::make_shared<SLE>( keylet ); auto newHookDef = std::make_shared<SLE>( keylet );
newHookDef->setFieldH256(sfHookHash, hash); newHookDef->setFieldH256(sfHookHash, *createHookHash);
newHookDef->setFieldU64( sfHookOn, *newHookOn); newHookDef->setFieldU64( sfHookOn, *newHookOn);
newHookDef->setFieldH256( sfHookNamespace, *newNamespace); newHookDef->setFieldH256( sfHookNamespace, *newNamespace);
newHookDef->setFieldArray( sfHookParameters, newHookDef->setFieldArray( sfHookParameters,
@@ -1800,7 +1810,7 @@ SetHook::setHook()
newHookDef->setFieldU64( sfReferenceCount, 1); newHookDef->setFieldU64( sfReferenceCount, 1);
newHookDef->setFieldAmount(sfFee, XRPAmount {hook::computeExecutionFee(maxInstrCount)} ); newHookDef->setFieldAmount(sfFee, XRPAmount {hook::computeExecutionFee(maxInstrCount)} );
view().insert(newHookDef); view().insert(newHookDef);
newHook.setFieldH256(sfHookHash, hash); newHook.setFieldH256(sfHookHash, *createHookHash);
newHooks.push_back(std::move(newHook)); newHooks.push_back(std::move(newHook));
continue; continue;
} }
@@ -1832,9 +1842,11 @@ SetHook::setHook()
if (oldHook && reduceReferenceCount(oldDefSLE)) if (oldHook && reduceReferenceCount(oldDefSLE))
defsToDestroy.emplace(*oldDefKeylet); defsToDestroy.emplace(*oldDefKeylet);
// set the hookhash on the new hook // set the hookhash on the new hook, and allow for a fall through event from hsoCREATE
uint256 const& hash = hookSetObj->getFieldH256(sfHookHash); if (!createHookHash)
newHook.setFieldH256(sfHookHash, hash); createHookHash = hookSetObj->getFieldH256(sfHookHash);
newHook.setFieldH256(sfHookHash, *createHookHash);
// increment reference count of target HookDefintion // increment reference count of target HookDefintion
incrementReferenceCount(newDefSLE); incrementReferenceCount(newDefSLE);

View File

@@ -181,7 +181,7 @@ Transactor::calculateHookChainFee(ReadView const& view, STTx const& tx, Keylet c
{ {
ripple::STObject const* hookObj = dynamic_cast<ripple::STObject const*>(&hook); ripple::STObject const* hookObj = dynamic_cast<ripple::STObject const*>(&hook);
if (hookObj->getCount() == 0 || !hookObj->isFieldPresent(sfHookHash)) // skip blanks if (!hookObj->isFieldPresent(sfHookHash)) // skip blanks
continue; continue;
uint256 const& hash = hookObj->getFieldH256(sfHookHash); uint256 const& hash = hookObj->getFieldH256(sfHookHash);
@@ -960,7 +960,7 @@ executeHookChain(
{ {
ripple::STObject const* hookObj = dynamic_cast<ripple::STObject const*>(&hook); ripple::STObject const* hookObj = dynamic_cast<ripple::STObject const*>(&hook);
if (hookObj->getCount() == 0 || !hookObj->isFieldPresent(sfHookHash)) // skip blanks if (!hookObj->isFieldPresent(sfHookHash)) // skip blanks
continue; continue;
// lookup hook definition // lookup hook definition
@@ -976,9 +976,10 @@ executeHookChain(
auto const& hookDef = ctx.view().peek(keylet::hookDefinition(hookHash)); auto const& hookDef = ctx.view().peek(keylet::hookDefinition(hookHash));
if (!hookDef) if (!hookDef)
{ {
JLOG(j_.fatal()) JLOG(j_.warn())
<< "HookError[]: Failure: hook def missing (send)"; << "HookError[]: Failure: hook def missing (send)";
return true; // return true;
continue;
} }
// check if the hook can fire // check if the hook can fire
@@ -1150,7 +1151,7 @@ Transactor::operator()()
STObject const* hookObj = dynamic_cast<STObject const*>(&hook); STObject const* hookObj = dynamic_cast<STObject const*>(&hook);
if (hookObj->getCount() == 0 || !hookObj->isFieldPresent(sfHookHash)) // skip blanks if (!hookObj->isFieldPresent(sfHookHash)) // skip blanks
continue; continue;
if (hookObj->getFieldH256(sfHookHash) != callbackHookHash) if (hookObj->getFieldH256(sfHookHash) != callbackHookHash)