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

View File

@@ -33,6 +33,7 @@
#include <algorithm> #include <algorithm>
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
#include <ripple/app/hook/Enum.h>
#include <ripple/app/hook/applyHook.h> #include <ripple/app/hook/applyHook.h>
namespace ripple { namespace ripple {
@@ -45,24 +46,6 @@ struct SetHookCtx
Application& app; 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 class SetHook : public Transactor
{ {

View File

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

View File

@@ -186,7 +186,8 @@ public:
// Hooks // Hooks
static FeeUnit64 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: protected:

View File

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

View File

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