fix txmeta issues

This commit is contained in:
Richard Holland
2022-05-16 11:42:25 +00:00
parent b01bbcae5c
commit 003bb9f63b
7 changed files with 96 additions and 32 deletions

View File

@@ -2,6 +2,27 @@
#include <string>
#ifndef HOOKENUM_INCLUDED
#define HOOKENUM_INCLUDED 1
namespace ripple
{
enum HookSetOperation : int8_t
{
hsoINVALID = -1,
hsoNOOP = 0,
hsoCREATE = 1,
hsoINSTALL = 2,
hsoDELETE = 3,
hsoNSDELETE = 4,
hsoUPDATE = 5
};
enum HookSetFlags : uint8_t
{
hsfOVERRIDE = 0b00000001U, // override or delete hook
hsfNSDELETE = 0b00000010U, // delete namespace
hsfCOLLECT = 0b00000100U, // allow collect calls on this hook
};
}
namespace hook
{
enum TSHFlags : uint8_t
@@ -11,6 +32,7 @@ namespace hook
tshCOLLECT = 0b010,
};
namespace log
{
/*

View File

@@ -247,7 +247,7 @@ validateHookSetEntry(SetHookCtx& ctx, STObject const& hookSetObj)
}
if (flags & ~(hsfOVERRIDE | hsfNSDELETE))
if (flags & ~(hsfOVERRIDE | hsfNSDELETE | hsfCOLLECT))
{
JLOG(ctx.j.trace())
<< "HookSet(" << hook::log::FLAGS_INVALID << ")[" << HS_ACC()
@@ -994,7 +994,7 @@ SetHook::setHook()
* so a degree of copying is required.
*/
uint32_t flags = 0;
std::optional<uint32_t> flags;
if (hookSetObj && hookSetObj->get().isFieldPresent(sfFlags))
flags = hookSetObj->get().getFieldU32(sfFlags);
@@ -1004,6 +1004,18 @@ SetHook::setHook()
if (hookSetObj)
op = inferOperation(hookSetObj->get());
// these flags are not able to be passed onto the ledger object
if (flags)
{
if (*flags & hsfOVERRIDE)
*flags -= hsfOVERRIDE;
if (*flags & hsfNSDELETE)
*flags -= hsfNSDELETE;
}
printf("HookSet operation %d: %s\n", hookSetNumber,
(op == hsoNSDELETE ? "hsoNSDELETE" :
@@ -1057,7 +1069,7 @@ SetHook::setHook()
}
// users may destroy a namespace in any operation except NOOP and INVALID
if (flags & hsfNSDELETE)
if (flags && (*flags & hsfNSDELETE))
{
if (op == hsoNOOP || op == hsoINVALID)
{
@@ -1109,7 +1121,7 @@ SetHook::setHook()
case hsoDELETE:
{
if (!(flags & hsfOVERRIDE))
if (!flags || !(*flags & hsfOVERRIDE))
{
JLOG(ctx.j.trace())
<< "HookSet(" << hook::log::DELETE_FLAG << ")[" << HS_ACC()
@@ -1162,6 +1174,11 @@ SetHook::setHook()
if (hookSetObj->get().isFieldPresent(sfHookGrants))
newHook.setFieldArray(sfHookGrants, hookSetObj->get().getFieldArray(sfHookGrants));
if (flags)
newHook.setFieldU32(sfFlags, *flags);
newHooks.push_back(std::move(newHook));
continue;
}
@@ -1169,7 +1186,7 @@ SetHook::setHook()
case hsoCREATE:
{
if (oldHook && oldHook->get().isFieldPresent(sfHookHash) && !(flags & hsfOVERRIDE))
if (oldHook && oldHook->get().isFieldPresent(sfHookHash) && (!flags || !(*flags & hsfOVERRIDE)))
{
JLOG(ctx.j.trace())
<< "HookSet(" << hook::log::CREATE_FLAG << ")[" << HS_ACC()
@@ -1267,6 +1284,12 @@ SetHook::setHook()
if (maxInstrCountCbak > 0)
newHookDef->setFieldAmount(sfHookCallbackFee,
XRPAmount {hook::computeExecutionFee(maxInstrCountCbak)});
if (flags)
newHookDef->setFieldU32(sfFlags, *flags);
else
newHookDef->setFieldU32(sfFlags, 0);
view().insert(newHookDef);
newHook.setFieldH256(sfHookHash, *createHookHash);
newHooks.push_back(std::move(newHook));
@@ -1279,7 +1302,7 @@ SetHook::setHook()
// otherwise be created already exists on the ledger
case hsoINSTALL:
{
if (oldHook && oldHook->get().isFieldPresent(sfHookHash) && !(flags & hsfOVERRIDE))
if (oldHook && oldHook->get().isFieldPresent(sfHookHash) && (!flags || !(*flags & hsfOVERRIDE)))
{
JLOG(ctx.j.trace())
<< "HookSet(" << hook::log::INSTALL_FLAG << ")[" << HS_ACC()
@@ -1337,6 +1360,9 @@ SetHook::setHook()
if (hookSetObj->get().isFieldPresent(sfHookGrants))
newHook.setFieldArray(sfHookGrants, hookSetObj->get().getFieldArray(sfHookGrants));
if (flags)
newHook.setFieldU32(sfFlags, *flags);
newHooks.push_back(std::move(newHook));
view().update(newDefSLE);

View File

@@ -33,6 +33,7 @@
#include <algorithm>
#include <cstdint>
#include <vector>
#include <ripple/app/hook/Enum.h>
#include <ripple/app/hook/applyHook.h>
namespace ripple {
@@ -45,24 +46,6 @@ struct SetHookCtx
Application& app;
};
enum HookSetOperation : int8_t
{
hsoINVALID = -1,
hsoNOOP = 0,
hsoCREATE = 1,
hsoINSTALL = 2,
hsoDELETE = 3,
hsoNSDELETE = 4,
hsoUPDATE = 5
};
enum HookSetFlags : uint8_t
{
hsfOVERRIDE = (1U << 0U), // override or delete hook
hsfNSDELETE = (1U << 1U), // delete namespace
};
class SetHook : public Transactor
{

View File

@@ -35,6 +35,7 @@
#include <ripple/protocol/UintTypes.h>
#include <ripple/ledger/PaymentSandbox.h>
#include <ripple/ledger/detail/ApplyViewBase.h>
#include <ripple/app/hook/Enum.h>
#include <limits>
#include <set>
@@ -156,7 +157,8 @@ Transactor::
calculateHookChainFee(
ReadView const& view,
STTx const& tx,
Keylet const& hookKeylet)
Keylet const& hookKeylet,
bool collectCallsOnly)
{
std::shared_ptr<SLE const> hookSLE = view.read(hookKeylet);
@@ -191,11 +193,20 @@ calculateHookChainFee(
? hookObj->getFieldU64(sfHookOn)
: hookDef->getFieldU64(sfHookOn));
if (hook::canHook(tx.getTxnType(), hookOn))
uint32_t flags = 0;
if (hookObj->isFieldPresent(sfFlags))
flags = hookObj->getFieldU32(sfFlags);
else
flags = hookDef->getFieldU32(sfFlags);
if (hook::canHook(tx.getTxnType(), hookOn) &&
((collectCallsOnly && (flags & hook::hsfCOLLECT)) ||
(!collectCallsOnly && !(flags & hook::hsfCOLLECT)))
)
{
fee += FeeUnit64{
(uint32_t)(hookDef->getFieldAmount(sfFee).xrp().drops())
};
fee += FeeUnit64{
(uint32_t)(hookDef->getFieldAmount(sfFee).xrp().drops())
};
}
}
@@ -948,6 +959,13 @@ executeHookChain(
if (!hook::canHook(ctx_.tx.getTxnType(), hookOn))
continue; // skip if it can't
uint32_t flags = (hookObj->isFieldPresent(sfFlags) ?
hookObj->getFieldU32(sfFlags) : hookDef->getFieldU32(sfFlags));
// skip weakly executed hooks that lack a collect flag
if (!strong && !(flags & hsfCOLLECT))
continue;
// fetch the namespace either from the hook object of, if absent, the hook def
uint256 const& ns =
(hookObj->isFieldPresent(sfHookNamespace)
@@ -1240,7 +1258,7 @@ doTSH(
// compute and deduct fees for the TSH if applicable
FeeUnit64 tshFee =
calculateHookChainFee(view, ctx_.tx, klTshHook);
calculateHookChainFee(view, ctx_.tx, klTshHook, !canRollback);
// no hooks to execute, skip tsh
if (tshFee == 0)
@@ -1614,8 +1632,11 @@ Transactor::operator()()
{
// weakly executed hooks have access to a provisional TxMeta
// for this tx application.
TxMeta meta = ctx_.generateProvisionalMeta();
meta.setResult(result, 0);
std::shared_ptr<STObject const>
proMeta = std::make_shared<STObject const>(std::move(ctx_.generateProvisionalMeta().getAsObject()));
proMeta = std::make_shared<STObject const>(std::move(meta.getAsObject()));
// perform callback logic if applicable
if (ctx_.tx.isFieldPresent(sfEmitDetails))

View File

@@ -186,7 +186,8 @@ public:
// Hooks
static FeeUnit64
calculateHookChainFee(ReadView const& view, STTx const& tx, Keylet const& hookKeylet);
calculateHookChainFee(ReadView const& view, STTx const& tx, Keylet const& hookKeylet,
bool collectCallsOnly = false);
protected:

View File

@@ -75,6 +75,9 @@ public:
return mIndex;
}
void
setResult(TER res, int index);
void
setAffectedNode(uint256 const&, SField const& type, std::uint16_t nodeType);
STObject&

View File

@@ -207,6 +207,14 @@ TxMeta::getAffectedNode(uint256 const& node)
return *(mNodes.begin()); // Silence compiler warning.
}
// used for mock TxMeta objects
void
TxMeta::setResult(TER res, int index)
{
mResult = TERtoInt(res);
mIndex = index;
}
STObject
TxMeta::getAsObject() const
{