mirror of
https://github.com/Xahau/xahaud.git
synced 2026-10-23 20:27:15 +00:00
Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8ec40cec2 | ||
|
|
8330449b69 | ||
|
|
265ec4b260 | ||
|
|
5ec22bf84e | ||
|
|
c97a1eb57f | ||
|
|
3f84673fa6 | ||
|
|
37e1c2a33e | ||
|
|
be65b69fba | ||
|
|
697149aaa9 |
No files matched your search
@@ -108,6 +108,8 @@
|
||||
#define sfMPTAmount ((3U << 16U) + 26U)
|
||||
#define sfIssuerNode ((3U << 16U) + 27U)
|
||||
#define sfSubjectNode ((3U << 16U) + 28U)
|
||||
#define sfHookCost ((3U << 16U) + 95U)
|
||||
#define sfHookCallbackCost ((3U << 16U) + 96U)
|
||||
#define sfTouchCount ((3U << 16U) + 97U)
|
||||
#define sfAccountIndex ((3U << 16U) + 98U)
|
||||
#define sfAccountCount ((3U << 16U) + 99U)
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
#define ttPERMISSIONED_DOMAIN_SET 71
|
||||
#define ttPERMISSIONED_DOMAIN_DELETE 72
|
||||
#define ttENTROPY 89
|
||||
#define ttHOOK_DEFINITION_UPDATE 90
|
||||
#define ttMANIFEST_SET 91
|
||||
#define ttCRON 92
|
||||
#define ttCRON_SET 93
|
||||
|
||||
@@ -115,3 +115,7 @@ enum AMMClawbackFlags : uint32_t {
|
||||
enum BridgeModifyFlags : uint32_t {
|
||||
tfClearAccountCreateAmount = 0x00010000,
|
||||
};
|
||||
|
||||
enum HookDefinitionUpdateFlags : uint32_t {
|
||||
tfValidateGuards = 0x00000001,
|
||||
};
|
||||
@@ -406,6 +406,13 @@ const uint8_t max_emit = 255;
|
||||
const uint8_t max_params = 16;
|
||||
const double fee_base_multiplier = 1.1f;
|
||||
|
||||
// HookFeeV2 execution cost units: every wasm instruction costs one unit and
|
||||
// every hook api call costs api_call_cost units on top of its call
|
||||
// instruction. cost_units_per_drop units make one drop, so an instruction
|
||||
// costs 0.1 drop and an api call 10 drops.
|
||||
const uint32_t api_call_cost = 100;
|
||||
const uint32_t cost_units_per_drop = 10;
|
||||
|
||||
using APIWhitelist = std::map<std::string, std::vector<uint8_t>>;
|
||||
|
||||
namespace detail {
|
||||
|
||||
+57
-28
@@ -145,6 +145,7 @@ struct WasmBlkInf
|
||||
uint32_t sanity_check;
|
||||
uint32_t iteration_bound;
|
||||
uint32_t instruction_count;
|
||||
uint32_t execution_cost;
|
||||
WasmBlkInf* parent;
|
||||
std::vector<WasmBlkInf*> children;
|
||||
uint32_t start_byte;
|
||||
@@ -159,6 +160,7 @@ struct WasmBlkInf
|
||||
: sanity_check(0x1234ABCDU)
|
||||
, iteration_bound(iteration_bound_)
|
||||
, instruction_count(instruction_count_)
|
||||
, execution_cost(0)
|
||||
, parent(parent_)
|
||||
, children({})
|
||||
, start_byte(start_byte_)
|
||||
@@ -194,7 +196,7 @@ struct WasmBlkInf
|
||||
level, \
|
||||
" " \
|
||||
" ", \
|
||||
worst_case_execution, \
|
||||
instruction_count, \
|
||||
blk->start_byte, \
|
||||
blk->instruction_count, \
|
||||
blk->iteration_bound, \
|
||||
@@ -203,7 +205,7 @@ struct WasmBlkInf
|
||||
&(blk->parent)); \
|
||||
}
|
||||
// compute worst case execution time
|
||||
inline uint64_t
|
||||
inline std::pair<uint64_t, uint64_t>
|
||||
compute_wce(
|
||||
const WasmBlkInf* blk,
|
||||
int level,
|
||||
@@ -213,14 +215,14 @@ compute_wce(
|
||||
if (level > max_level)
|
||||
{
|
||||
*recursion_limit_reached = true;
|
||||
return 0;
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
if (blk->sanity_check != 0x1234ABCDU)
|
||||
{
|
||||
printf("!!! sanity check failed\n");
|
||||
*recursion_limit_reached = true;
|
||||
return (uint64_t)-1;
|
||||
return {(uint64_t)-1, (uint64_t)-1};
|
||||
}
|
||||
|
||||
WasmBlkInf const* parent = blk->parent;
|
||||
@@ -229,23 +231,28 @@ compute_wce(
|
||||
{
|
||||
printf("!!! parent sanity check failed\n");
|
||||
*recursion_limit_reached = true;
|
||||
return (uint64_t)-1;
|
||||
return {(uint64_t)-1, (uint64_t)-1};
|
||||
}
|
||||
|
||||
uint64_t worst_case_execution = blk->instruction_count;
|
||||
uint64_t instruction_count = blk->instruction_count;
|
||||
uint64_t execution_cost = blk->execution_cost;
|
||||
double multiplier = 1.0;
|
||||
|
||||
if (blk->children.size() > 0)
|
||||
for (auto const& child : blk->children)
|
||||
worst_case_execution += compute_wce(
|
||||
{
|
||||
auto [child_instruction_count, child_execution_cost] = compute_wce(
|
||||
child, level + 1, max_level, recursion_limit_reached);
|
||||
instruction_count += child_instruction_count;
|
||||
execution_cost += child_execution_cost;
|
||||
}
|
||||
|
||||
if (parent == 0 ||
|
||||
parent->iteration_bound ==
|
||||
0) // this condtion should never occur [defensively programmed]
|
||||
{
|
||||
PRINT_WCE(1);
|
||||
return worst_case_execution;
|
||||
return {instruction_count, execution_cost};
|
||||
}
|
||||
|
||||
// if the block has a parent then the quotient of its guard and its parent's
|
||||
@@ -254,12 +261,18 @@ compute_wce(
|
||||
multiplier =
|
||||
((double)(blk->iteration_bound)) / ((double)(parent->iteration_bound));
|
||||
|
||||
worst_case_execution *= multiplier;
|
||||
if (worst_case_execution < 1.0)
|
||||
worst_case_execution = 1.0;
|
||||
instruction_count *= multiplier;
|
||||
if (instruction_count < 1.0)
|
||||
instruction_count = 1.0;
|
||||
|
||||
// the loop multiplier must apply to the execution cost as well, otherwise
|
||||
// an api call inside a loop is only ever charged for a single iteration
|
||||
execution_cost *= multiplier;
|
||||
if (execution_cost < 1.0)
|
||||
execution_cost = 1.0;
|
||||
|
||||
PRINT_WCE(3);
|
||||
return worst_case_execution;
|
||||
return {instruction_count, execution_cost};
|
||||
};
|
||||
|
||||
// checks the WASM binary for the appropriate required _g guard calls and
|
||||
@@ -267,7 +280,7 @@ compute_wce(
|
||||
// expr under analysis begins and end_offset is where it ends returns {worst
|
||||
// case instruction count} if valid or {} if invalid may throw overflow_error,
|
||||
// length_error
|
||||
inline std::optional<uint64_t>
|
||||
inline std::optional<uint64_t> // count or cost depending on returnCost
|
||||
check_guard(
|
||||
std::vector<uint8_t> const& wasm,
|
||||
int codesec,
|
||||
@@ -277,6 +290,7 @@ check_guard(
|
||||
int last_import_idx,
|
||||
GuardLog guardLog,
|
||||
std::string guardLogAccStr,
|
||||
bool returnCost,
|
||||
/* RH NOTE:
|
||||
* rules version is a bit field, so rule update 1 is 0x01, update 2 is 0x02
|
||||
* and update 3 is 0x04 ideally at rule version 3 all bits so far are set
|
||||
@@ -337,6 +351,7 @@ check_guard(
|
||||
ADVANCE(1);
|
||||
|
||||
current->instruction_count++;
|
||||
current->execution_cost++;
|
||||
|
||||
// unreachable and nop instructions
|
||||
if (instr == 0x00U || // unreachable
|
||||
@@ -516,6 +531,9 @@ check_guard(
|
||||
GUARD_ERROR("Too many guard calls! Limit is 1024");
|
||||
}
|
||||
|
||||
// every import (including _g) is a hook api call
|
||||
current->execution_cost += hook_api::api_call_cost;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -795,7 +813,7 @@ check_guard(
|
||||
int max_level = 16;
|
||||
if (rulesVersion & hook_api::GuardRuleDepth32)
|
||||
max_level = 32;
|
||||
uint64_t wce =
|
||||
auto [instruction_count, execution_cost] =
|
||||
compute_wce(&(*root), 0, max_level, &recursion_limit_reached);
|
||||
if (recursion_limit_reached)
|
||||
{
|
||||
@@ -807,11 +825,7 @@ check_guard(
|
||||
return {};
|
||||
}
|
||||
|
||||
GUARDLOG(hook::log::INSTRUCTION_COUNT)
|
||||
<< "GuardCheck "
|
||||
<< "Total worse-case execution count: " << wce << "\n";
|
||||
|
||||
if (wce >= 0xFFFFU)
|
||||
if (instruction_count >= 0xFFFFU)
|
||||
{
|
||||
GUARDLOG(hook::log::INSTRUCTION_EXCESS)
|
||||
<< "GuardCheck "
|
||||
@@ -821,7 +835,10 @@ check_guard(
|
||||
<< "\n";
|
||||
return {};
|
||||
}
|
||||
return wce;
|
||||
if (returnCost)
|
||||
return execution_cost;
|
||||
else
|
||||
return instruction_count;
|
||||
}
|
||||
|
||||
// RH TODO: reprogram this function to use REQUIRE/ADVANCE
|
||||
@@ -835,6 +852,7 @@ validateGuards(
|
||||
std::vector<uint8_t> const& wasm,
|
||||
GuardLog guardLog,
|
||||
std::string guardLogAccStr,
|
||||
bool returnCost,
|
||||
hook_api::APIWhitelist const import_whitelist,
|
||||
/* RH NOTE:
|
||||
* rules version is a bit field, so rule update 1 is 0x01, update 2 is 0x02
|
||||
@@ -883,6 +901,7 @@ validateGuards(
|
||||
// this maps function ids to type ids, used for looking up the type of cbak
|
||||
// and hook as established inside the wasm binary.
|
||||
std::map<int, int> func_type_map;
|
||||
// used to check that every import sharing a type has the same signature
|
||||
std::map<
|
||||
int /* type idx */,
|
||||
std::map<int /* import index */, std::string /* api name */>>
|
||||
@@ -1035,9 +1054,8 @@ validateGuards(
|
||||
bool found_in_whitelist = (it != it_end);
|
||||
|
||||
if (import_name == "_g")
|
||||
{
|
||||
guard_import_number = func_upto;
|
||||
}
|
||||
|
||||
if (!found_in_whitelist)
|
||||
{
|
||||
GUARDLOG(hook::log::IMPORT_ILLEGAL)
|
||||
@@ -1051,12 +1069,8 @@ validateGuards(
|
||||
}
|
||||
|
||||
// add to import map
|
||||
if (import_type_map.find(type_idx) == import_type_map.end())
|
||||
import_type_map[type_idx] = {
|
||||
{func_upto, std::move(import_name)}};
|
||||
else
|
||||
import_type_map[type_idx].emplace(
|
||||
func_upto, std::move(import_name));
|
||||
import_type_map[type_idx].emplace(
|
||||
func_upto, std::move(import_name));
|
||||
|
||||
func_upto++;
|
||||
}
|
||||
@@ -1509,15 +1523,30 @@ validateGuards(
|
||||
last_import_number,
|
||||
guardLog,
|
||||
guardLogAccStr,
|
||||
returnCost,
|
||||
rulesVersion);
|
||||
|
||||
if (!valid)
|
||||
return {};
|
||||
|
||||
if (hook_func_idx && *hook_func_idx == j)
|
||||
{
|
||||
GUARDLOG(hook::log::INSTRUCTION_COUNT)
|
||||
<< "GuardCheck "
|
||||
<< "Total hook worse-case execution "
|
||||
<< (returnCost ? "cost: " : "count: ") << *valid
|
||||
<< "\n";
|
||||
maxInstrCountHook = *valid;
|
||||
}
|
||||
else if (cbak_func_idx && *cbak_func_idx == j)
|
||||
{
|
||||
GUARDLOG(hook::log::INSTRUCTION_COUNT)
|
||||
<< "GuardCheck "
|
||||
<< "Total cbak worse-case execution "
|
||||
<< (returnCost ? "cost: " : "count: ") << *valid
|
||||
<< "\n";
|
||||
maxInstrCountCbak = *valid;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DEBUG_GUARD)
|
||||
|
||||
@@ -88,6 +88,7 @@ main(int argc, char** argv)
|
||||
hook,
|
||||
std::cout,
|
||||
"",
|
||||
true,
|
||||
hook_api::getImportWhitelist(rules),
|
||||
hook_api::getGuardRulesVersion(rules));
|
||||
|
||||
|
||||
@@ -274,6 +274,12 @@ enum BridgeModifyFlags : uint32_t {
|
||||
tfClearAccountCreateAmount = 0x00010000,
|
||||
};
|
||||
constexpr std::uint32_t tfBridgeModifyMask = ~(tfUniversal | tfClearAccountCreateAmount);
|
||||
|
||||
// HookDefinitionUpdate flags:
|
||||
enum HookDefinitionUpdateFlags : uint32_t {
|
||||
tfValidateGuards = 0x00000001,
|
||||
};
|
||||
constexpr std::uint32_t tfHookDefinitionUpdateMask = ~(tfUniversal | tfValidateGuards);
|
||||
// clang-format on
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
@@ -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(HookFeeV2, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(RNG, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(PWALoader, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (20261005, Supported::yes, VoteBehavior::DefaultYes)
|
||||
|
||||
@@ -103,8 +103,10 @@ LEDGER_ENTRY(ltHOOK_DEFINITION, 'D', HookDefinition, hook_definition, ({
|
||||
{sfCreateCode, soeREQUIRED},
|
||||
{sfHookSetTxnID, soeREQUIRED},
|
||||
{sfReferenceCount, soeREQUIRED},
|
||||
{sfFee, soeREQUIRED},
|
||||
{sfFee, soeOPTIONAL},
|
||||
{sfHookCallbackFee, soeOPTIONAL},
|
||||
{sfHookCost, soeOPTIONAL},
|
||||
{sfHookCallbackCost, soeOPTIONAL},
|
||||
{sfPreviousTxnID, soeOPTIONAL},
|
||||
{sfPreviousTxnLgrSeq, soeOPTIONAL},
|
||||
}))
|
||||
|
||||
@@ -156,6 +156,8 @@ TYPED_SFIELD(sfOutstandingAmount, UINT64, 25, SField::sMD_BaseTen|SFie
|
||||
TYPED_SFIELD(sfMPTAmount, UINT64, 26, SField::sMD_BaseTen|SField::sMD_Default)
|
||||
TYPED_SFIELD(sfIssuerNode, UINT64, 27)
|
||||
TYPED_SFIELD(sfSubjectNode, UINT64, 28)
|
||||
TYPED_SFIELD(sfHookCost, UINT64, 95)
|
||||
TYPED_SFIELD(sfHookCallbackCost, UINT64, 96)
|
||||
TYPED_SFIELD(sfTouchCount, UINT64, 97)
|
||||
TYPED_SFIELD(sfAccountIndex, UINT64, 98)
|
||||
TYPED_SFIELD(sfAccountCount, UINT64, 99)
|
||||
|
||||
@@ -517,6 +517,11 @@ TRANSACTION(ttENTROPY, 89, Entropy, ({
|
||||
{sfRandomData, soeOPTIONAL},
|
||||
}))
|
||||
|
||||
/** This transaction type updates a hook definition */
|
||||
TRANSACTION(ttHOOK_DEFINITION_UPDATE, 90, HookDefinitionUpdate, ({
|
||||
{sfHookHash, soeREQUIRED},
|
||||
}))
|
||||
|
||||
/* sfAccount is supplied by TxFormats::commonFields; listing it here as well
|
||||
makes the SOTemplate reject the format at construction. */
|
||||
TRANSACTION(ttMANIFEST_SET, 91, SetManifest, ({
|
||||
|
||||
@@ -682,6 +682,7 @@ public:
|
||||
auto const sa = supported_amendments();
|
||||
testWithFeats(sa);
|
||||
testWithFeats(sa - fixHookAPI20251128);
|
||||
testWithFeats(sa - featureHookFeeV2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2023 XRPL-Labs
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS S
|
||||
OFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <test/jtx.h>
|
||||
#include <test/jtx/genesis.h>
|
||||
#include <test/jtx/hook.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
|
||||
namespace ripple {
|
||||
namespace test {
|
||||
|
||||
class HookDefinitionUpdate_test : public beast::unit_test::suite
|
||||
{
|
||||
static Json::Value
|
||||
hookDefUpdateTx(
|
||||
jtx::Account const& account,
|
||||
std::string const& hookHash,
|
||||
uint32_t flags = tfValidateGuards)
|
||||
{
|
||||
using namespace jtx;
|
||||
Json::Value jv;
|
||||
jv[jss::TransactionType] = jss::HookDefinitionUpdate;
|
||||
jv[jss::Account] = account.human();
|
||||
jv[jss::HookHash] = hookHash;
|
||||
jv[jss::Flags] = flags;
|
||||
return jv;
|
||||
}
|
||||
|
||||
void
|
||||
testInvalidPreflight(FeatureBitset features)
|
||||
{
|
||||
testcase("hook definition update invalid preflight");
|
||||
|
||||
using namespace test::jtx;
|
||||
|
||||
auto const alice = Account("alice");
|
||||
|
||||
// temDISABLED
|
||||
{
|
||||
Env env{*this, features - featureHookFeeV2};
|
||||
env.fund(XRP(1000), alice);
|
||||
env.close();
|
||||
|
||||
env(hookDefUpdateTx(alice, ""), ter(temDISABLED));
|
||||
}
|
||||
|
||||
// temINVALID_FLAG
|
||||
{
|
||||
Env env{*this, features};
|
||||
env.fund(XRP(1000), alice);
|
||||
env.close();
|
||||
|
||||
env(hookDefUpdateTx(alice, "", 0x00000002), ter(temINVALID_FLAG));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testInvalidPreclaim(FeatureBitset features)
|
||||
{
|
||||
testcase("hook definition update invalid preclaim");
|
||||
|
||||
using namespace test::jtx;
|
||||
auto const alice = Account("alice");
|
||||
|
||||
// tecNO_ENTRY
|
||||
{
|
||||
Env env{*this};
|
||||
env.fund(XRP(1000), alice);
|
||||
env.close();
|
||||
|
||||
env(hookDefUpdateTx(alice, ""), ter(tecNO_ENTRY));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testDoApply(FeatureBitset features)
|
||||
{
|
||||
testcase("hook definition update do apply");
|
||||
|
||||
using namespace test::jtx;
|
||||
auto const alice = Account("alice");
|
||||
|
||||
Env env{*this, features - featureHookFeeV2};
|
||||
env.fund(XRP(1000), alice);
|
||||
env.close();
|
||||
|
||||
auto const hookCode = jtx::genesis::AcceptHook;
|
||||
uint256 const hash = ripple::sha512Half_s(
|
||||
ripple::Slice(hookCode.data(), hookCode.size()));
|
||||
|
||||
// prepare: Create Hook Definition without HookFeeV2
|
||||
auto hookObj = hso(hookCode);
|
||||
env(hook(alice, {{hookObj}}, 0), fee(XRP(1)));
|
||||
env.close();
|
||||
// prepare: enable HookFeeV2
|
||||
env.enableFeature(featureHookFeeV2);
|
||||
env.close();
|
||||
|
||||
// 1. Update Hook Definition (Fee -> Cost)
|
||||
{
|
||||
auto leb = env.le(keylet::hookDefinition(hash));
|
||||
BEAST_EXPECT(leb->isFieldPresent(sfFee));
|
||||
BEAST_EXPECT(!leb->isFieldPresent(sfHookCost));
|
||||
env(hookDefUpdateTx(alice, to_string(hash)), fee(XRP(1)));
|
||||
env.close();
|
||||
|
||||
auto lea = env.le(keylet::hookDefinition(hash));
|
||||
BEAST_EXPECT(lea->isFieldPresent(sfHookCost));
|
||||
BEAST_EXPECT(!lea->isFieldPresent(sfFee));
|
||||
}
|
||||
// 2. Update Hook Definition (Cost -> Cost)
|
||||
{
|
||||
env(hookDefUpdateTx(alice, to_string(hash)), fee(XRP(1)));
|
||||
env.close();
|
||||
auto const meta = env.meta();
|
||||
BEAST_EXPECT(meta->isFieldPresent(sfAffectedNodes));
|
||||
|
||||
auto& nodes = meta->getFieldArray(sfAffectedNodes);
|
||||
BEAST_EXPECT(nodes.size() == 1);
|
||||
// no update for ltHookDefinition
|
||||
BEAST_EXPECT(
|
||||
nodes[0].getFieldU16(sfLedgerEntryType) == ltACCOUNT_ROOT);
|
||||
}
|
||||
|
||||
// TODO: test callback cost
|
||||
}
|
||||
|
||||
public:
|
||||
void
|
||||
run() override
|
||||
{
|
||||
using namespace test::jtx;
|
||||
FeatureBitset const all{supported_amendments()};
|
||||
testWithFeats(all);
|
||||
}
|
||||
|
||||
void
|
||||
testWithFeats(FeatureBitset features)
|
||||
{
|
||||
testInvalidPreflight(features);
|
||||
testInvalidPreclaim(features);
|
||||
testDoApply(features);
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(HookDefinitionUpdate, app, ripple);
|
||||
|
||||
} // namespace test
|
||||
} // namespace ripple
|
||||
@@ -4913,9 +4913,11 @@ private:
|
||||
env.close(std::chrono::seconds(300));
|
||||
Oracle oracle(
|
||||
env,
|
||||
{.owner = account,
|
||||
.series = {{"XRP", "USD", 740, 1}},
|
||||
.fee = 10000});
|
||||
{
|
||||
.owner = account,
|
||||
.series = {{"XRP", "USD", 740, 1}},
|
||||
.fee = 1'000'000,
|
||||
});
|
||||
|
||||
// verify tsh hook triggered
|
||||
testTSHStrongWeak(env, tshSTRONG, __LINE__);
|
||||
@@ -4952,6 +4954,7 @@ private:
|
||||
{
|
||||
.owner = account,
|
||||
.series = {{"XRP", "USD", 740, 1}},
|
||||
.fee = 1'000'000,
|
||||
});
|
||||
|
||||
// set tsh collect
|
||||
@@ -4964,7 +4967,7 @@ private:
|
||||
// delete oracle
|
||||
oracle.remove(oracle::RemoveArg{
|
||||
.documentID = oracle.documentID(),
|
||||
.fee = 10000,
|
||||
.fee = 1'000'000,
|
||||
});
|
||||
|
||||
// verify tsh hook triggered
|
||||
@@ -8257,6 +8260,15 @@ private:
|
||||
testTSHStrongWeak(env, tx->getTransactionID(), expected, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testHookDefinitionUpdateTSH(FeatureBitset features)
|
||||
{
|
||||
testcase("hook definition update tsh");
|
||||
// TODO
|
||||
BEAST_EXPECT(true);
|
||||
}
|
||||
|
||||
void
|
||||
testEmissionOrdering(FeatureBitset features)
|
||||
{
|
||||
@@ -8541,9 +8553,10 @@ public:
|
||||
using namespace test::jtx;
|
||||
static FeatureBitset const all{supported_amendments()};
|
||||
|
||||
static std::array<FeatureBitset, 3> const feats{
|
||||
static std::array<FeatureBitset, 4> const feats{
|
||||
all,
|
||||
all - featureEscrowDestinationCancel,
|
||||
all - featureHookFeeV2,
|
||||
all - featureIOUIssuerWeakTSH,
|
||||
};
|
||||
|
||||
@@ -8574,11 +8587,13 @@ public:
|
||||
};
|
||||
|
||||
SETHOOKTSH_TEST(1, false)
|
||||
SETHOOKTSH_TEST(2, true)
|
||||
SETHOOKTSH_TEST(2, false)
|
||||
SETHOOKTSH_TEST(3, true)
|
||||
|
||||
BEAST_DEFINE_TESTSUITE_PRIO(SetHookTSH0, app, ripple, 2);
|
||||
BEAST_DEFINE_TESTSUITE_PRIO(SetHookTSH1, app, ripple, 2);
|
||||
BEAST_DEFINE_TESTSUITE_PRIO(SetHookTSH2, app, ripple, 2);
|
||||
BEAST_DEFINE_TESTSUITE_PRIO(SetHookTSH3, app, ripple, 2);
|
||||
|
||||
} // namespace test
|
||||
} // namespace ripple
|
||||
+278
-29
@@ -82,14 +82,52 @@ using JSSMap =
|
||||
std::string const x##_hash_str = to_string(x##_hash); \
|
||||
Keylet const x##_keylet = keylet::hookDefinition(x##_hash);
|
||||
|
||||
#define EXPECT_HOOK_FEE(x, fee) \
|
||||
do \
|
||||
{ \
|
||||
auto const hookSLE = env.le(x##_keylet); \
|
||||
BEAST_EXPECTS( \
|
||||
hookSLE->getFieldAmount(sfFee) == XRPAmount{fee}, \
|
||||
"Hook fee mismatch: expected " #fee " got " + \
|
||||
to_string(hookSLE->getFieldAmount(sfFee))); \
|
||||
#define EXPECT_HOOK_FEE(x, fee) \
|
||||
do \
|
||||
{ \
|
||||
auto const hookSLE = env.le(x##_keylet); \
|
||||
if (env.current()->rules().enabled(featureHookFeeV2)) \
|
||||
{ \
|
||||
BEAST_EXPECTS( \
|
||||
!hookSLE->isFieldPresent(sfFee), \
|
||||
"Hook fee should not be present after featureHookFeeV2 is " \
|
||||
"enabled"); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
BEAST_EXPECTS( \
|
||||
hookSLE->getFieldAmount(sfFee) == XRPAmount{fee}, \
|
||||
"Hook fee mismatch: expected " #fee " got " + \
|
||||
to_string(hookSLE->getFieldAmount(sfFee))); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#define EXPECT_HOOK_COST(x, cost, fee) \
|
||||
do \
|
||||
{ \
|
||||
auto const hookSLE = env.le(x##_keylet); \
|
||||
if (env.current()->rules().enabled(featureHookFeeV2)) \
|
||||
{ \
|
||||
auto const actualCost = hookSLE->getFieldU64(sfHookCost); \
|
||||
auto const calculatedFee = hook::hookCostToFee(actualCost); \
|
||||
BEAST_EXPECTS( \
|
||||
actualCost > 0, "Hook cost should be greater than 0"); \
|
||||
BEAST_EXPECTS( \
|
||||
calculatedFee == XRPAmount{fee}, \
|
||||
"Hook fee(v2) mismatch: expected " #fee " got " + \
|
||||
to_string(calculatedFee)); \
|
||||
BEAST_EXPECTS( \
|
||||
actualCost == cost, \
|
||||
"Hook cost mismatch: expected " #cost " got " + \
|
||||
to_string(actualCost)); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
BEAST_EXPECTS( \
|
||||
!hookSLE->isFieldPresent(sfHookCost), \
|
||||
"Hook cost should not be present before featureHookFeeV2 is " \
|
||||
"enabled"); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
class SetHook0_test : public beast::unit_test::suite
|
||||
@@ -1379,7 +1417,7 @@ public:
|
||||
{
|
||||
testcase("Test hook on v2");
|
||||
using namespace jtx;
|
||||
Env env{*this, features};
|
||||
Env env{*this, features - featureHookFeeV2};
|
||||
|
||||
bool const hookOnV2 = env.current()->rules().enabled(featureHookOnV2) ||
|
||||
env.current()->rules().enabled(featureHookOnV2_1);
|
||||
@@ -2265,7 +2303,12 @@ public:
|
||||
auto jv = invoke::invoke(alice);
|
||||
auto expectedFee =
|
||||
calculateBaseFee(*env.current(), *env.jt(jv).stx);
|
||||
BEAST_EXPECT(expectedFee == drops(19));
|
||||
|
||||
if (env.current()->rules().enabled(featureHookFeeV2))
|
||||
// TODO: add test for hook fee v2
|
||||
BEAST_EXPECT(expectedFee > env.current()->fees().base);
|
||||
else
|
||||
BEAST_EXPECT(expectedFee == drops(19));
|
||||
env(jv,
|
||||
M("Call named hook without specifying the hook name"),
|
||||
HSFEE);
|
||||
@@ -2284,7 +2327,11 @@ public:
|
||||
jv[jss::HookName] = "41424345";
|
||||
auto expectedFee =
|
||||
calculateBaseFee(*env.current(), *env.jt(jv).stx);
|
||||
BEAST_EXPECT(expectedFee == drops(19));
|
||||
if (env.current()->rules().enabled(featureHookFeeV2))
|
||||
// TODO: add test for hook fee v2
|
||||
BEAST_EXPECT(expectedFee > env.current()->fees().base);
|
||||
else
|
||||
BEAST_EXPECT(expectedFee == drops(19));
|
||||
env(jv, M("Call named hook with the wrong hook name"), HSFEE);
|
||||
env.close();
|
||||
// execute only non-named hook
|
||||
@@ -2301,7 +2348,11 @@ public:
|
||||
jv[jss::HookName] = "41424344";
|
||||
auto expectedFee =
|
||||
calculateBaseFee(*env.current(), *env.jt(jv).stx);
|
||||
BEAST_EXPECT(expectedFee == drops(28));
|
||||
if (env.current()->rules().enabled(featureHookFeeV2))
|
||||
// TODO: add test for hook fee v2
|
||||
BEAST_EXPECT(expectedFee > env.current()->fees().base);
|
||||
else
|
||||
BEAST_EXPECT(expectedFee == drops(28));
|
||||
env(jv, M("Call named hook with the correct hook name"), HSFEE);
|
||||
env.close();
|
||||
// execute both named and non-named hooks
|
||||
@@ -3580,6 +3631,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(accept, 9);
|
||||
EXPECT_HOOK_COST(accept, 209, 21);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("Test Accept Hook"), fee(XRP(1)));
|
||||
env.close();
|
||||
@@ -3602,6 +3654,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(rollback, 9);
|
||||
EXPECT_HOOK_COST(rollback, 209, 21);
|
||||
|
||||
env(pay(bob, alice, XRP(1)),
|
||||
M("Test Rollback Hook"),
|
||||
@@ -3778,6 +3831,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 14);
|
||||
EXPECT_HOOK_COST(hook, 114, 12);
|
||||
}
|
||||
|
||||
// simple looping, c
|
||||
@@ -3806,6 +3860,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 100);
|
||||
EXPECT_HOOK_COST(hook, 2300, 230);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("Test Loop 2"), fee(XRP(1)));
|
||||
env.close();
|
||||
@@ -3853,6 +3908,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 1944);
|
||||
EXPECT_HOOK_COST(hook, 48244, 4825);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("Test Loop 3"), fee(XRP(1)));
|
||||
env.close();
|
||||
@@ -3903,6 +3959,88 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testGuardCost(FeatureBitset features)
|
||||
{
|
||||
testcase("Test guard cost");
|
||||
using namespace jtx;
|
||||
|
||||
auto const alice = Account{"alice"};
|
||||
auto const bob = Account{"bob"};
|
||||
|
||||
for (auto withCost : {true, false})
|
||||
{
|
||||
Env env{
|
||||
*this,
|
||||
withCost ? features | featureHookFeeV2
|
||||
: features - featureHookFeeV2};
|
||||
|
||||
env.fund(XRP(10000), alice);
|
||||
env.fund(XRP(10000), bob);
|
||||
TestHook hook_wasm = wasm[R"[test.hook](
|
||||
#include <stdint.h>
|
||||
extern int32_t _g (uint32_t id, uint32_t maxiter);
|
||||
#define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1)
|
||||
extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
extern int64_t hook_account (uint32_t, uint32_t);
|
||||
int64_t hook(uint32_t reserved)
|
||||
{
|
||||
uint8_t acc[20];
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
_g(1, 11);
|
||||
for (int j = 0; j < 2; ++j)
|
||||
{
|
||||
_g(2, 30);
|
||||
for (int k = 0; k < 5; ++k)
|
||||
{
|
||||
_g(3, 120);
|
||||
hook_account(acc, 20);
|
||||
}
|
||||
for (int k = 0; k < 5; ++k)
|
||||
{
|
||||
_g(4, 120);
|
||||
hook_account(acc, 20);
|
||||
}
|
||||
}
|
||||
}
|
||||
return accept(0,0,2);
|
||||
}
|
||||
)[test.hook]"];
|
||||
|
||||
HASH_WASM(hook);
|
||||
|
||||
env(ripple::test::jtx::hook(
|
||||
alice, {{hso(hook_wasm, overrideFlag)}}, 0),
|
||||
HSFEE);
|
||||
env.close();
|
||||
|
||||
auto const hookDef = env.le(hook_keylet);
|
||||
|
||||
BEAST_EXPECT(hookDef);
|
||||
if (withCost)
|
||||
{
|
||||
auto const hookCost = hookDef->getFieldU64(sfHookCost);
|
||||
auto const expectedCost = 48244;
|
||||
BEAST_EXPECTS(
|
||||
hookCost == expectedCost,
|
||||
"Hook cost mismatch: expected " + to_string(expectedCost) +
|
||||
" got " + to_string(hookCost));
|
||||
BEAST_EXPECT(!hookDef->isFieldPresent(sfFee));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const hookFee = hookDef->getFieldAmount(sfFee);
|
||||
auto const expectedFee = XRPAmount{1944};
|
||||
BEAST_EXPECTS(
|
||||
hookFee == expectedFee,
|
||||
"Hook fee mismatch: expected " + to_string(expectedFee) +
|
||||
" got " + to_string(hookFee));
|
||||
BEAST_EXPECT(!hookDef->isFieldPresent(sfHookCost));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_emit(FeatureBitset features)
|
||||
{
|
||||
@@ -4243,6 +4381,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 342);
|
||||
EXPECT_HOOK_COST(hook, 2542, 255);
|
||||
|
||||
Json::Value invoke;
|
||||
invoke[jss::TransactionType] = "Invoke";
|
||||
@@ -5044,13 +5183,21 @@ public:
|
||||
etxn_reserve(1);
|
||||
ASSERT(etxn_details((uint32_t)det, 116) == 116);
|
||||
|
||||
uint8_t expected1[49] = {
|
||||
uint8_t expected1[16] = {
|
||||
0xEDU, 0x20U, 0x2EU, 0x00U, 0x00U, 0x00U, 0x01U, 0x3DU, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x01U, 0x5BU, 0xBCU, 0x09U, 0x95U,
|
||||
0xFDU, 0x03U, 0x0FU, 0xF1U, 0x85U, 0xF4U, 0xECU, 0xACU, 0x94U, 0xDBU,
|
||||
0x02U, 0x19U, 0x26U, 0xFEU, 0x58U, 0xD4U, 0x8DU, 0x48U, 0x21U, 0xCCU,
|
||||
0x82U, 0x2EU, 0x4AU, 0x6AU, 0xC9U, 0xC8U, 0xC6U, 0x7CU, 0x88U
|
||||
};
|
||||
// 0x5B
|
||||
// EmitParentTxnID 32bytes
|
||||
uint8_t expected_emit_parent_txn_id[32] = {
|
||||
0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU,
|
||||
0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU,
|
||||
0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU,
|
||||
0xFFU, 0xFFU
|
||||
};
|
||||
// 0x5CU
|
||||
// EmitNonce 32bytes
|
||||
uint8_t expected_emit_nonce[32] = {
|
||||
@@ -5072,10 +5219,14 @@ public:
|
||||
// current hook hash
|
||||
ASSERT(hook_hash((uint32_t)expected_hook_hash, 32, -1) == 32);
|
||||
|
||||
for (int i = 0; GUARD(49), i < sizeof(expected1); ++i)
|
||||
for (int i = 0; GUARD(16), i < sizeof(expected1); ++i)
|
||||
ASSERT(det[i] == expected1[i]);
|
||||
ASSERT(det[16] == 0x5BU);
|
||||
// TODO: need to test EmitParentTxnID
|
||||
// for (int i = 0; GUARD(32), i < sizeof(expected_emit_parent_txn_id); ++i)
|
||||
// ASSERT(det[17 + i] == expected_emit_parent_txn_id[i]);
|
||||
ASSERT(det[49] == 0x5CU);
|
||||
// TODO: need to test this
|
||||
// TODO: need to test EmitNonce
|
||||
// for (int i = 0; GUARD(32), i < sizeof(expected_emit_nonce); ++i)
|
||||
// ASSERT(det[50 + i] == expected_emit_nonce[i]);
|
||||
ASSERT(det[82] == 0x5DU);
|
||||
@@ -5093,7 +5244,8 @@ public:
|
||||
M("set etxn_details"),
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 2436);
|
||||
EXPECT_HOOK_FEE(hook, 1524);
|
||||
EXPECT_HOOK_COST(hook, 8624, 863);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test etxn_details"), fee(XRP(1)));
|
||||
@@ -5181,6 +5333,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 77);
|
||||
EXPECT_HOOK_COST(hook, 1277, 128);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test etxn_fee_base"), fee(XRP(1)));
|
||||
@@ -5264,6 +5417,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 11657);
|
||||
EXPECT_HOOK_COST(hook, 90057, 9006);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test etxn_nonce"), fee(XRP(1)));
|
||||
@@ -5316,6 +5470,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 69);
|
||||
EXPECT_HOOK_COST(hook, 1269, 127);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test etxn_reserve"), fee(XRP(1)));
|
||||
@@ -5359,6 +5514,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 20);
|
||||
EXPECT_HOOK_COST(hook, 420, 42);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test fee_base"), fee(XRP(1)));
|
||||
@@ -5494,8 +5650,9 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 583);
|
||||
EXPECT_HOOK_COST(hook, 9683, 969);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("test float_compare"), fee(XRP(1)));
|
||||
env(pay(bob, alice, XRP(1)), M("test float_compare"), HSFEE);
|
||||
env.close();
|
||||
}
|
||||
}
|
||||
@@ -5696,6 +5853,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 1799);
|
||||
EXPECT_HOOK_COST(hook, 15499, 1550);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("test float_divide"), fee(XRP(1)));
|
||||
env.close();
|
||||
@@ -5828,8 +5986,9 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 1178);
|
||||
EXPECT_HOOK_COST(hook, 17978, 1798);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("test float_int"), fee(XRP(1)));
|
||||
env(pay(bob, alice, XRP(1)), M("test float_int"), HSFEE);
|
||||
env.close();
|
||||
}
|
||||
}
|
||||
@@ -5919,6 +6078,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 329);
|
||||
EXPECT_HOOK_COST(hook, 2929, 293);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("test float_invert"), fee(XRP(1)));
|
||||
env.close();
|
||||
@@ -6005,6 +6165,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 388);
|
||||
EXPECT_HOOK_COST(hook, 2988, 299);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("test float_log"), fee(XRP(1)));
|
||||
env.close();
|
||||
@@ -6137,6 +6298,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 309);
|
||||
EXPECT_HOOK_COST(hook, 5809, 581);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("test float_mantissa"), fee(XRP(1)));
|
||||
env.close();
|
||||
@@ -6295,6 +6457,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 1683);
|
||||
EXPECT_HOOK_COST(hook, 12583, 1259);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("test float_mulratio"), fee(XRP(1)));
|
||||
env.close();
|
||||
@@ -6597,6 +6760,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 3180);
|
||||
EXPECT_HOOK_COST(hook, 24680, 2468);
|
||||
env(pay(bob, alice, XRP(1)), M("test float_multiply"), fee(XRP(1)));
|
||||
env.close();
|
||||
}
|
||||
@@ -6670,6 +6834,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 105);
|
||||
EXPECT_HOOK_COST(hook, 2505, 251);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("test float_negate"), fee(XRP(1)));
|
||||
env.close();
|
||||
@@ -6714,6 +6879,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 20);
|
||||
EXPECT_HOOK_COST(hook, 420, 42);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("test float_one"), fee(XRP(1)));
|
||||
env.close();
|
||||
@@ -6795,6 +6961,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 257);
|
||||
EXPECT_HOOK_COST(hook, 2257, 226);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("test float_root"), fee(XRP(1)));
|
||||
env.close();
|
||||
@@ -6874,6 +7041,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 343);
|
||||
EXPECT_HOOK_COST(hook, 5743, 575);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("test float_set"), fee(XRP(1)));
|
||||
env.close();
|
||||
@@ -6990,6 +7158,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 296);
|
||||
EXPECT_HOOK_COST(hook, 5796, 580);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("test float_sign"), fee(XRP(1)));
|
||||
env.close();
|
||||
@@ -7198,6 +7367,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 920);
|
||||
EXPECT_HOOK_COST(hook, 10320, 1032);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("test float_sto"), fee(XRP(1)));
|
||||
env.close();
|
||||
@@ -7343,6 +7513,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 187);
|
||||
EXPECT_HOOK_COST(hook, 3187, 319);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("test float_sto_set"), fee(XRP(1)));
|
||||
env.close();
|
||||
@@ -7526,6 +7697,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 1735);
|
||||
EXPECT_HOOK_COST(hook, 12035, 1204);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("test float_sum"), fee(XRP(1)));
|
||||
env.close();
|
||||
@@ -7581,6 +7753,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 72);
|
||||
EXPECT_HOOK_COST(hook, 1072, 108);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test hook_account"), fee(XRP(1)));
|
||||
@@ -7708,6 +7881,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 54);
|
||||
EXPECT_HOOK_COST(hook, 854, 86);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("test hook_again"), fee(XRP(1)));
|
||||
env.close();
|
||||
@@ -7781,6 +7955,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 62);
|
||||
EXPECT_HOOK_COST(hook, 862, 87);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test hook_hash"), fee(XRP(1)));
|
||||
@@ -7843,6 +8018,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook2, 62);
|
||||
EXPECT_HOOK_COST(hook, 862, 87);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test hook_hash 2"), fee(XRP(1)));
|
||||
@@ -8020,6 +8196,7 @@ public:
|
||||
env(jv, M("set hook_param"), HSFEE, ter(tesSUCCESS));
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 2412);
|
||||
EXPECT_HOOK_COST(hook, 12612, 1262);
|
||||
|
||||
// invoke
|
||||
env(pay(bob, alice, XRP(1)), M("test hook_param"), fee(XRP(1)));
|
||||
@@ -8232,6 +8409,8 @@ public:
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(checker, 475);
|
||||
EXPECT_HOOK_FEE(setter, 759);
|
||||
EXPECT_HOOK_COST(checker, 2775, 278);
|
||||
EXPECT_HOOK_COST(setter, 6859, 686);
|
||||
|
||||
// invoke
|
||||
env(pay(bob, alice, XRP(1)), M("test hook_param_set"), fee(XRP(1)));
|
||||
@@ -8277,6 +8456,7 @@ public:
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 11);
|
||||
EXPECT_HOOK_COST(hook, 311, 32);
|
||||
|
||||
// invoke the hooks
|
||||
env(pay(bob, alice, XRP(1)), M("test hook_pos"), fee(XRP(1)));
|
||||
@@ -8400,6 +8580,8 @@ public:
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(skip, 263);
|
||||
EXPECT_HOOK_FEE(pos, 11);
|
||||
EXPECT_HOOK_COST(skip, 4063, 407);
|
||||
EXPECT_HOOK_COST(pos, 211, 22);
|
||||
|
||||
// invoke the hooks
|
||||
{
|
||||
@@ -8522,6 +8704,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 415);
|
||||
EXPECT_HOOK_COST(hook, 4015, 402);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("test ledger_keylet"), fee(XRP(1)));
|
||||
env.close();
|
||||
@@ -8573,6 +8756,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 59);
|
||||
EXPECT_HOOK_COST(hook, 859, 86);
|
||||
|
||||
for (uint32_t i = 0; i < 3; ++i)
|
||||
{
|
||||
@@ -8636,6 +8820,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 11);
|
||||
EXPECT_HOOK_COST(hook, 311, 32);
|
||||
|
||||
// invoke the hook a few times
|
||||
for (uint32_t i = 0; i < 3; ++i)
|
||||
@@ -8721,6 +8906,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 74);
|
||||
EXPECT_HOOK_COST(hook, 1074, 108);
|
||||
|
||||
// invoke the hook
|
||||
auto const seq =
|
||||
@@ -8806,6 +8992,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 11);
|
||||
EXPECT_HOOK_COST(hook, 311, 32);
|
||||
|
||||
// invoke the hook a few times
|
||||
for (uint32_t i = 0; i < 3; ++i)
|
||||
@@ -8905,6 +9092,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 139);
|
||||
EXPECT_HOOK_COST(hook, 2039, 204);
|
||||
|
||||
env(pay(bob, alice, XRP(1)), M("test meta_slot"), fee(XRP(1)));
|
||||
env.close();
|
||||
@@ -9030,6 +9218,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 3245);
|
||||
EXPECT_HOOK_COST(hook, 31445, 3145);
|
||||
|
||||
auto checkResult =
|
||||
[this](auto const& meta, uint64_t expectedCode) -> void {
|
||||
@@ -9124,6 +9313,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 732);
|
||||
EXPECT_HOOK_COST(hook, 4732, 474);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(alice, bob, XRP(1)), M("test otxn_field"), fee(XRP(1)));
|
||||
@@ -9209,6 +9399,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 1077);
|
||||
EXPECT_HOOK_COST(hook, 6277, 628);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test otxn_id"), fee(XRP(1)));
|
||||
@@ -9293,6 +9484,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 6442);
|
||||
EXPECT_HOOK_COST(hook, 62742, 6275);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test otxn_slot"), fee(XRP(1)));
|
||||
@@ -9355,6 +9547,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 51);
|
||||
EXPECT_HOOK_COST(hook, 951, 96);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test otxn_type"), fee(XRP(1)));
|
||||
@@ -9473,6 +9666,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 2412);
|
||||
EXPECT_HOOK_COST(hook, 12612, 1262);
|
||||
|
||||
// invoke
|
||||
Json::Value invoke;
|
||||
@@ -9606,6 +9800,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 232);
|
||||
EXPECT_HOOK_COST(hook, 3232, 324);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test slot"), fee(XRP(1)));
|
||||
@@ -9666,6 +9861,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 83);
|
||||
EXPECT_HOOK_COST(hook, 1483, 149);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test slot_clear"), fee(XRP(1)));
|
||||
@@ -9733,6 +9929,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 97);
|
||||
EXPECT_HOOK_COST(hook, 1697, 170);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test slot_count"), fee(XRP(1)));
|
||||
@@ -9810,6 +10007,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 112);
|
||||
EXPECT_HOOK_COST(hook, 1912, 192);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test slot_float"), fee(XRP(1)));
|
||||
@@ -9925,6 +10123,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 11645);
|
||||
EXPECT_HOOK_COST(hook, 118745, 11875);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test slot_set"), fee(XRP(1)));
|
||||
@@ -9999,7 +10198,7 @@ public:
|
||||
ASSERT(s > 0);
|
||||
|
||||
// pull the object out into a buffer, check the number of bytes written is correct
|
||||
uint8_t buf[4096];
|
||||
uint8_t buf[8210]; // ltSkip(3)+FLS(6)+LLS(6)+ Hashes(3+8,192(32*256))
|
||||
ASSERT(slot(SBUF(buf), 1) == s);
|
||||
|
||||
// check the object is valid
|
||||
@@ -10017,6 +10216,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 114);
|
||||
EXPECT_HOOK_COST(hook, 1814, 182);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test slot_size"), fee(XRP(1)));
|
||||
@@ -10140,6 +10340,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 6212);
|
||||
EXPECT_HOOK_COST(hook, 61112, 6112);
|
||||
|
||||
// generate an array of memos to attach
|
||||
Json::Value jv;
|
||||
@@ -10262,6 +10463,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 6109);
|
||||
EXPECT_HOOK_COST(hook, 60909, 6091);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test slot_subfield"), fee(XRP(1)));
|
||||
@@ -10403,6 +10605,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 284);
|
||||
EXPECT_HOOK_COST(hook, 4384, 439);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test slot_type"), fee(XRP(1)));
|
||||
@@ -10490,6 +10693,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 2254);
|
||||
EXPECT_HOOK_COST(hook, 11254, 1126);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test state"), fee(XRP(1)));
|
||||
@@ -10549,6 +10753,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 2134);
|
||||
EXPECT_HOOK_COST(hook, 9534, 954);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test state 2"), fee(XRP(1)));
|
||||
@@ -10618,6 +10823,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 72);
|
||||
EXPECT_HOOK_COST(hook, 872, 88);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test state_foreign"), fee(XRP(1)));
|
||||
@@ -10711,6 +10917,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 2408);
|
||||
EXPECT_HOOK_COST(hook, 11808, 1181);
|
||||
|
||||
// invoke the hook
|
||||
|
||||
@@ -10802,6 +11009,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(ns_maxHook, 103);
|
||||
EXPECT_HOOK_COST(ns_maxHook, 1003, 101);
|
||||
|
||||
// invoke the hook
|
||||
for (uint32_t i = 0; i < 255; ++i)
|
||||
@@ -10836,7 +11044,10 @@ public:
|
||||
testcase("Test state_foreign_set");
|
||||
using namespace jtx;
|
||||
|
||||
Env env{*this, features};
|
||||
Env env{
|
||||
*this,
|
||||
network::makeNetworkConfig(21137, "10", "200000000", "50000000"),
|
||||
features};
|
||||
|
||||
auto const david = Account("david"); // grantee generic
|
||||
auto const cho = Account{"cho"}; // invoker
|
||||
@@ -10976,6 +11187,7 @@ public:
|
||||
env(json, M("set state_foreign_set"), HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(grantor, 103);
|
||||
EXPECT_HOOK_COST(grantor, 903, 91);
|
||||
}
|
||||
|
||||
// install the grantee hook on bob
|
||||
@@ -10986,6 +11198,7 @@ public:
|
||||
env(json, M("set state_foreign_set 2"), HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(grantee, 234);
|
||||
EXPECT_HOOK_COST(grantee, 2634, 264);
|
||||
}
|
||||
|
||||
auto const aliceid = Account("alice").id();
|
||||
@@ -11248,6 +11461,7 @@ public:
|
||||
env(json, M("set state_foreign_set 12"), HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(exhaustion, 10582);
|
||||
EXPECT_HOOK_COST(exhaustion, 88282, 8829);
|
||||
}
|
||||
|
||||
// now invoke repeatedly until exhaustion is reached
|
||||
@@ -11885,7 +12099,10 @@ public:
|
||||
testcase("Test state_set");
|
||||
using namespace jtx;
|
||||
|
||||
Env env{*this, features};
|
||||
Env env{
|
||||
*this,
|
||||
network::makeNetworkConfig(21137, "10", "200000000", "50000000"),
|
||||
features};
|
||||
|
||||
auto const bob = Account{"bob"};
|
||||
auto const alice = Account{"alice"};
|
||||
@@ -11981,6 +12198,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 143);
|
||||
EXPECT_HOOK_COST(hook, 1943, 195);
|
||||
|
||||
BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 1);
|
||||
|
||||
@@ -12108,6 +12326,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 85);
|
||||
EXPECT_HOOK_COST(hook, 685, 69);
|
||||
|
||||
BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 1);
|
||||
|
||||
@@ -12309,6 +12528,8 @@ public:
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 82);
|
||||
EXPECT_HOOK_FEE(hook2, 525);
|
||||
EXPECT_HOOK_COST(hook, 682, 69);
|
||||
EXPECT_HOOK_COST(hook2, 2725, 273);
|
||||
|
||||
// two hooks + two state objects = 4
|
||||
BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 4);
|
||||
@@ -12386,6 +12607,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook3, 560);
|
||||
EXPECT_HOOK_COST(hook3, 3060, 306);
|
||||
|
||||
// invoke the hook with cho (rollback after alice's hooks have
|
||||
// executed)
|
||||
@@ -12493,6 +12715,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 52);
|
||||
EXPECT_HOOK_COST(hook, 552, 56);
|
||||
|
||||
// invoke from alice to cho, this will cause a rollback, however the
|
||||
// hook state should still be updated because the hook specified
|
||||
@@ -12606,6 +12829,7 @@ public:
|
||||
env(json, M("set state_set 6"), HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(exhaustion, 54114);
|
||||
EXPECT_HOOK_COST(exhaustion, 355114, 35512);
|
||||
}
|
||||
|
||||
// now invoke repeatedly until exhaustion is reached
|
||||
@@ -12759,6 +12983,7 @@ public:
|
||||
env(jv, M("Create scaled state hook"), HSFEE, ter(tesSUCCESS));
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(scaled_state, 227);
|
||||
EXPECT_HOOK_COST(scaled_state, 2927, 293);
|
||||
|
||||
BEAST_EXPECT((*env.le(gary))[sfOwnerCount] == 1);
|
||||
BEAST_EXPECT(!env.le(gary)->isFieldPresent(sfHookStateCount));
|
||||
@@ -12865,6 +13090,7 @@ public:
|
||||
env(ripple::test::jtx::hook(hank, {{jv}}, 0), HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(extended_state_reserve_hook, 95);
|
||||
EXPECT_HOOK_COST(extended_state_reserve_hook, 1495, 150);
|
||||
|
||||
Json::Value jv1 = noop(hank);
|
||||
jv1[sfHookStateScale.fieldName] = 8;
|
||||
@@ -13086,6 +13312,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 15024);
|
||||
EXPECT_HOOK_COST(hook, 73424, 7343);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test sto_emplace"), fee(XRP(1)));
|
||||
@@ -13147,6 +13374,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 36);
|
||||
EXPECT_HOOK_COST(hook, 536, 54);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)),
|
||||
@@ -13305,6 +13533,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 10021);
|
||||
EXPECT_HOOK_COST(hook, 46721, 4673);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test sto_erase"), fee(XRP(1)));
|
||||
@@ -13383,6 +13612,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 95);
|
||||
EXPECT_HOOK_COST(hook, 1495, 150);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test sto_subarray"), fee(XRP(1)));
|
||||
@@ -13449,6 +13679,8 @@ public:
|
||||
M("test sto_subarray"),
|
||||
fee(XRP(1)));
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 19);
|
||||
EXPECT_HOOK_COST(hook, 419, 42);
|
||||
|
||||
auto const meta = env.meta();
|
||||
BEAST_REQUIRE(meta);
|
||||
@@ -13578,6 +13810,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 123);
|
||||
EXPECT_HOOK_COST(hook, 1923, 193);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test sto_subfield"), fee(XRP(1)));
|
||||
@@ -13665,6 +13898,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 130);
|
||||
EXPECT_HOOK_COST(hook, 1730, 173);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test sto_validate"), fee(XRP(1)));
|
||||
@@ -13936,6 +14170,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 103);
|
||||
EXPECT_HOOK_COST(hook, 1503, 151);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test trace"), fee(XRP(1)));
|
||||
@@ -13982,6 +14217,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 37);
|
||||
EXPECT_HOOK_COST(hook, 637, 64);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test trace_float"), fee(XRP(1)));
|
||||
@@ -14028,6 +14264,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 37);
|
||||
EXPECT_HOOK_COST(hook, 637, 64);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test trace_num"), fee(XRP(1)));
|
||||
@@ -14298,6 +14535,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 3101);
|
||||
EXPECT_HOOK_COST(hook, 9901, 991);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test util_accid"), fee(XRP(1)));
|
||||
@@ -14981,6 +15219,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 1786);
|
||||
EXPECT_HOOK_COST(hook, 14286, 1429);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test util_keylet"), fee(XRP(1)));
|
||||
@@ -15436,6 +15675,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 4279);
|
||||
EXPECT_HOOK_COST(hook, 11079, 1108);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test util_raddr"), fee(XRP(1)));
|
||||
@@ -15811,6 +16051,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 2875);
|
||||
EXPECT_HOOK_COST(hook, 9675, 968);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test util_sha512h"), fee(XRP(1)));
|
||||
@@ -15927,6 +16168,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 230);
|
||||
EXPECT_HOOK_COST(hook, 3030, 303);
|
||||
|
||||
// invoke the hook
|
||||
env(pay(bob, alice, XRP(1)), M("test util_verify"), fee(XRP(1)));
|
||||
@@ -16322,6 +16564,7 @@ public:
|
||||
HSFEE);
|
||||
env.close();
|
||||
EXPECT_HOOK_FEE(hook, 755);
|
||||
EXPECT_HOOK_COST(hook, 4655, 466);
|
||||
}
|
||||
else if (i == 2)
|
||||
{
|
||||
@@ -16456,7 +16699,7 @@ public:
|
||||
// invoke the hook
|
||||
env(pay(caller, acc, XRP(1)),
|
||||
M("test hookcanemit 3"),
|
||||
fee(XRP(1)));
|
||||
fee(XRP(10)));
|
||||
env.close();
|
||||
|
||||
auto meta = env.meta();
|
||||
@@ -16514,6 +16757,7 @@ public:
|
||||
test_exit_out_of_bounds(features);
|
||||
|
||||
testGuards(features);
|
||||
testGuardCost(features);
|
||||
|
||||
test_emit(features); //
|
||||
test_emit_failure_callback(features);
|
||||
@@ -16611,13 +16855,16 @@ public:
|
||||
using namespace test::jtx;
|
||||
static FeatureBitset const all{supported_amendments()};
|
||||
|
||||
static std::array<FeatureBitset, 6> const feats{
|
||||
static std::array<FeatureBitset, 7> const feats{
|
||||
all,
|
||||
all - fixNSDelete,
|
||||
all - fixNSDelete - fixPageCap,
|
||||
all - fixNSDelete - fixPageCap - featureHookCanEmit,
|
||||
all - fixNSDelete - fixPageCap - featureExtendedHookState,
|
||||
all - featureNamedHooks,
|
||||
all - featureHookFeeV2,
|
||||
all - fixNSDelete - featureHookFeeV2,
|
||||
all - fixNSDelete - fixPageCap - featureHookFeeV2,
|
||||
all - fixNSDelete - fixPageCap - featureHookCanEmit -
|
||||
featureHookFeeV2,
|
||||
all - fixNSDelete - fixPageCap - featureExtendedHookState -
|
||||
featureHookFeeV2,
|
||||
all - featureNamedHooks - featureHookFeeV2,
|
||||
};
|
||||
|
||||
if (BEAST_EXPECT(instance < feats.size()))
|
||||
@@ -16880,7 +17127,8 @@ SETHOOK_TEST(1, false)
|
||||
SETHOOK_TEST(2, false)
|
||||
SETHOOK_TEST(3, false)
|
||||
SETHOOK_TEST(4, false)
|
||||
SETHOOK_TEST(5, true)
|
||||
SETHOOK_TEST(5, false)
|
||||
SETHOOK_TEST(6, true)
|
||||
|
||||
BEAST_DEFINE_TESTSUITE_PRIO(SetHook0, app, ripple, 2);
|
||||
BEAST_DEFINE_TESTSUITE_PRIO(SetHook1, app, ripple, 2);
|
||||
@@ -16888,6 +17136,7 @@ BEAST_DEFINE_TESTSUITE_PRIO(SetHook2, app, ripple, 2);
|
||||
BEAST_DEFINE_TESTSUITE_PRIO(SetHook3, app, ripple, 2);
|
||||
BEAST_DEFINE_TESTSUITE_PRIO(SetHook4, app, ripple, 2);
|
||||
BEAST_DEFINE_TESTSUITE_PRIO(SetHook5, app, ripple, 2);
|
||||
BEAST_DEFINE_TESTSUITE_PRIO(SetHook6, app, ripple, 2);
|
||||
} // namespace test
|
||||
} // namespace ripple
|
||||
#undef M
|
||||
+259
-141
@@ -594,6 +594,109 @@ std::map<std::string, std::vector<uint8_t>> wasm = {
|
||||
0x6AU, 0x24U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x20U, 0x05U, 0x0BU,
|
||||
}},
|
||||
|
||||
{R"[test.hook](
|
||||
#include <stdint.h>
|
||||
extern int32_t _g (uint32_t id, uint32_t maxiter);
|
||||
#define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1)
|
||||
extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
extern int64_t hook_account (uint32_t, uint32_t);
|
||||
int64_t hook(uint32_t reserved)
|
||||
{
|
||||
uint8_t acc[20];
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
_g(1, 11);
|
||||
for (int j = 0; j < 2; ++j)
|
||||
{
|
||||
_g(2, 30);
|
||||
for (int k = 0; k < 5; ++k)
|
||||
{
|
||||
_g(3, 120);
|
||||
hook_account(acc, 20);
|
||||
}
|
||||
for (int k = 0; k < 5; ++k)
|
||||
{
|
||||
_g(4, 120);
|
||||
hook_account(acc, 20);
|
||||
}
|
||||
}
|
||||
}
|
||||
return accept(0,0,2);
|
||||
}
|
||||
)[test.hook]",
|
||||
{
|
||||
0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x19U,
|
||||
0x04U, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, 0x02U, 0x7FU,
|
||||
0x7FU, 0x01U, 0x7EU, 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7EU, 0x01U, 0x7EU,
|
||||
0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU, 0x02U, 0x2AU, 0x03U, 0x03U, 0x65U,
|
||||
0x6EU, 0x76U, 0x02U, 0x5FU, 0x67U, 0x00U, 0x00U, 0x03U, 0x65U, 0x6EU,
|
||||
0x76U, 0x0CU, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x5FU, 0x61U, 0x63U, 0x63U,
|
||||
0x6FU, 0x75U, 0x6EU, 0x74U, 0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U,
|
||||
0x06U, 0x61U, 0x63U, 0x63U, 0x65U, 0x70U, 0x74U, 0x00U, 0x02U, 0x03U,
|
||||
0x02U, 0x01U, 0x03U, 0x05U, 0x03U, 0x01U, 0x00U, 0x02U, 0x06U, 0x21U,
|
||||
0x05U, 0x7FU, 0x01U, 0x41U, 0x80U, 0x88U, 0x04U, 0x0BU, 0x7FU, 0x00U,
|
||||
0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU,
|
||||
0x7FU, 0x00U, 0x41U, 0x80U, 0x88U, 0x04U, 0x0BU, 0x7FU, 0x00U, 0x41U,
|
||||
0x80U, 0x08U, 0x0BU, 0x07U, 0x08U, 0x01U, 0x04U, 0x68U, 0x6FU, 0x6FU,
|
||||
0x6BU, 0x00U, 0x03U, 0x0AU, 0xB3U, 0x84U, 0x00U, 0x01U, 0xAFU, 0x84U,
|
||||
0x00U, 0x02U, 0x02U, 0x7FU, 0x01U, 0x7EU, 0x23U, 0x80U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x41U, 0x20U, 0x6BU, 0x22U, 0x01U, 0x24U, 0x80U, 0x80U,
|
||||
0x80U, 0x80U, 0x00U, 0x41U, 0x0AU, 0x21U, 0x02U, 0x03U, 0x40U, 0x41U,
|
||||
0x01U, 0x41U, 0x0BU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU,
|
||||
0x41U, 0x02U, 0x41U, 0x1EU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x1AU, 0x41U, 0x03U, 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U,
|
||||
0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x03U, 0x41U, 0xF8U, 0x00U, 0x10U,
|
||||
0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U,
|
||||
0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x03U, 0x41U,
|
||||
0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U,
|
||||
0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU,
|
||||
0x41U, 0x03U, 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x1AU, 0x41U, 0x03U, 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U,
|
||||
0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, 0x10U,
|
||||
0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x04U, 0x41U, 0xF8U,
|
||||
0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U,
|
||||
0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U,
|
||||
0x04U, 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x1AU, 0x41U, 0x04U, 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U,
|
||||
0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U,
|
||||
0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x04U, 0x41U, 0xF8U, 0x00U,
|
||||
0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U,
|
||||
0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x04U,
|
||||
0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU,
|
||||
0x20U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x1AU, 0x41U, 0x02U, 0x41U, 0x1EU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x1AU, 0x41U, 0x03U, 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U,
|
||||
0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U,
|
||||
0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x03U, 0x41U, 0xF8U, 0x00U,
|
||||
0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U,
|
||||
0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x03U,
|
||||
0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU,
|
||||
0x20U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x1AU, 0x41U, 0x03U, 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U,
|
||||
0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x03U, 0x41U, 0xF8U, 0x00U, 0x10U,
|
||||
0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U,
|
||||
0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x04U, 0x41U,
|
||||
0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U,
|
||||
0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU,
|
||||
0x41U, 0x04U, 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x1AU, 0x41U, 0x04U, 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U,
|
||||
0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, 0x10U,
|
||||
0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x04U, 0x41U, 0xF8U,
|
||||
0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U,
|
||||
0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U,
|
||||
0x04U, 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x1AU, 0x20U, 0x02U, 0x41U, 0x7FU, 0x6AU, 0x22U, 0x02U, 0x0DU,
|
||||
0x00U, 0x0BU, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x02U, 0x10U, 0x82U,
|
||||
0x80U, 0x80U, 0x80U, 0x00U, 0x21U, 0x03U, 0x20U, 0x01U, 0x41U, 0x20U,
|
||||
0x6AU, 0x24U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x20U, 0x03U, 0x0BU,
|
||||
}},
|
||||
|
||||
{R"[test.hook](
|
||||
#include <stdint.h>
|
||||
extern int32_t _g(uint32_t, uint32_t);
|
||||
@@ -1669,13 +1772,21 @@ std::map<std::string, std::vector<uint8_t>> wasm = {
|
||||
etxn_reserve(1);
|
||||
ASSERT(etxn_details((uint32_t)det, 116) == 116);
|
||||
|
||||
uint8_t expected1[49] = {
|
||||
uint8_t expected1[16] = {
|
||||
0xEDU, 0x20U, 0x2EU, 0x00U, 0x00U, 0x00U, 0x01U, 0x3DU, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x01U, 0x5BU, 0xBCU, 0x09U, 0x95U,
|
||||
0xFDU, 0x03U, 0x0FU, 0xF1U, 0x85U, 0xF4U, 0xECU, 0xACU, 0x94U, 0xDBU,
|
||||
0x02U, 0x19U, 0x26U, 0xFEU, 0x58U, 0xD4U, 0x8DU, 0x48U, 0x21U, 0xCCU,
|
||||
0x82U, 0x2EU, 0x4AU, 0x6AU, 0xC9U, 0xC8U, 0xC6U, 0x7CU, 0x88U
|
||||
};
|
||||
// 0x5B
|
||||
// EmitParentTxnID 32bytes
|
||||
uint8_t expected_emit_parent_txn_id[32] = {
|
||||
0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU,
|
||||
0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU,
|
||||
0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU,
|
||||
0xFFU, 0xFFU
|
||||
};
|
||||
// 0x5CU
|
||||
// EmitNonce 32bytes
|
||||
uint8_t expected_emit_nonce[32] = {
|
||||
@@ -1697,10 +1808,14 @@ std::map<std::string, std::vector<uint8_t>> wasm = {
|
||||
// current hook hash
|
||||
ASSERT(hook_hash((uint32_t)expected_hook_hash, 32, -1) == 32);
|
||||
|
||||
for (int i = 0; GUARD(49), i < sizeof(expected1); ++i)
|
||||
for (int i = 0; GUARD(16), i < sizeof(expected1); ++i)
|
||||
ASSERT(det[i] == expected1[i]);
|
||||
ASSERT(det[16] == 0x5BU);
|
||||
// TODO: need to test EmitParentTxnID
|
||||
// for (int i = 0; GUARD(32), i < sizeof(expected_emit_parent_txn_id); ++i)
|
||||
// ASSERT(det[17 + i] == expected_emit_parent_txn_id[i]);
|
||||
ASSERT(det[49] == 0x5CU);
|
||||
// TODO: need to test this
|
||||
// TODO: need to test EmitNonce
|
||||
// for (int i = 0; GUARD(32), i < sizeof(expected_emit_nonce); ++i)
|
||||
// ASSERT(det[50 + i] == expected_emit_nonce[i]);
|
||||
ASSERT(det[82] == 0x5DU);
|
||||
@@ -1727,11 +1842,11 @@ std::map<std::string, std::vector<uint8_t>> wasm = {
|
||||
0x68U, 0x00U, 0x04U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x06U, 0x61U, 0x63U,
|
||||
0x63U, 0x65U, 0x70U, 0x74U, 0x00U, 0x02U, 0x03U, 0x02U, 0x01U, 0x03U,
|
||||
0x05U, 0x03U, 0x01U, 0x00U, 0x02U, 0x06U, 0x21U, 0x05U, 0x7FU, 0x01U,
|
||||
0x41U, 0xD0U, 0x8BU, 0x04U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0xC6U, 0x0BU,
|
||||
0x41U, 0xC0U, 0x8BU, 0x04U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0xB6U, 0x0BU,
|
||||
0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU, 0x00U, 0x41U,
|
||||
0xD0U, 0x8BU, 0x04U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU,
|
||||
0xC0U, 0x8BU, 0x04U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU,
|
||||
0x07U, 0x08U, 0x01U, 0x04U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x06U,
|
||||
0x0AU, 0xF4U, 0x84U, 0x00U, 0x01U, 0xF0U, 0x84U, 0x00U, 0x02U, 0x03U,
|
||||
0x0AU, 0x97U, 0x85U, 0x00U, 0x01U, 0x93U, 0x85U, 0x00U, 0x02U, 0x03U,
|
||||
0x7FU, 0x01U, 0x7EU, 0x23U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x41U,
|
||||
0xA0U, 0x01U, 0x6BU, 0x22U, 0x01U, 0x24U, 0x80U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U,
|
||||
@@ -1760,87 +1875,89 @@ std::map<std::string, std::vector<uint8_t>> wasm = {
|
||||
0x7FU, 0x37U, 0x03U, 0x00U, 0x20U, 0x01U, 0x42U, 0x7FU, 0x37U, 0x03U,
|
||||
0x08U, 0x20U, 0x01U, 0x42U, 0x7FU, 0x37U, 0x03U, 0x00U, 0x02U, 0x40U,
|
||||
0x20U, 0x01U, 0x41U, 0x20U, 0x41U, 0x7FU, 0x10U, 0x84U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x42U, 0x20U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xA1U, 0x8AU,
|
||||
0x80U, 0x80U, 0x00U, 0x41U, 0x36U, 0x42U, 0x3AU, 0x10U, 0x82U, 0x80U,
|
||||
0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x41U, 0xBCU, 0x80U, 0x80U, 0x80U,
|
||||
0x78U, 0x41U, 0x32U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU,
|
||||
0x41U, 0x00U, 0x21U, 0x02U, 0x03U, 0x40U, 0x41U, 0xBCU, 0x80U, 0x80U,
|
||||
0x80U, 0x78U, 0x41U, 0x32U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x1AU, 0x02U, 0x40U, 0x20U, 0x01U, 0x41U, 0x20U, 0x6AU, 0x20U, 0x02U,
|
||||
0x6AU, 0x2DU, 0x00U, 0x00U, 0x20U, 0x02U, 0x41U, 0xF0U, 0x89U, 0x80U,
|
||||
0x80U, 0x00U, 0x6AU, 0x2DU, 0x00U, 0x00U, 0x46U, 0x0DU, 0x00U, 0x41U,
|
||||
0xD7U, 0x8AU, 0x80U, 0x80U, 0x00U, 0x41U, 0x17U, 0x42U, 0x3DU, 0x10U,
|
||||
0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x20U, 0x02U, 0x41U,
|
||||
0x01U, 0x6AU, 0x22U, 0x02U, 0x41U, 0x31U, 0x47U, 0x0DU, 0x00U, 0x0BU,
|
||||
0x02U, 0x40U, 0x20U, 0x01U, 0x2DU, 0x00U, 0x51U, 0x41U, 0xDCU, 0x00U,
|
||||
0x46U, 0x0DU, 0x00U, 0x41U, 0xEEU, 0x8AU, 0x80U, 0x80U, 0x00U, 0x41U,
|
||||
0x11U, 0x42U, 0x3EU, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU,
|
||||
0x0BU, 0x02U, 0x40U, 0x20U, 0x01U, 0x2DU, 0x00U, 0x72U, 0x41U, 0xDDU,
|
||||
0x00U, 0x46U, 0x0DU, 0x00U, 0x41U, 0xFFU, 0x8AU, 0x80U, 0x80U, 0x00U,
|
||||
0x41U, 0x11U, 0x42U, 0xC2U, 0x00U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x1AU, 0x0BU, 0x41U, 0xC3U, 0x80U, 0x80U, 0x80U, 0x78U, 0x41U,
|
||||
0x21U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U,
|
||||
0x41U, 0xF3U, 0x00U, 0x6AU, 0x21U, 0x03U, 0x41U, 0x00U, 0x21U, 0x02U,
|
||||
0x03U, 0x40U, 0x41U, 0xC3U, 0x80U, 0x80U, 0x80U, 0x78U, 0x41U, 0x21U,
|
||||
0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x02U, 0x40U, 0x20U,
|
||||
0x03U, 0x20U, 0x02U, 0x6AU, 0x2DU, 0x00U, 0x00U, 0x20U, 0x01U, 0x20U,
|
||||
0x02U, 0x6AU, 0x2DU, 0x00U, 0x00U, 0x46U, 0x0DU, 0x00U, 0x41U, 0x90U,
|
||||
0x8BU, 0x80U, 0x80U, 0x00U, 0x41U, 0x25U, 0x42U, 0xC4U, 0x00U, 0x10U,
|
||||
0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x20U, 0x02U, 0x41U,
|
||||
0x01U, 0x6AU, 0x22U, 0x02U, 0x41U, 0x20U, 0x47U, 0x0DU, 0x00U, 0x0BU,
|
||||
0x02U, 0x40U, 0x20U, 0x01U, 0x2DU, 0x00U, 0x93U, 0x01U, 0x41U, 0xE1U,
|
||||
0x01U, 0x46U, 0x0DU, 0x00U, 0x41U, 0xB5U, 0x8BU, 0x80U, 0x80U, 0x00U,
|
||||
0x41U, 0x11U, 0x42U, 0xC5U, 0x00U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x1AU, 0x0BU, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x00U, 0x10U,
|
||||
0x85U, 0x80U, 0x80U, 0x80U, 0x00U, 0x21U, 0x04U, 0x20U, 0x01U, 0x41U,
|
||||
0xA0U, 0x01U, 0x6AU, 0x24U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x20U,
|
||||
0x04U, 0x0BU, 0x0BU, 0xCEU, 0x03U, 0x01U, 0x00U, 0x41U, 0x80U, 0x08U,
|
||||
0x0BU, 0xC6U, 0x03U, 0x65U, 0x74U, 0x78U, 0x6EU, 0x5FU, 0x64U, 0x65U,
|
||||
0x74U, 0x61U, 0x69U, 0x6CU, 0x73U, 0x28U, 0x31U, 0x30U, 0x30U, 0x30U,
|
||||
0x30U, 0x30U, 0x30U, 0x2CU, 0x20U, 0x31U, 0x31U, 0x36U, 0x29U, 0x20U,
|
||||
0x3DU, 0x3DU, 0x20U, 0x4FU, 0x55U, 0x54U, 0x5FU, 0x4FU, 0x46U, 0x5FU,
|
||||
0x42U, 0x4FU, 0x55U, 0x4EU, 0x44U, 0x53U, 0x00U, 0x65U, 0x74U, 0x78U,
|
||||
0x80U, 0x00U, 0x42U, 0x20U, 0x51U, 0x0DU, 0x00U, 0x41U, 0x80U, 0x8AU,
|
||||
0x80U, 0x80U, 0x00U, 0x41U, 0x36U, 0x42U, 0xC2U, 0x00U, 0x10U, 0x82U,
|
||||
0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x41U, 0xC4U, 0x80U, 0x80U,
|
||||
0x80U, 0x78U, 0x41U, 0x11U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x1AU, 0x41U, 0x00U, 0x21U, 0x02U, 0x03U, 0x40U, 0x41U, 0xC4U, 0x80U,
|
||||
0x80U, 0x80U, 0x78U, 0x41U, 0x11U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x1AU, 0x02U, 0x40U, 0x20U, 0x01U, 0x41U, 0x20U, 0x6AU, 0x20U,
|
||||
0x02U, 0x6AU, 0x2DU, 0x00U, 0x00U, 0x20U, 0x02U, 0x41U, 0xF0U, 0x89U,
|
||||
0x80U, 0x80U, 0x00U, 0x6AU, 0x2DU, 0x00U, 0x00U, 0x46U, 0x0DU, 0x00U,
|
||||
0x41U, 0xB6U, 0x8AU, 0x80U, 0x80U, 0x00U, 0x41U, 0x17U, 0x42U, 0xC5U,
|
||||
0x00U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x20U,
|
||||
0x02U, 0x41U, 0x01U, 0x6AU, 0x22U, 0x02U, 0x41U, 0x10U, 0x47U, 0x0DU,
|
||||
0x00U, 0x0BU, 0x02U, 0x40U, 0x20U, 0x01U, 0x2DU, 0x00U, 0x30U, 0x41U,
|
||||
0xDBU, 0x00U, 0x46U, 0x0DU, 0x00U, 0x41U, 0xCDU, 0x8AU, 0x80U, 0x80U,
|
||||
0x00U, 0x41U, 0x11U, 0x42U, 0xC6U, 0x00U, 0x10U, 0x82U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x20U, 0x01U, 0x2DU, 0x00U,
|
||||
0x51U, 0x41U, 0xDCU, 0x00U, 0x46U, 0x0DU, 0x00U, 0x41U, 0xDEU, 0x8AU,
|
||||
0x80U, 0x80U, 0x00U, 0x41U, 0x11U, 0x42U, 0xCAU, 0x00U, 0x10U, 0x82U,
|
||||
0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x20U, 0x01U,
|
||||
0x2DU, 0x00U, 0x72U, 0x41U, 0xDDU, 0x00U, 0x46U, 0x0DU, 0x00U, 0x41U,
|
||||
0xEFU, 0x8AU, 0x80U, 0x80U, 0x00U, 0x41U, 0x11U, 0x42U, 0xCEU, 0x00U,
|
||||
0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x41U, 0xCFU,
|
||||
0x80U, 0x80U, 0x80U, 0x78U, 0x41U, 0x21U, 0x10U, 0x80U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0xF3U, 0x00U, 0x6AU, 0x21U,
|
||||
0x03U, 0x41U, 0x00U, 0x21U, 0x02U, 0x03U, 0x40U, 0x41U, 0xCFU, 0x80U,
|
||||
0x80U, 0x80U, 0x78U, 0x41U, 0x21U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x1AU, 0x02U, 0x40U, 0x20U, 0x03U, 0x20U, 0x02U, 0x6AU, 0x2DU,
|
||||
0x00U, 0x00U, 0x20U, 0x01U, 0x20U, 0x02U, 0x6AU, 0x2DU, 0x00U, 0x00U,
|
||||
0x46U, 0x0DU, 0x00U, 0x41U, 0x80U, 0x8BU, 0x80U, 0x80U, 0x00U, 0x41U,
|
||||
0x25U, 0x42U, 0xD0U, 0x00U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x1AU, 0x0BU, 0x20U, 0x02U, 0x41U, 0x01U, 0x6AU, 0x22U, 0x02U, 0x41U,
|
||||
0x20U, 0x47U, 0x0DU, 0x00U, 0x0BU, 0x02U, 0x40U, 0x20U, 0x01U, 0x2DU,
|
||||
0x00U, 0x93U, 0x01U, 0x41U, 0xE1U, 0x01U, 0x46U, 0x0DU, 0x00U, 0x41U,
|
||||
0xA5U, 0x8BU, 0x80U, 0x80U, 0x00U, 0x41U, 0x11U, 0x42U, 0xD1U, 0x00U,
|
||||
0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x41U, 0x00U,
|
||||
0x41U, 0x00U, 0x42U, 0x00U, 0x10U, 0x85U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x21U, 0x04U, 0x20U, 0x01U, 0x41U, 0xA0U, 0x01U, 0x6AU, 0x24U, 0x80U,
|
||||
0x80U, 0x80U, 0x80U, 0x00U, 0x20U, 0x04U, 0x0BU, 0x0BU, 0xBEU, 0x03U,
|
||||
0x01U, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0xB6U, 0x03U, 0x65U, 0x74U,
|
||||
0x78U, 0x6EU, 0x5FU, 0x64U, 0x65U, 0x74U, 0x61U, 0x69U, 0x6CU, 0x73U,
|
||||
0x28U, 0x31U, 0x30U, 0x30U, 0x30U, 0x30U, 0x30U, 0x30U, 0x2CU, 0x20U,
|
||||
0x31U, 0x31U, 0x36U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x4FU, 0x55U,
|
||||
0x54U, 0x5FU, 0x4FU, 0x46U, 0x5FU, 0x42U, 0x4FU, 0x55U, 0x4EU, 0x44U,
|
||||
0x53U, 0x00U, 0x65U, 0x74U, 0x78U, 0x6EU, 0x5FU, 0x64U, 0x65U, 0x74U,
|
||||
0x61U, 0x69U, 0x6CU, 0x73U, 0x28U, 0x30U, 0x2CU, 0x20U, 0x31U, 0x30U,
|
||||
0x30U, 0x30U, 0x30U, 0x30U, 0x30U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U,
|
||||
0x4FU, 0x55U, 0x54U, 0x5FU, 0x4FU, 0x46U, 0x5FU, 0x42U, 0x4FU, 0x55U,
|
||||
0x4EU, 0x44U, 0x53U, 0x00U, 0x65U, 0x74U, 0x78U, 0x6EU, 0x5FU, 0x64U,
|
||||
0x65U, 0x74U, 0x61U, 0x69U, 0x6CU, 0x73U, 0x28U, 0x28U, 0x75U, 0x69U,
|
||||
0x6EU, 0x74U, 0x33U, 0x32U, 0x5FU, 0x74U, 0x29U, 0x64U, 0x65U, 0x74U,
|
||||
0x2CU, 0x20U, 0x31U, 0x31U, 0x35U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U,
|
||||
0x54U, 0x4FU, 0x4FU, 0x5FU, 0x53U, 0x4DU, 0x41U, 0x4CU, 0x4CU, 0x00U,
|
||||
0x65U, 0x74U, 0x78U, 0x6EU, 0x5FU, 0x64U, 0x65U, 0x74U, 0x61U, 0x69U,
|
||||
0x6CU, 0x73U, 0x28U, 0x28U, 0x75U, 0x69U, 0x6EU, 0x74U, 0x33U, 0x32U,
|
||||
0x5FU, 0x74U, 0x29U, 0x64U, 0x65U, 0x74U, 0x2CU, 0x20U, 0x31U, 0x31U,
|
||||
0x36U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x50U, 0x52U, 0x45U, 0x52U,
|
||||
0x45U, 0x51U, 0x55U, 0x49U, 0x53U, 0x49U, 0x54U, 0x45U, 0x5FU, 0x4EU,
|
||||
0x4FU, 0x54U, 0x5FU, 0x4DU, 0x45U, 0x54U, 0x00U, 0x65U, 0x74U, 0x78U,
|
||||
0x6EU, 0x5FU, 0x64U, 0x65U, 0x74U, 0x61U, 0x69U, 0x6CU, 0x73U, 0x28U,
|
||||
0x30U, 0x2CU, 0x20U, 0x31U, 0x30U, 0x30U, 0x30U, 0x30U, 0x30U, 0x30U,
|
||||
0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x4FU, 0x55U, 0x54U, 0x5FU, 0x4FU,
|
||||
0x46U, 0x5FU, 0x42U, 0x4FU, 0x55U, 0x4EU, 0x44U, 0x53U, 0x00U, 0x65U,
|
||||
0x74U, 0x78U, 0x6EU, 0x5FU, 0x64U, 0x65U, 0x74U, 0x61U, 0x69U, 0x6CU,
|
||||
0x73U, 0x28U, 0x28U, 0x75U, 0x69U, 0x6EU, 0x74U, 0x33U, 0x32U, 0x5FU,
|
||||
0x74U, 0x29U, 0x64U, 0x65U, 0x74U, 0x2CU, 0x20U, 0x31U, 0x31U, 0x35U,
|
||||
0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x54U, 0x4FU, 0x4FU, 0x5FU, 0x53U,
|
||||
0x4DU, 0x41U, 0x4CU, 0x4CU, 0x00U, 0x65U, 0x74U, 0x78U, 0x6EU, 0x5FU,
|
||||
0x64U, 0x65U, 0x74U, 0x61U, 0x69U, 0x6CU, 0x73U, 0x28U, 0x28U, 0x75U,
|
||||
0x69U, 0x6EU, 0x74U, 0x33U, 0x32U, 0x5FU, 0x74U, 0x29U, 0x64U, 0x65U,
|
||||
0x74U, 0x2CU, 0x20U, 0x31U, 0x31U, 0x36U, 0x29U, 0x20U, 0x3DU, 0x3DU,
|
||||
0x20U, 0x50U, 0x52U, 0x45U, 0x52U, 0x45U, 0x51U, 0x55U, 0x49U, 0x53U,
|
||||
0x49U, 0x54U, 0x45U, 0x5FU, 0x4EU, 0x4FU, 0x54U, 0x5FU, 0x4DU, 0x45U,
|
||||
0x54U, 0x00U, 0x65U, 0x74U, 0x78U, 0x6EU, 0x5FU, 0x64U, 0x65U, 0x74U,
|
||||
0x61U, 0x69U, 0x6CU, 0x73U, 0x28U, 0x28U, 0x75U, 0x69U, 0x6EU, 0x74U,
|
||||
0x33U, 0x32U, 0x5FU, 0x74U, 0x29U, 0x64U, 0x65U, 0x74U, 0x2CU, 0x20U,
|
||||
0x31U, 0x31U, 0x36U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x31U, 0x31U,
|
||||
0x36U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0xEDU, 0x20U, 0x2EU, 0x00U, 0x00U, 0x00U, 0x01U,
|
||||
0x3DU, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x01U, 0x5BU,
|
||||
0xBCU, 0x09U, 0x95U, 0xFDU, 0x03U, 0x0FU, 0xF1U, 0x85U, 0xF4U, 0xECU,
|
||||
0xACU, 0x94U, 0xDBU, 0x02U, 0x19U, 0x26U, 0xFEU, 0x58U, 0xD4U, 0x8DU,
|
||||
0x48U, 0x21U, 0xCCU, 0x82U, 0x2EU, 0x4AU, 0x6AU, 0xC9U, 0xC8U, 0xC6U,
|
||||
0x7CU, 0x88U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x5FU, 0x68U, 0x61U, 0x73U,
|
||||
0x68U, 0x28U, 0x28U, 0x75U, 0x69U, 0x6EU, 0x74U, 0x33U, 0x32U, 0x5FU,
|
||||
0x74U, 0x29U, 0x65U, 0x78U, 0x70U, 0x65U, 0x63U, 0x74U, 0x65U, 0x64U,
|
||||
0x5FU, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x5FU, 0x68U, 0x61U, 0x73U, 0x68U,
|
||||
0x2CU, 0x20U, 0x33U, 0x32U, 0x2CU, 0x20U, 0x2DU, 0x31U, 0x29U, 0x20U,
|
||||
0x3DU, 0x3DU, 0x20U, 0x33U, 0x32U, 0x00U, 0x64U, 0x65U, 0x74U, 0x5BU,
|
||||
0x69U, 0x5DU, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x65U, 0x78U, 0x70U, 0x65U,
|
||||
0x63U, 0x74U, 0x65U, 0x64U, 0x31U, 0x5BU, 0x69U, 0x5DU, 0x00U, 0x64U,
|
||||
0x65U, 0x74U, 0x5BU, 0x34U, 0x39U, 0x5DU, 0x20U, 0x3DU, 0x3DU, 0x20U,
|
||||
0x30U, 0x78U, 0x35U, 0x43U, 0x55U, 0x00U, 0x64U, 0x65U, 0x74U, 0x5BU,
|
||||
0x38U, 0x32U, 0x5DU, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x30U, 0x78U, 0x35U,
|
||||
0x44U, 0x55U, 0x00U, 0x64U, 0x65U, 0x74U, 0x5BU, 0x38U, 0x33U, 0x20U,
|
||||
0x2BU, 0x20U, 0x69U, 0x5DU, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x65U, 0x78U,
|
||||
0x70U, 0x65U, 0x63U, 0x74U, 0x65U, 0x64U, 0x5FU, 0x68U, 0x6FU, 0x6FU,
|
||||
0x6BU, 0x5FU, 0x68U, 0x61U, 0x73U, 0x68U, 0x5BU, 0x69U, 0x5DU, 0x00U,
|
||||
0x64U, 0x65U, 0x74U, 0x5BU, 0x31U, 0x31U, 0x35U, 0x5DU, 0x20U, 0x3DU,
|
||||
0x3DU, 0x20U, 0x30U, 0x78U, 0x45U, 0x31U, 0x00U,
|
||||
0x28U, 0x75U, 0x69U, 0x6EU, 0x74U, 0x33U, 0x32U, 0x5FU, 0x74U, 0x29U,
|
||||
0x64U, 0x65U, 0x74U, 0x2CU, 0x20U, 0x31U, 0x31U, 0x36U, 0x29U, 0x20U,
|
||||
0x3DU, 0x3DU, 0x20U, 0x31U, 0x31U, 0x36U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0xEDU, 0x20U,
|
||||
0x2EU, 0x00U, 0x00U, 0x00U, 0x01U, 0x3DU, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x01U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x5FU, 0x68U,
|
||||
0x61U, 0x73U, 0x68U, 0x28U, 0x28U, 0x75U, 0x69U, 0x6EU, 0x74U, 0x33U,
|
||||
0x32U, 0x5FU, 0x74U, 0x29U, 0x65U, 0x78U, 0x70U, 0x65U, 0x63U, 0x74U,
|
||||
0x65U, 0x64U, 0x5FU, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x5FU, 0x68U, 0x61U,
|
||||
0x73U, 0x68U, 0x2CU, 0x20U, 0x33U, 0x32U, 0x2CU, 0x20U, 0x2DU, 0x31U,
|
||||
0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x33U, 0x32U, 0x00U, 0x64U, 0x65U,
|
||||
0x74U, 0x5BU, 0x69U, 0x5DU, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x65U, 0x78U,
|
||||
0x70U, 0x65U, 0x63U, 0x74U, 0x65U, 0x64U, 0x31U, 0x5BU, 0x69U, 0x5DU,
|
||||
0x00U, 0x64U, 0x65U, 0x74U, 0x5BU, 0x31U, 0x36U, 0x5DU, 0x20U, 0x3DU,
|
||||
0x3DU, 0x20U, 0x30U, 0x78U, 0x35U, 0x42U, 0x55U, 0x00U, 0x64U, 0x65U,
|
||||
0x74U, 0x5BU, 0x34U, 0x39U, 0x5DU, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x30U,
|
||||
0x78U, 0x35U, 0x43U, 0x55U, 0x00U, 0x64U, 0x65U, 0x74U, 0x5BU, 0x38U,
|
||||
0x32U, 0x5DU, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x30U, 0x78U, 0x35U, 0x44U,
|
||||
0x55U, 0x00U, 0x64U, 0x65U, 0x74U, 0x5BU, 0x38U, 0x33U, 0x20U, 0x2BU,
|
||||
0x20U, 0x69U, 0x5DU, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x65U, 0x78U, 0x70U,
|
||||
0x65U, 0x63U, 0x74U, 0x65U, 0x64U, 0x5FU, 0x68U, 0x6FU, 0x6FU, 0x6BU,
|
||||
0x5FU, 0x68U, 0x61U, 0x73U, 0x68U, 0x5BU, 0x69U, 0x5DU, 0x00U, 0x64U,
|
||||
0x65U, 0x74U, 0x5BU, 0x31U, 0x31U, 0x35U, 0x5DU, 0x20U, 0x3DU, 0x3DU,
|
||||
0x20U, 0x30U, 0x78U, 0x45U, 0x31U, 0x00U,
|
||||
}},
|
||||
|
||||
{R"[test.hook](
|
||||
@@ -12784,7 +12901,7 @@ std::map<std::string, std::vector<uint8_t>> wasm = {
|
||||
ASSERT(s > 0);
|
||||
|
||||
// pull the object out into a buffer, check the number of bytes written is correct
|
||||
uint8_t buf[4096];
|
||||
uint8_t buf[8210]; // ltSkip(3)+FLS(6)+LLS(6)+ Hashes(3+8,192(32*256))
|
||||
ASSERT(slot(SBUF(buf), 1) == s);
|
||||
|
||||
// check the object is valid
|
||||
@@ -12815,63 +12932,64 @@ std::map<std::string, std::vector<uint8_t>> wasm = {
|
||||
0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0xE0U, 0x89U, 0x04U,
|
||||
0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU, 0x00U, 0x41U,
|
||||
0x80U, 0x08U, 0x0BU, 0x07U, 0x08U, 0x01U, 0x04U, 0x68U, 0x6FU, 0x6FU,
|
||||
0x6BU, 0x00U, 0x07U, 0x0AU, 0xCCU, 0x82U, 0x00U, 0x01U, 0xC8U, 0x82U,
|
||||
0x6BU, 0x00U, 0x07U, 0x0AU, 0xCFU, 0x82U, 0x00U, 0x01U, 0xCBU, 0x82U,
|
||||
0x00U, 0x02U, 0x01U, 0x7FU, 0x01U, 0x7EU, 0x23U, 0x80U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x41U, 0x80U, 0x20U, 0x6BU, 0x22U, 0x01U, 0x24U, 0x80U,
|
||||
0x80U, 0x80U, 0x80U, 0x00U, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, 0x80U,
|
||||
0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x02U, 0x40U, 0x41U, 0x01U, 0x10U,
|
||||
0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U, 0x7BU, 0x51U, 0x0DU, 0x00U,
|
||||
0x41U, 0xA2U, 0x88U, 0x80U, 0x80U, 0x00U, 0x41U, 0x1DU, 0x42U, 0x21U,
|
||||
0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U,
|
||||
0x41U, 0x80U, 0x88U, 0x80U, 0x80U, 0x00U, 0x41U, 0x22U, 0x41U, 0x01U,
|
||||
0x10U, 0x83U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U, 0x01U, 0x51U, 0x0DU,
|
||||
0x00U, 0x41U, 0xBFU, 0x88U, 0x80U, 0x80U, 0x00U, 0x41U, 0x1EU, 0x42U,
|
||||
0x24U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U,
|
||||
0x80U, 0x00U, 0x41U, 0xA0U, 0xC0U, 0x00U, 0x6BU, 0x22U, 0x01U, 0x24U,
|
||||
0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U,
|
||||
0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x02U, 0x40U, 0x41U, 0x01U,
|
||||
0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U, 0x7BU, 0x51U, 0x0DU,
|
||||
0x00U, 0x41U, 0xA2U, 0x88U, 0x80U, 0x80U, 0x00U, 0x41U, 0x1DU, 0x42U,
|
||||
0x21U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U,
|
||||
0x40U, 0x41U, 0x80U, 0x88U, 0x80U, 0x80U, 0x00U, 0x41U, 0x22U, 0x41U,
|
||||
0xFFU, 0x01U, 0x10U, 0x83U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U, 0xFFU,
|
||||
0x01U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xDDU, 0x88U, 0x80U, 0x80U, 0x00U,
|
||||
0x41U, 0x22U, 0x42U, 0x25U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x1AU, 0x0BU, 0x02U, 0x40U, 0x41U, 0x01U, 0x10U, 0x81U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x41U, 0xFFU, 0x01U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xFFU, 0x88U, 0x80U, 0x80U, 0x00U,
|
||||
0x41U, 0x1FU, 0x42U, 0x28U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x1AU, 0x0BU, 0x02U, 0x40U, 0x41U, 0x01U, 0x10U, 0x81U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x22U, 0x02U, 0x42U, 0x00U, 0x55U, 0x0DU, 0x00U, 0x41U,
|
||||
0x9EU, 0x89U, 0x80U, 0x80U, 0x00U, 0x41U, 0x06U, 0x42U, 0x2CU, 0x10U,
|
||||
0x01U, 0x10U, 0x83U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U, 0x01U, 0x51U,
|
||||
0x0DU, 0x00U, 0x41U, 0xBFU, 0x88U, 0x80U, 0x80U, 0x00U, 0x41U, 0x1EU,
|
||||
0x42U, 0x24U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU,
|
||||
0x02U, 0x40U, 0x41U, 0x80U, 0x88U, 0x80U, 0x80U, 0x00U, 0x41U, 0x22U,
|
||||
0x41U, 0xFFU, 0x01U, 0x10U, 0x83U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U,
|
||||
0xFFU, 0x01U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xDDU, 0x88U, 0x80U, 0x80U,
|
||||
0x00U, 0x41U, 0x22U, 0x42U, 0x25U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x41U, 0x01U, 0x10U, 0x81U, 0x80U,
|
||||
0x80U, 0x80U, 0x00U, 0x41U, 0xFFU, 0x01U, 0x10U, 0x81U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xFFU, 0x88U, 0x80U, 0x80U,
|
||||
0x00U, 0x41U, 0x1FU, 0x42U, 0x28U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x41U, 0x01U, 0x10U, 0x81U, 0x80U,
|
||||
0x80U, 0x80U, 0x00U, 0x22U, 0x02U, 0x42U, 0x00U, 0x55U, 0x0DU, 0x00U,
|
||||
0x41U, 0x9EU, 0x89U, 0x80U, 0x80U, 0x00U, 0x41U, 0x06U, 0x42U, 0x2CU,
|
||||
0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U,
|
||||
0x20U, 0x01U, 0x41U, 0x92U, 0xC0U, 0x00U, 0x41U, 0x01U, 0x10U, 0x84U,
|
||||
0x80U, 0x80U, 0x80U, 0x00U, 0x20U, 0x02U, 0x51U, 0x0DU, 0x00U, 0x41U,
|
||||
0xA4U, 0x89U, 0x80U, 0x80U, 0x00U, 0x41U, 0x18U, 0x42U, 0x30U, 0x10U,
|
||||
0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x20U,
|
||||
0x01U, 0x41U, 0x80U, 0x20U, 0x41U, 0x01U, 0x10U, 0x84U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x20U, 0x02U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xA4U, 0x89U,
|
||||
0x80U, 0x80U, 0x00U, 0x41U, 0x18U, 0x42U, 0x30U, 0x10U, 0x82U, 0x80U,
|
||||
0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x20U, 0x01U, 0x20U,
|
||||
0x02U, 0xA7U, 0x10U, 0x85U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U, 0x01U,
|
||||
0x51U, 0x0DU, 0x00U, 0x41U, 0xBCU, 0x89U, 0x80U, 0x80U, 0x00U, 0x41U,
|
||||
0x1AU, 0x42U, 0x33U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU,
|
||||
0x0BU, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x00U, 0x10U, 0x86U, 0x80U,
|
||||
0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x80U, 0x20U, 0x6AU,
|
||||
0x24U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x20U, 0x02U, 0x0BU, 0x0BU,
|
||||
0xE4U, 0x01U, 0x02U, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x22U, 0x00U,
|
||||
0x68U, 0xB4U, 0x97U, 0x9AU, 0x36U, 0xCDU, 0xC7U, 0xF3U, 0xD3U, 0xD5U,
|
||||
0xC3U, 0x1AU, 0x4EU, 0xAEU, 0x2AU, 0xC7U, 0xD7U, 0x20U, 0x9DU, 0xDAU,
|
||||
0x87U, 0x75U, 0x88U, 0xB9U, 0xAFU, 0xC6U, 0x67U, 0x99U, 0x69U, 0x2AU,
|
||||
0xB0U, 0xD6U, 0x6BU, 0x00U, 0x41U, 0xA2U, 0x08U, 0x0BU, 0xB4U, 0x01U,
|
||||
0x73U, 0x6CU, 0x6FU, 0x74U, 0x5FU, 0x73U, 0x69U, 0x7AU, 0x65U, 0x28U,
|
||||
0x31U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x44U, 0x4FU, 0x45U, 0x53U,
|
||||
0x4EU, 0x54U, 0x5FU, 0x45U, 0x58U, 0x49U, 0x53U, 0x54U, 0x00U, 0x73U,
|
||||
0x6CU, 0x6FU, 0x74U, 0x5FU, 0x73U, 0x65U, 0x74U, 0x28U, 0x53U, 0x42U,
|
||||
0x55U, 0x46U, 0x28U, 0x6BU, 0x6CU, 0x5FU, 0x73U, 0x6BU, 0x29U, 0x2CU,
|
||||
0x20U, 0x31U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x31U, 0x00U, 0x73U,
|
||||
0x6CU, 0x6FU, 0x74U, 0x5FU, 0x73U, 0x65U, 0x74U, 0x28U, 0x53U, 0x42U,
|
||||
0x55U, 0x46U, 0x28U, 0x6BU, 0x6CU, 0x5FU, 0x73U, 0x6BU, 0x29U, 0x2CU,
|
||||
0x20U, 0x32U, 0x35U, 0x35U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x32U,
|
||||
0x35U, 0x35U, 0x00U, 0x73U, 0x6CU, 0x6FU, 0x74U, 0x5FU, 0x73U, 0x69U,
|
||||
0x7AU, 0x65U, 0x28U, 0x31U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x73U,
|
||||
0x6CU, 0x6FU, 0x74U, 0x5FU, 0x73U, 0x69U, 0x7AU, 0x65U, 0x28U, 0x32U,
|
||||
0x35U, 0x35U, 0x29U, 0x00U, 0x73U, 0x20U, 0x3EU, 0x20U, 0x30U, 0x00U,
|
||||
0x73U, 0x6CU, 0x6FU, 0x74U, 0x28U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U,
|
||||
0x62U, 0x75U, 0x66U, 0x29U, 0x2CU, 0x20U, 0x31U, 0x29U, 0x20U, 0x3DU,
|
||||
0x3DU, 0x20U, 0x73U, 0x00U, 0x73U, 0x74U, 0x6FU, 0x5FU, 0x76U, 0x61U,
|
||||
0x6CU, 0x69U, 0x64U, 0x61U, 0x74U, 0x65U, 0x28U, 0x62U, 0x75U, 0x66U,
|
||||
0x2CU, 0x20U, 0x73U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x31U, 0x00U,
|
||||
0x01U, 0x20U, 0x02U, 0xA7U, 0x10U, 0x85U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x42U, 0x01U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xBCU, 0x89U, 0x80U, 0x80U,
|
||||
0x00U, 0x41U, 0x1AU, 0x42U, 0x33U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x1AU, 0x0BU, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x00U, 0x10U,
|
||||
0x86U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0xA0U,
|
||||
0xC0U, 0x00U, 0x6AU, 0x24U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x20U,
|
||||
0x02U, 0x0BU, 0x0BU, 0xE4U, 0x01U, 0x02U, 0x00U, 0x41U, 0x80U, 0x08U,
|
||||
0x0BU, 0x22U, 0x00U, 0x68U, 0xB4U, 0x97U, 0x9AU, 0x36U, 0xCDU, 0xC7U,
|
||||
0xF3U, 0xD3U, 0xD5U, 0xC3U, 0x1AU, 0x4EU, 0xAEU, 0x2AU, 0xC7U, 0xD7U,
|
||||
0x20U, 0x9DU, 0xDAU, 0x87U, 0x75U, 0x88U, 0xB9U, 0xAFU, 0xC6U, 0x67U,
|
||||
0x99U, 0x69U, 0x2AU, 0xB0U, 0xD6U, 0x6BU, 0x00U, 0x41U, 0xA2U, 0x08U,
|
||||
0x0BU, 0xB4U, 0x01U, 0x73U, 0x6CU, 0x6FU, 0x74U, 0x5FU, 0x73U, 0x69U,
|
||||
0x7AU, 0x65U, 0x28U, 0x31U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x44U,
|
||||
0x4FU, 0x45U, 0x53U, 0x4EU, 0x54U, 0x5FU, 0x45U, 0x58U, 0x49U, 0x53U,
|
||||
0x54U, 0x00U, 0x73U, 0x6CU, 0x6FU, 0x74U, 0x5FU, 0x73U, 0x65U, 0x74U,
|
||||
0x28U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U, 0x6BU, 0x6CU, 0x5FU, 0x73U,
|
||||
0x6BU, 0x29U, 0x2CU, 0x20U, 0x31U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U,
|
||||
0x31U, 0x00U, 0x73U, 0x6CU, 0x6FU, 0x74U, 0x5FU, 0x73U, 0x65U, 0x74U,
|
||||
0x28U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U, 0x6BU, 0x6CU, 0x5FU, 0x73U,
|
||||
0x6BU, 0x29U, 0x2CU, 0x20U, 0x32U, 0x35U, 0x35U, 0x29U, 0x20U, 0x3DU,
|
||||
0x3DU, 0x20U, 0x32U, 0x35U, 0x35U, 0x00U, 0x73U, 0x6CU, 0x6FU, 0x74U,
|
||||
0x5FU, 0x73U, 0x69U, 0x7AU, 0x65U, 0x28U, 0x31U, 0x29U, 0x20U, 0x3DU,
|
||||
0x3DU, 0x20U, 0x73U, 0x6CU, 0x6FU, 0x74U, 0x5FU, 0x73U, 0x69U, 0x7AU,
|
||||
0x65U, 0x28U, 0x32U, 0x35U, 0x35U, 0x29U, 0x00U, 0x73U, 0x20U, 0x3EU,
|
||||
0x20U, 0x30U, 0x00U, 0x73U, 0x6CU, 0x6FU, 0x74U, 0x28U, 0x53U, 0x42U,
|
||||
0x55U, 0x46U, 0x28U, 0x62U, 0x75U, 0x66U, 0x29U, 0x2CU, 0x20U, 0x31U,
|
||||
0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x73U, 0x00U, 0x73U, 0x74U, 0x6FU,
|
||||
0x5FU, 0x76U, 0x61U, 0x6CU, 0x69U, 0x64U, 0x61U, 0x74U, 0x65U, 0x28U,
|
||||
0x62U, 0x75U, 0x66U, 0x2CU, 0x20U, 0x73U, 0x29U, 0x20U, 0x3DU, 0x3DU,
|
||||
0x20U, 0x31U, 0x00U,
|
||||
}},
|
||||
|
||||
{R"[test.hook](
|
||||
|
||||
@@ -1410,6 +1410,7 @@ public:
|
||||
testAllTxns(sa);
|
||||
testAllTxns(sa - fixHookAPI20251128);
|
||||
testAllTxns(sa - featureTouch - fixHookAPI20251128);
|
||||
testAllTxns(sa - featureHookFeeV2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -142,6 +142,18 @@ computeExecutionFee(uint64_t instructionCount);
|
||||
int64_t
|
||||
computeCreationFee(uint64_t byteCount);
|
||||
|
||||
// HookFeeV2: converts a hook's cost units (see hook_api::api_call_cost) into
|
||||
// drops, rounding up
|
||||
XRPAmount
|
||||
hookCostToFee(uint64_t hookCost);
|
||||
|
||||
std::optional<std::pair<uint64_t, uint64_t>>
|
||||
doValidateGuards(
|
||||
STTx const& tx,
|
||||
Blob const& wasm,
|
||||
Rules const& rules,
|
||||
beast::Journal const& j);
|
||||
|
||||
struct HookResult
|
||||
{
|
||||
ripple::uint256 const hookSetTxnID;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <xrpld/app/tx/detail/NFTokenUtils.h>
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/hook/Guard.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/ErrorCodes.h>
|
||||
#include <xrpl/protocol/PublicKey.h>
|
||||
@@ -553,6 +554,9 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
|
||||
case ttREMARKS_SET: {
|
||||
break;
|
||||
}
|
||||
case ttHOOK_DEFINITION_UPDATE: {
|
||||
break;
|
||||
}
|
||||
// pseudo transactions
|
||||
case ttAMENDMENT:
|
||||
case ttFEE:
|
||||
@@ -692,6 +696,83 @@ hook::computeCreationFee(uint64_t byteCount)
|
||||
return fee;
|
||||
}
|
||||
|
||||
XRPAmount
|
||||
hook::hookCostToFee(uint64_t hookCost)
|
||||
{
|
||||
// round up, and avoid overflow: the quotient of a uint64 by 10 always
|
||||
// fits in an int64
|
||||
uint64_t const drops = hookCost / hook_api::cost_units_per_drop +
|
||||
(hookCost % hook_api::cost_units_per_drop != 0);
|
||||
return XRPAmount{static_cast<XRPAmount::value_type>(drops)};
|
||||
}
|
||||
|
||||
std::optional<std::pair<uint64_t, uint64_t>>
|
||||
hook::doValidateGuards(
|
||||
STTx const& tx,
|
||||
Blob const& wasm,
|
||||
Rules const& rules,
|
||||
beast::Journal const& j)
|
||||
{
|
||||
// RH NOTE: validateGuards has a generic non-rippled specific
|
||||
// interface so it can be used in other projects (i.e. tooling).
|
||||
// As such the calling here is a bit convoluted.
|
||||
|
||||
std::optional<std::reference_wrapper<std::basic_ostream<char>>> logger;
|
||||
std::ostringstream loggerStream;
|
||||
std::string hsacc{""};
|
||||
if (j.trace())
|
||||
{
|
||||
logger = loggerStream;
|
||||
std::stringstream ss;
|
||||
|
||||
#define HS_ACC() tx.getAccountID(sfAccount) << "-" << tx.getTransactionID()
|
||||
ss << HS_ACC();
|
||||
#undef HS_ACC
|
||||
hsacc = ss.str();
|
||||
}
|
||||
|
||||
auto result = validateGuards(
|
||||
wasm, // wasm to verify
|
||||
logger,
|
||||
hsacc,
|
||||
rules.enabled(featureHookFeeV2),
|
||||
hook_api::getImportWhitelist(rules),
|
||||
hook_api::getGuardRulesVersion(rules));
|
||||
|
||||
if (j.trace())
|
||||
{
|
||||
// clunky but to get the stream to accept the output
|
||||
// correctly we will split on new line and feed each line
|
||||
// one by one into the trace stream beast::Journal should be
|
||||
// updated to inherit from basic_ostream<char> then this
|
||||
// wouldn't be necessary.
|
||||
|
||||
// is this a needless copy or does the compiler do copy
|
||||
// elision here?
|
||||
std::string s = loggerStream.str();
|
||||
|
||||
char* data = s.data();
|
||||
size_t len = s.size();
|
||||
|
||||
char* last = data;
|
||||
size_t i = 0;
|
||||
for (; i < len; ++i)
|
||||
{
|
||||
if (data[i] == '\n')
|
||||
{
|
||||
data[i] = '\0';
|
||||
j.trace() << last;
|
||||
last = data + i;
|
||||
}
|
||||
}
|
||||
|
||||
if (last < data + i)
|
||||
j.trace() << last;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// many datatypes can be encoded into an int64_t
|
||||
inline std::variant<uint64_t, hook_api::hook_return_code>
|
||||
data_as_int64(void const* ptr_raw, uint32_t len)
|
||||
|
||||
@@ -775,6 +775,7 @@ Change::activateXahauGenesis()
|
||||
wasmBytes, // wasm to verify
|
||||
loggerStream,
|
||||
"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
false,
|
||||
hook_api::getImportWhitelist(ctx_.view().rules()),
|
||||
hook_api::getGuardRulesVersion(ctx_.view().rules()));
|
||||
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2025 XRPL-Labs
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <xrpld/app/tx/detail/HookDefinitionUpdate.h>
|
||||
#include <xrpl/protocol/TxFlags.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
NotTEC
|
||||
HookDefinitionUpdate::preflight(PreflightContext const& ctx)
|
||||
{
|
||||
if (!ctx.rules.enabled(featureHookFeeV2))
|
||||
return temDISABLED;
|
||||
|
||||
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
|
||||
return ret;
|
||||
|
||||
auto const& tx = ctx.tx;
|
||||
|
||||
if (tx.getFlags() & tfHookDefinitionUpdateMask)
|
||||
return temINVALID_FLAG;
|
||||
|
||||
return preflight2(ctx);
|
||||
}
|
||||
|
||||
TER
|
||||
HookDefinitionUpdate::preclaim(PreclaimContext const& ctx)
|
||||
{
|
||||
auto const& view = ctx.view;
|
||||
auto const& tx = ctx.tx;
|
||||
|
||||
if (!view.exists(keylet::hookDefinition(tx.getFieldH256(sfHookHash))))
|
||||
return tecNO_ENTRY;
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
TER
|
||||
HookDefinitionUpdate::doApply()
|
||||
{
|
||||
auto& view = ctx_.view();
|
||||
auto const& tx = ctx_.tx;
|
||||
|
||||
auto hookDefSle =
|
||||
view.peek(keylet::hookDefinition(tx.getFieldH256(sfHookHash)));
|
||||
if (!hookDefSle)
|
||||
return tefINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
Blob hook = hookDefSle->getFieldVL(sfCreateCode);
|
||||
|
||||
if (!tx.isFlag(tfValidateGuards))
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
auto const result =
|
||||
hook::doValidateGuards(tx, hook, view.rules(), ctx_.journal);
|
||||
if (!result)
|
||||
// TODO: TEQU better error code
|
||||
// For compatibility, if an already deployed HookDefinition fails with a
|
||||
// new guard-checker, don't update/delete it
|
||||
return tecINTERNAL;
|
||||
|
||||
auto const [hookCost, callbackCost] = *result;
|
||||
|
||||
{
|
||||
// if result is same as old, don't update sle
|
||||
if (hookCost == hookDefSle->getFieldU64(sfHookCost) &&
|
||||
callbackCost == hookDefSle->getFieldU64(sfHookCallbackCost))
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
{
|
||||
// set new cost fields
|
||||
hookDefSle->setFieldU64(sfHookCost, hookCost);
|
||||
if (callbackCost > 0)
|
||||
hookDefSle->setFieldU64(sfHookCallbackCost, callbackCost);
|
||||
else if (hookDefSle->isFieldPresent(sfHookCallbackCost))
|
||||
hookDefSle->makeFieldAbsent(sfHookCallbackCost);
|
||||
}
|
||||
|
||||
{
|
||||
// remove old fee fields
|
||||
if (hookDefSle->isFieldPresent(sfFee))
|
||||
hookDefSle->makeFieldAbsent(sfFee);
|
||||
if (hookDefSle->isFieldPresent(sfHookCallbackFee))
|
||||
hookDefSle->makeFieldAbsent(sfHookCallbackFee);
|
||||
}
|
||||
|
||||
view.update(hookDefSle);
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
XRPAmount
|
||||
HookDefinitionUpdate::calculateBaseFee(ReadView const& view, STTx const& tx)
|
||||
{
|
||||
auto const baseFee = Transactor::calculateBaseFee(view, tx);
|
||||
|
||||
auto const& hookDefSle =
|
||||
view.read(keylet::hookDefinition(tx.getFieldH256(sfHookHash)));
|
||||
|
||||
if (!hookDefSle || !hookDefSle->isFieldPresent(sfCreateCode))
|
||||
// if hook definition is not present, doValidateGuards will not call, so
|
||||
// no additional fee is needed
|
||||
return baseFee;
|
||||
|
||||
auto const hookCodeSize = hookDefSle->getFieldVL(sfCreateCode).size();
|
||||
|
||||
return baseFee + XRPAmount{hook::computeCreationFee(hookCodeSize)};
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
@@ -0,0 +1,53 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2025 XRPL-Labs
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TX_HOOKDEFINITIONUPDATE_H_INCLUDED
|
||||
#define RIPPLE_TX_HOOKDEFINITIONUPDATE_H_INCLUDED
|
||||
|
||||
#include <xrpld/app/tx/detail/Transactor.h>
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class HookDefinitionUpdate : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit HookDefinitionUpdate(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static XRPAmount
|
||||
calculateBaseFee(ReadView const& view, STTx const& tx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const&);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
@@ -556,59 +556,8 @@ SetHook::validateHookSetEntry(SetHookCtx& ctx, STObject const& hookSetObj)
|
||||
|
||||
Blob hook = hookSetObj.getFieldVL(sfCreateCode);
|
||||
|
||||
// RH NOTE: validateGuards has a generic non-rippled specific
|
||||
// interface so it can be used in other projects (i.e. tooling).
|
||||
// As such the calling here is a bit convoluted.
|
||||
|
||||
std::optional<std::reference_wrapper<std::basic_ostream<char>>>
|
||||
logger;
|
||||
std::ostringstream loggerStream;
|
||||
std::string hsacc{""};
|
||||
if (ctx.j.trace())
|
||||
{
|
||||
logger = loggerStream;
|
||||
std::stringstream ss;
|
||||
ss << HS_ACC();
|
||||
hsacc = ss.str();
|
||||
}
|
||||
|
||||
auto result = validateGuards(
|
||||
hook, // wasm to verify
|
||||
logger,
|
||||
hsacc,
|
||||
hook_api::getImportWhitelist(ctx.rules),
|
||||
hook_api::getGuardRulesVersion(ctx.rules));
|
||||
|
||||
if (ctx.j.trace())
|
||||
{
|
||||
// clunky but to get the stream to accept the output
|
||||
// correctly we will split on new line and feed each line
|
||||
// one by one into the trace stream beast::Journal should be
|
||||
// updated to inherit from basic_ostream<char> then this
|
||||
// wouldn't be necessary.
|
||||
|
||||
// is this a needless copy or does the compiler do copy
|
||||
// elision here?
|
||||
std::string s = loggerStream.str();
|
||||
|
||||
char* data = s.data();
|
||||
size_t len = s.size();
|
||||
|
||||
char* last = data;
|
||||
size_t i = 0;
|
||||
for (; i < len; ++i)
|
||||
{
|
||||
if (data[i] == '\n')
|
||||
{
|
||||
data[i] = '\0';
|
||||
ctx.j.trace() << last;
|
||||
last = data + i;
|
||||
}
|
||||
}
|
||||
|
||||
if (last < data + i)
|
||||
ctx.j.trace() << last;
|
||||
}
|
||||
auto const result =
|
||||
hook::doValidateGuards(ctx.tx, hook, ctx.rules, ctx.j);
|
||||
|
||||
if (!result)
|
||||
return false;
|
||||
@@ -1879,9 +1828,11 @@ SetHook::setHook()
|
||||
"SetHook::hsoCREATE : should never happen");
|
||||
}
|
||||
|
||||
// otherwise assign instruction counts
|
||||
std::tie(maxInstrCountHook, maxInstrCountCbak) =
|
||||
auto const instrCounts =
|
||||
std::get<std::pair<uint64_t, uint64_t>>(valid);
|
||||
|
||||
std::tie(maxInstrCountHook, maxInstrCountCbak) =
|
||||
instrCounts;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
@@ -1935,15 +1886,26 @@ SetHook::setHook()
|
||||
newHookDef->setFieldH256(
|
||||
sfHookSetTxnID, ctx.tx.getTransactionID());
|
||||
newHookDef->setFieldU64(sfReferenceCount, 1);
|
||||
newHookDef->setFieldAmount(
|
||||
sfFee,
|
||||
XRPAmount{
|
||||
hook::computeExecutionFee(maxInstrCountHook)});
|
||||
if (maxInstrCountCbak > 0)
|
||||
|
||||
if (view().rules().enabled(featureHookFeeV2))
|
||||
{
|
||||
newHookDef->setFieldU64(sfHookCost, maxInstrCountHook);
|
||||
if (maxInstrCountCbak > 0)
|
||||
newHookDef->setFieldU64(
|
||||
sfHookCallbackCost, maxInstrCountCbak);
|
||||
}
|
||||
else
|
||||
{
|
||||
newHookDef->setFieldAmount(
|
||||
sfHookCallbackFee,
|
||||
sfFee,
|
||||
XRPAmount{
|
||||
hook::computeExecutionFee(maxInstrCountCbak)});
|
||||
hook::computeExecutionFee(maxInstrCountHook)});
|
||||
if (maxInstrCountCbak > 0)
|
||||
newHookDef->setFieldAmount(
|
||||
sfHookCallbackFee,
|
||||
XRPAmount{hook::computeExecutionFee(
|
||||
maxInstrCountCbak)});
|
||||
}
|
||||
|
||||
if (flags)
|
||||
newHookDef->setFieldU32(sfFlags, newFlags);
|
||||
|
||||
@@ -251,7 +251,7 @@ Transactor::Transactor(ApplyContext& ctx)
|
||||
|
||||
// RH NOTE: this only computes one chain at a time, so if there is a receiving
|
||||
// side to a txn then it must seperately be computed by a second call here
|
||||
XRPAmount
|
||||
std::pair<XRPAmount, uint64_t>
|
||||
Transactor::calculateHookChainFee(
|
||||
ReadView const& view,
|
||||
STTx const& tx,
|
||||
@@ -261,9 +261,10 @@ Transactor::calculateHookChainFee(
|
||||
{
|
||||
std::shared_ptr<SLE const> hookSLE = view.read(hookKeylet);
|
||||
if (!hookSLE)
|
||||
return XRPAmount{0};
|
||||
return std::make_pair(XRPAmount{0}, 0);
|
||||
|
||||
XRPAmount fee{0};
|
||||
uint64_t hookCost{0};
|
||||
|
||||
auto const& hooks = hookSLE->getFieldArray(sfHooks);
|
||||
|
||||
@@ -304,19 +305,35 @@ Transactor::calculateHookChainFee(
|
||||
if (hook::canHook(tx, hookOn, hookName) &&
|
||||
(!collectCallsOnly || (flags & hook::hsfCOLLECT)))
|
||||
{
|
||||
XRPAmount const toAdd{hookDef->getFieldAmount(sfFee).xrp().drops()};
|
||||
if (hookDef->isFieldPresent(sfFee))
|
||||
{
|
||||
XRPAmount const toAdd{
|
||||
hookDef->getFieldAmount(sfFee).xrp().drops()};
|
||||
|
||||
// this overflow should never happen, if somehow it does
|
||||
// fee is set to the largest possible valid xrp value to force
|
||||
// fail the transaction
|
||||
if (fee + toAdd < fee)
|
||||
fee = XRPAmount{INITIAL_XRP.drops()};
|
||||
// this overflow should never happen, if somehow it does
|
||||
// fee is set to the largest possible valid xrp value to force
|
||||
// fail the transaction
|
||||
if (fee + toAdd < fee)
|
||||
fee = XRPAmount{INITIAL_XRP.drops()};
|
||||
else
|
||||
fee += toAdd;
|
||||
}
|
||||
else
|
||||
fee += toAdd;
|
||||
{
|
||||
uint64_t const toAdd{hookDef->getFieldU64(sfHookCost)};
|
||||
|
||||
// this overflow should never happen, if somehow it does
|
||||
// fee is set to the largest possible valid xrp value to force
|
||||
// fail the transaction
|
||||
if (hookCost + toAdd < hookCost)
|
||||
hookCost = std::numeric_limits<uint64_t>::max();
|
||||
else
|
||||
hookCost += toAdd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fee;
|
||||
return std::make_pair(fee, hookCost);
|
||||
}
|
||||
|
||||
XRPAmount
|
||||
@@ -342,6 +359,7 @@ Transactor::calculateBaseFee(ReadView const& view, STTx const& tx)
|
||||
tx.isFieldPresent(sfSigners) ? tx.getFieldArray(sfSigners).size() : 0;
|
||||
|
||||
XRPAmount hookExecutionFee{0};
|
||||
uint64_t hookCost{0};
|
||||
uint64_t burden{1};
|
||||
if (view.rules().enabled(featureHooks))
|
||||
{
|
||||
@@ -364,18 +382,32 @@ Transactor::calculateBaseFee(ReadView const& view, STTx const& tx)
|
||||
std::shared_ptr<SLE const> hookDef =
|
||||
view.read(keylet::hookDefinition(callbackHookHash));
|
||||
|
||||
if (hookDef && hookDef->isFieldPresent(sfHookCallbackFee))
|
||||
if (hookDef)
|
||||
{
|
||||
XRPAmount const toAdd{
|
||||
hookDef->getFieldAmount(sfHookCallbackFee).xrp().drops()};
|
||||
if (hookDef->isFieldPresent(sfHookCallbackFee))
|
||||
{
|
||||
XRPAmount const toAdd{
|
||||
hookDef->getFieldAmount(sfHookCallbackFee)
|
||||
.xrp()
|
||||
.drops()};
|
||||
|
||||
// this overflow should never happen, if somehow it does
|
||||
// fee is set to the largest possible valid xrp value to force
|
||||
// fail the transaction
|
||||
if (hookExecutionFee + toAdd < hookExecutionFee)
|
||||
hookExecutionFee = XRPAmount{INITIAL_XRP.drops()};
|
||||
else
|
||||
hookExecutionFee += toAdd;
|
||||
// this overflow should never happen, if somehow it does
|
||||
// fee is set to the largest possible valid xrp value to
|
||||
// force fail the transaction
|
||||
if (hookExecutionFee + toAdd < hookExecutionFee)
|
||||
hookExecutionFee = XRPAmount{INITIAL_XRP.drops()};
|
||||
else
|
||||
hookExecutionFee += toAdd;
|
||||
}
|
||||
if (hookDef->isFieldPresent(sfHookCallbackCost))
|
||||
{
|
||||
uint64_t const toAdd{
|
||||
hookDef->getFieldU64(sfHookCallbackCost)};
|
||||
if (hookCost + toAdd < hookCost)
|
||||
hookCost = std::numeric_limits<uint64_t>::max();
|
||||
else
|
||||
hookCost += toAdd;
|
||||
}
|
||||
}
|
||||
|
||||
XRPL_ASSERT(
|
||||
@@ -385,8 +417,12 @@ Transactor::calculateBaseFee(ReadView const& view, STTx const& tx)
|
||||
burden = emitDetails.getFieldU64(sfEmitBurden);
|
||||
}
|
||||
else
|
||||
hookExecutionFee += calculateHookChainFee(
|
||||
{
|
||||
auto const hookChainFee = calculateHookChainFee(
|
||||
view, tx, keylet::hook(tx.getAccountID(sfAccount)), true);
|
||||
hookExecutionFee += hookChainFee.first;
|
||||
hookCost += hookChainFee.second;
|
||||
}
|
||||
|
||||
// find any additional stakeholders whose hooks will be executed and
|
||||
// charged to this transaction
|
||||
@@ -395,8 +431,12 @@ Transactor::calculateBaseFee(ReadView const& view, STTx const& tx)
|
||||
|
||||
for (auto& [tshAcc, canRollback] : tsh)
|
||||
if (canRollback)
|
||||
hookExecutionFee += calculateHookChainFee(
|
||||
{
|
||||
auto const hookChainFee = calculateHookChainFee(
|
||||
view, tx, keylet::hook(tshAcc), false);
|
||||
hookExecutionFee += hookChainFee.first;
|
||||
hookCost += hookChainFee.second;
|
||||
}
|
||||
}
|
||||
|
||||
XRPAmount accumulator = baseFee;
|
||||
@@ -450,6 +490,8 @@ Transactor::calculateBaseFee(ReadView const& view, STTx const& tx)
|
||||
// transaction.
|
||||
do
|
||||
{
|
||||
hookExecutionFee += hook::hookCostToFee(hookCost);
|
||||
|
||||
if (accumulator * burden < accumulator)
|
||||
break;
|
||||
|
||||
@@ -1452,7 +1494,8 @@ Transactor::executeHookChain(
|
||||
return tecINTERNAL;
|
||||
}
|
||||
|
||||
bool hasCallback = hookDef->isFieldPresent(sfHookCallbackFee);
|
||||
bool hasCallback = hookDef->isFieldPresent(sfHookCallbackFee) ||
|
||||
hookDef->isFieldPresent(sfHookCallbackCost);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -1572,7 +1615,8 @@ Transactor::doHookCallback(
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hookDef->isFieldPresent(sfHookCallbackFee))
|
||||
if (!hookDef->isFieldPresent(sfHookCallbackFee) &&
|
||||
!hookDef->isFieldPresent(sfHookCallbackCost))
|
||||
{
|
||||
JLOG(j_.trace()) << "HookInfo[" << callbackAccountID
|
||||
<< "]: Callback specified by emitted txn "
|
||||
@@ -1799,8 +1843,11 @@ Transactor::doTSH(
|
||||
continue;
|
||||
|
||||
// compute and deduct fees for the TSH if applicable
|
||||
XRPAmount tshFeeDrops = calculateHookChainFee(
|
||||
auto const tshFee = calculateHookChainFee(
|
||||
view, ctx_.tx, klTshHook, false, !canRollback);
|
||||
XRPAmount tshFeeDrops{tshFee.first};
|
||||
|
||||
tshFeeDrops += hook::hookCostToFee(tshFee.second);
|
||||
|
||||
// no hooks to execute, skip tsh
|
||||
if (tshFeeDrops == 0)
|
||||
@@ -1955,7 +2002,8 @@ Transactor::doAgainAsWeak(
|
||||
stateMap,
|
||||
ctx_,
|
||||
hookAccountID,
|
||||
hookDef->isFieldPresent(sfHookCallbackFee),
|
||||
hookDef->isFieldPresent(sfHookCallbackFee) ||
|
||||
hookDef->isFieldPresent(sfHookCallbackCost),
|
||||
false,
|
||||
false,
|
||||
2UL, // param 2 = aaw
|
||||
|
||||
@@ -174,7 +174,7 @@ public:
|
||||
|
||||
// Hooks
|
||||
|
||||
static XRPAmount
|
||||
static std::pair<XRPAmount, uint64_t>
|
||||
calculateHookChainFee(
|
||||
ReadView const& view,
|
||||
STTx const& tx,
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <xrpld/app/tx/detail/DepositPreauth.h>
|
||||
#include <xrpld/app/tx/detail/Escrow.h>
|
||||
#include <xrpld/app/tx/detail/GenesisMint.h>
|
||||
#include <xrpld/app/tx/detail/HookDefinitionUpdate.h>
|
||||
#include <xrpld/app/tx/detail/Import.h>
|
||||
#include <xrpld/app/tx/detail/Invoke.h>
|
||||
#include <xrpld/app/tx/detail/LedgerStateFix.h>
|
||||
|
||||
@@ -76,10 +76,12 @@ doHookValidate(RPC::JsonContext& context)
|
||||
std::optional<std::pair<uint64_t, uint64_t>> result;
|
||||
try
|
||||
{
|
||||
auto const returnCost = rules.enabled(featureHookFeeV2);
|
||||
result = validateGuards(
|
||||
*blob,
|
||||
logger,
|
||||
"",
|
||||
returnCost,
|
||||
hook_api::getImportWhitelist(rules),
|
||||
hook_api::getGuardRulesVersion(rules));
|
||||
}
|
||||
|
||||
@@ -59,6 +59,13 @@ MAGIC_ENUM_FLAG(ripple::PaymentChannelClaimFlags);
|
||||
MAGIC_ENUM_FLAG(ripple::NFTokenMintFlags);
|
||||
MAGIC_ENUM_FLAG(ripple::NFTokenCreateOfferFlags);
|
||||
MAGIC_ENUM_FLAG(ripple::ClaimRewardFlags);
|
||||
MAGIC_ENUM_FLAG(ripple::HookDefinitionUpdateFlags);
|
||||
MAGIC_ENUM_FLAG(ripple::CronSetFlags);
|
||||
MAGIC_ENUM_FLAG(ripple::BridgeModifyFlags);
|
||||
MAGIC_ENUM_FLAG(ripple::MPTokenIssuanceCreateFlags);
|
||||
MAGIC_ENUM_FLAG(ripple::MPTokenAuthorizeFlags);
|
||||
MAGIC_ENUM_FLAG(ripple::MPTokenIssuanceSetFlags);
|
||||
MAGIC_ENUM_FLAG(ripple::AMMClawbackFlags);
|
||||
MAGIC_ENUM_16(ripple::AccountFlags);
|
||||
|
||||
// hook_return_code spans [-10024, 0] because of INVALID_FLOAT
|
||||
@@ -379,6 +386,7 @@ private:
|
||||
addFlagsToJson<NFTokenMintFlags>(ret, "NFTokenMint");
|
||||
addFlagsToJson<NFTokenCreateOfferFlags>(ret, "NFTokenCreateOffer");
|
||||
addFlagsToJson<ClaimRewardFlags>(ret, "ClaimReward");
|
||||
addFlagsToJson<HookDefinitionUpdateFlags>(ret, "HookDefinitionUpdate");
|
||||
addFlagsToJson<CronSetFlags>(ret, "CronSet");
|
||||
addFlagsToJson<BridgeModifyFlags>(ret, "XChainModifyBridge");
|
||||
addFlagsToJson<MPTokenIssuanceCreateFlags>(
|
||||
|
||||
Reference in new issue
Block a user