mirror of
https://github.com/Xahau/xahaud.git
synced 2026-10-23 04:07:13 +00:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a90944e09d | ||
|
|
37161f82d5 | ||
|
|
e690bee955 | ||
|
|
871dbc2596 | ||
|
|
653927eb49 |
No files matched your search
@@ -10971,6 +10971,587 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_state_foreign_set_touch(FeatureBitset features)
|
||||
{
|
||||
testcase("Test hook state writes touch the state owner");
|
||||
using namespace jtx;
|
||||
|
||||
if (!features[featureTouch])
|
||||
return;
|
||||
|
||||
for (bool const withFix : {false, true})
|
||||
{
|
||||
Env env{
|
||||
*this,
|
||||
withFix ? features | fix20261005 : features - fix20261005};
|
||||
|
||||
auto const alice = Account{"alice"}; // grantor
|
||||
auto const bob = Account{"bob"}; // strong grantee
|
||||
auto const cho = Account{"cho"}; // invoker
|
||||
auto const dan = Account{"dan"}; // weak grantee
|
||||
auto const eve = Account{"eve"}; // callback grantee
|
||||
env.fund(XRP(10000), alice, bob, cho, dan, eve);
|
||||
|
||||
// Same hooks as test_state_foreign_set: bob's hook writes the
|
||||
// current txn id under key 1, namespace 0, of the account named
|
||||
// in the InvoiceID; alice's hook deletes that key whenever alice
|
||||
// sends a txn.
|
||||
TestHook grantee_wasm = wasm[R"[test.hook](
|
||||
#include <stdint.h>
|
||||
#define sfInvoiceID ((5U << 16U) + 17U)
|
||||
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 rollback (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
extern int64_t state_foreign (
|
||||
uint32_t, uint32_t, uint32_t, uint32_t,
|
||||
uint32_t, uint32_t, uint32_t, uint32_t
|
||||
);
|
||||
extern int64_t state_foreign_set (
|
||||
uint32_t, uint32_t, uint32_t, uint32_t,
|
||||
uint32_t, uint32_t, uint32_t, uint32_t
|
||||
);
|
||||
extern int64_t otxn_id(uint32_t, uint32_t, uint32_t);
|
||||
extern int64_t otxn_field(uint32_t, uint32_t, uint32_t);
|
||||
#define ASSERT(x)\
|
||||
if (!(x))\
|
||||
rollback((uint32_t)#x, sizeof(#x), __LINE__);
|
||||
|
||||
#define TOO_BIG (-3)
|
||||
#define TOO_SMALL (-4)
|
||||
#define OUT_OF_BOUNDS (-1)
|
||||
#define DOESNT_EXIST (-5)
|
||||
#define INVALID_ARGUMENT (-7)
|
||||
#define SBUF(x) (uint32_t)(x), sizeof(x)
|
||||
int64_t hook(uint32_t reserved )
|
||||
{
|
||||
_g(1,1);
|
||||
|
||||
// bounds tests
|
||||
int64_t y;
|
||||
ASSERT((y=state_foreign_set(1111111, 32, 1, 32, 1, 32, 1, 20)) == OUT_OF_BOUNDS);
|
||||
ASSERT((y=state_foreign_set(1, 1111111, 1, 32, 1, 32, 1, 20)) == OUT_OF_BOUNDS);
|
||||
ASSERT((y=state_foreign_set(1, 32, 1111111, 32, 1, 32, 1, 20)) == OUT_OF_BOUNDS);
|
||||
ASSERT((y=state_foreign_set(1, 32, 1, 1111111, 1, 32, 1, 20)) == TOO_BIG);
|
||||
ASSERT((y=state_foreign_set(1, 32, 1, 32, 1111111, 32, 1, 20)) == OUT_OF_BOUNDS);
|
||||
ASSERT((y=state_foreign_set(1, 32, 1, 32, 1, 1111111, 1, 20)) == INVALID_ARGUMENT);
|
||||
ASSERT((y=state_foreign_set(1, 32, 1, 32, 1, 32, 1111111, 20)) == OUT_OF_BOUNDS);
|
||||
ASSERT((y=state_foreign_set(1, 32, 1, 32, 1, 32, 1, 1111111)) == INVALID_ARGUMENT);
|
||||
|
||||
// get this transaction id
|
||||
uint8_t txn[32];
|
||||
ASSERT(otxn_id(SBUF(txn), 0) == 32);
|
||||
|
||||
// get the invoice id, which contains the grantor account
|
||||
uint8_t grantor[32];
|
||||
ASSERT(otxn_field(SBUF(grantor), sfInvoiceID) == 32);
|
||||
|
||||
// set the current txn id on the grantor's state under key 1, namespace 0
|
||||
uint8_t one[32]; one[31] = 1U;
|
||||
uint8_t zero[32];
|
||||
ASSERT(state_foreign_set(SBUF(txn), SBUF(one), SBUF(zero), grantor + 12, 20) == 32);
|
||||
|
||||
return accept(0,0,0);
|
||||
}
|
||||
)[test.hook]"];
|
||||
|
||||
HASH_WASM(grantee);
|
||||
|
||||
TestHook grantor_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 rollback (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
extern int64_t otxn_field (uint32_t, uint32_t, uint32_t);
|
||||
extern int64_t hook_account(uint32_t write_ptr, uint32_t write_len);
|
||||
extern int64_t state_foreign_set (
|
||||
uint32_t, uint32_t, uint32_t, uint32_t,
|
||||
uint32_t, uint32_t, uint32_t, uint32_t
|
||||
);
|
||||
#define DOESNT_EXIST (-5)
|
||||
#define ASSERT(x)\
|
||||
if (!(x))\
|
||||
rollback((uint32_t)#x, sizeof(#x), __LINE__);
|
||||
|
||||
#define BUFFER_EQUAL_20(buf1, buf2)\
|
||||
(\
|
||||
*(((uint64_t*)(buf1)) + 0) == *(((uint64_t*)(buf2)) + 0) &&\
|
||||
*(((uint64_t*)(buf1)) + 1) == *(((uint64_t*)(buf2)) + 1) &&\
|
||||
*(((uint32_t*)(buf1)) + 4) == *(((uint32_t*)(buf2)) + 4))
|
||||
#define SBUF(x) (uint32_t)(x), sizeof(x)
|
||||
|
||||
#define sfAccount ((8U << 16U) + 1U)
|
||||
int64_t hook(uint32_t reserved )
|
||||
{
|
||||
_g(1,1);
|
||||
uint8_t otxnacc[20];
|
||||
ASSERT(otxn_field(SBUF(otxnacc), sfAccount) == 20);
|
||||
|
||||
uint8_t hookacc[20];
|
||||
ASSERT(hook_account(SBUF(hookacc)) == 20);
|
||||
|
||||
if (BUFFER_EQUAL_20(otxnacc, hookacc))
|
||||
{
|
||||
// outgoin txn, delete the state
|
||||
uint8_t one[32]; one[31] = 1U;
|
||||
uint8_t zero[32];
|
||||
// we can use state_foreign_set to do the deletion, a concise way to test this functionality too
|
||||
int64_t y = state_foreign_set(0,0, SBUF(one), SBUF(zero), SBUF(hookacc));
|
||||
ASSERT(y == 0 || y == DOESNT_EXIST);
|
||||
}
|
||||
|
||||
|
||||
return accept(0,0,0);
|
||||
}
|
||||
)[test.hook]"];
|
||||
|
||||
HASH_WASM(grantor);
|
||||
|
||||
// dan's hook writes nothing when executed strongly, it only asks
|
||||
// to be executed again weakly. Then it writes the txn id under key
|
||||
// 2, namespace 0, of the account named in the InvoiceID or, if the
|
||||
// txn carries the parameter D, deletes key 4 there instead.
|
||||
TestHook weak_grantee_wasm = wasm[R"[test.hook](
|
||||
#include <stdint.h>
|
||||
extern int32_t _g (uint32_t id, uint32_t maxiter);
|
||||
extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
extern int64_t rollback (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
extern int64_t hook_again (void);
|
||||
extern int64_t otxn_id (uint32_t, uint32_t, uint32_t);
|
||||
extern int64_t otxn_field (uint32_t, uint32_t, uint32_t);
|
||||
extern int64_t otxn_param (uint32_t, uint32_t, uint32_t, uint32_t);
|
||||
extern int64_t state_foreign_set (
|
||||
uint32_t, uint32_t, uint32_t, uint32_t,
|
||||
uint32_t, uint32_t, uint32_t, uint32_t
|
||||
);
|
||||
#define sfInvoiceID ((5U << 16U) + 17U)
|
||||
#define SBUF(x) (uint32_t)(x), sizeof(x)
|
||||
#define ASSERT(x)\
|
||||
if (!(x))\
|
||||
rollback((uint32_t)#x, sizeof(#x), __LINE__);
|
||||
|
||||
uint8_t ns[32];
|
||||
uint8_t write_key[32] = { [31] = 2U };
|
||||
uint8_t delete_key[32] = { [31] = 4U };
|
||||
|
||||
int64_t hook(uint32_t r)
|
||||
{
|
||||
_g(1,1);
|
||||
|
||||
// strong execution: write nothing, ask to be executed again weakly
|
||||
if (r == 0)
|
||||
{
|
||||
ASSERT(hook_again() == 1);
|
||||
return accept(0,0,0);
|
||||
}
|
||||
|
||||
// the grantor is the account in the low 20 bytes of the InvoiceID
|
||||
uint8_t grantor[32];
|
||||
ASSERT(otxn_field(SBUF(grantor), sfInvoiceID) == 32);
|
||||
|
||||
// with otxn parameter D, delete a key the grantor does not have
|
||||
uint8_t d[1];
|
||||
if (otxn_param(SBUF(d), (uint32_t)"D", 1) == 1)
|
||||
{
|
||||
ASSERT(state_foreign_set(0, 0, SBUF(delete_key), SBUF(ns), (uint32_t)(grantor + 12), 20) == 0);
|
||||
return accept(0,0,0);
|
||||
}
|
||||
|
||||
// otherwise write the otxn id under key 2
|
||||
uint8_t txn[32];
|
||||
ASSERT(otxn_id(SBUF(txn), 0) == 32);
|
||||
ASSERT(state_foreign_set(SBUF(txn), SBUF(write_key), SBUF(ns), (uint32_t)(grantor + 12), 20) == 32);
|
||||
|
||||
return accept(0,0,0);
|
||||
}
|
||||
)[test.hook]"];
|
||||
|
||||
HASH_WASM(weak_grantee);
|
||||
|
||||
// eve's hook emits an Invoke. Its callback, which runs when that
|
||||
// Invoke is applied, writes the Invoke's id under key 3, namespace
|
||||
// 0, of the account in the hook parameter G.
|
||||
TestHook cbak_grantee_wasm = wasm[R"[test.hook](
|
||||
#include <stdint.h>
|
||||
extern int32_t _g (uint32_t id, uint32_t maxiter);
|
||||
extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
extern int64_t rollback (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
extern int64_t emit (uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
|
||||
extern int64_t hook_account (uint32_t write_ptr, uint32_t write_len);
|
||||
extern int64_t hook_param (uint32_t, uint32_t, uint32_t, uint32_t);
|
||||
extern int64_t etxn_reserve (uint32_t);
|
||||
extern int64_t etxn_fee_base (uint32_t read_ptr, uint32_t read_len);
|
||||
extern int64_t etxn_details (uint32_t write_ptr, uint32_t write_len);
|
||||
extern int64_t ledger_seq (void);
|
||||
extern int64_t otxn_id (uint32_t, uint32_t, uint32_t);
|
||||
extern int64_t state_foreign_set (
|
||||
uint32_t, uint32_t, uint32_t, uint32_t,
|
||||
uint32_t, uint32_t, uint32_t, uint32_t
|
||||
);
|
||||
#define SBUF(x) (uint32_t)(x), sizeof(x)
|
||||
#define ASSERT(x)\
|
||||
if (!(x))\
|
||||
rollback((uint32_t)#x, sizeof(#x), __LINE__);
|
||||
|
||||
uint8_t ns[32];
|
||||
uint8_t write_key[32] = { [31] = 3U };
|
||||
|
||||
// an Invoke from the hook account, emitted so its callback runs
|
||||
uint8_t txn[229] =
|
||||
{
|
||||
/* size, upto, field name */
|
||||
/* 3, 0, tt = Invoke */ 0x12U, 0x00U, 0x63U,
|
||||
/* 5, 3, flags */ 0x22U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
/* 5, 8, sequence */ 0x24U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
/* 6, 13, firstledgersequence */ 0x20U, 0x1AU, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
/* 6, 19, lastledgersequence */ 0x20U, 0x1BU, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
/* 9, 25, fee */ 0x68U, 0x40U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
/* 35, 34, signingpubkey */ 0x73U, 0x21U, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
/* 22, 69, account */ 0x81U, 0x14U, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
/* 138, 91, emit details */
|
||||
/* 0, 229, */
|
||||
};
|
||||
#define FLS_OUT (txn + 15U)
|
||||
#define LLS_OUT (txn + 21U)
|
||||
#define FEE_OUT (txn + 26U)
|
||||
#define ACCOUNT_OUT (txn + 71U)
|
||||
#define EMIT_OUT (txn + 91U)
|
||||
#define SET_UINT32(ptr, value)\
|
||||
{\
|
||||
uint32_t v = (value);\
|
||||
(ptr)[0] = v >> 24U; (ptr)[1] = v >> 16U; (ptr)[2] = v >> 8U; (ptr)[3] = v;\
|
||||
}
|
||||
#define SET_NATIVE_AMOUNT(ptr, amount)\
|
||||
{\
|
||||
uint64_t a = (amount);\
|
||||
(ptr)[0] = 0x40U + ((a >> 56U) & 0x3FU);\
|
||||
(ptr)[1] = a >> 48U; (ptr)[2] = a >> 40U; (ptr)[3] = a >> 32U;\
|
||||
(ptr)[4] = a >> 24U; (ptr)[5] = a >> 16U; (ptr)[6] = a >> 8U; (ptr)[7] = a;\
|
||||
}
|
||||
|
||||
int64_t cbak(uint32_t r)
|
||||
{
|
||||
_g(1,1);
|
||||
|
||||
// the grantor is the hook parameter G
|
||||
uint8_t grantor[20];
|
||||
ASSERT(hook_param(SBUF(grantor), (uint32_t)"G", 1) == 20);
|
||||
|
||||
// in a callback the otxn is the emitted txn: write its id under key 3
|
||||
uint8_t id[32];
|
||||
ASSERT(otxn_id(SBUF(id), 0) == 32);
|
||||
ASSERT(state_foreign_set(SBUF(id), SBUF(write_key), SBUF(ns), SBUF(grantor)) == 32);
|
||||
|
||||
return accept(0,0,0);
|
||||
}
|
||||
|
||||
int64_t hook(uint32_t r)
|
||||
{
|
||||
_g(1,1);
|
||||
|
||||
ASSERT(etxn_reserve(1) == 1);
|
||||
uint32_t fls = (uint32_t)ledger_seq() + 1;
|
||||
SET_UINT32(FLS_OUT, fls);
|
||||
SET_UINT32(LLS_OUT, fls + 4);
|
||||
ASSERT(hook_account(ACCOUNT_OUT, 20) == 20);
|
||||
ASSERT(etxn_details(EMIT_OUT, 138U) == 138);
|
||||
int64_t fee = etxn_fee_base(SBUF(txn));
|
||||
ASSERT(fee > 0);
|
||||
SET_NATIVE_AMOUNT(FEE_OUT, fee);
|
||||
|
||||
uint8_t emithash[32];
|
||||
ASSERT(emit(SBUF(emithash), SBUF(txn)) == 32);
|
||||
|
||||
return accept(0,0,0);
|
||||
}
|
||||
)[test.hook]"];
|
||||
|
||||
HASH_WASM(cbak_grantee);
|
||||
|
||||
// alice grants each grantee hook the right to write her state
|
||||
{
|
||||
Json::Value grants{Json::arrayValue};
|
||||
auto const grant = [&](std::string const& hash,
|
||||
Account const& grantee) {
|
||||
Json::Value g;
|
||||
g[jss::HookGrant][jss::HookHash] = hash;
|
||||
g[jss::HookGrant][jss::Authorize] = grantee.human();
|
||||
grants.append(g);
|
||||
};
|
||||
grant(grantee_hash_str, bob);
|
||||
grant(weak_grantee_hash_str, dan);
|
||||
grant(cbak_grantee_hash_str, eve);
|
||||
|
||||
Json::Value json = ripple::test::jtx::hook(
|
||||
alice, {{hso(grantor_wasm, overrideFlag)}}, 0);
|
||||
json[jss::Hooks][0U][jss::Hook][jss::HookGrants] = grants;
|
||||
env(json, M("touch: set grantor"), HSFEE);
|
||||
}
|
||||
env(ripple::test::jtx::hook(
|
||||
bob, {{hso(grantee_wasm, overrideFlag)}}, 0),
|
||||
M("touch: set grantee"),
|
||||
HSFEE);
|
||||
env(ripple::test::jtx::hook(
|
||||
dan, {{hso(weak_grantee_wasm, overrideFlag)}}, 0),
|
||||
M("touch: set weak grantee"),
|
||||
HSFEE);
|
||||
{
|
||||
Json::Value params{Json::arrayValue};
|
||||
params[0U][jss::HookParameter][jss::HookParameterName] =
|
||||
strHex(std::string("G"));
|
||||
params[0U][jss::HookParameter][jss::HookParameterValue] =
|
||||
strHex(alice.id());
|
||||
|
||||
Json::Value json = ripple::test::jtx::hook(
|
||||
eve, {{hso(cbak_grantee_wasm, overrideFlag)}}, 0);
|
||||
json[jss::Hooks][0U][jss::Hook][jss::HookParameters] = params;
|
||||
env(json, M("touch: set callback grantee"), HSFEE);
|
||||
}
|
||||
env.close();
|
||||
|
||||
uint256 const ns{beast::zero};
|
||||
auto const aliceState = [&](std::uint8_t n) {
|
||||
uint256 key;
|
||||
key.data()[31] = n;
|
||||
return env.le(keylet::hookState(alice.id(), key, ns));
|
||||
};
|
||||
auto const stateIs = [&](std::uint8_t n, uint256 const& txid) {
|
||||
auto const sle = aliceState(n);
|
||||
return sle &&
|
||||
sle->getFieldVL(sfHookStateData) ==
|
||||
Blob(txid.begin(), txid.end());
|
||||
};
|
||||
|
||||
auto const touchCount = [&]() -> std::uint64_t {
|
||||
auto const sle = env.le(alice);
|
||||
return sle->isFieldPresent(sfTouchCount)
|
||||
? sle->getFieldU64(sfTouchCount)
|
||||
: 0;
|
||||
};
|
||||
auto const prevTxnID = [&]() {
|
||||
return env.le(alice)->getFieldH256(sfPreviousTxnID);
|
||||
};
|
||||
|
||||
auto const aliceKey = keylet::account(alice.id()).key;
|
||||
auto const inMeta =
|
||||
[&](std::shared_ptr<STObject const> const& meta) -> bool {
|
||||
if (!meta)
|
||||
return false;
|
||||
for (auto const& node : meta->getFieldArray(sfAffectedNodes))
|
||||
if (node.getFieldH256(sfLedgerIndex) == aliceKey)
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
// env.meta() closes the ledger, so call it before reading state
|
||||
auto const aliceInMeta = [&]() -> bool {
|
||||
return inMeta(env.meta());
|
||||
};
|
||||
|
||||
std::string const invid = std::string(24, '0') + strHex(alice.id());
|
||||
auto const payTo = [&](Account const& from,
|
||||
Account const& to,
|
||||
PrettyAmount const& amount) {
|
||||
Json::Value json = pay(from, to, amount);
|
||||
json[jss::InvoiceID] = invid;
|
||||
return json;
|
||||
};
|
||||
|
||||
// 1. strong pass, first write creates key 1: HookStateCount
|
||||
// changes, so alice's root is modified either way; only the
|
||||
// fix also touches it
|
||||
{
|
||||
auto const before = touchCount();
|
||||
env(payTo(cho, bob, XRP(1)),
|
||||
fee(XRP(1)),
|
||||
M("touch: create"),
|
||||
ter(tesSUCCESS));
|
||||
auto const txid = env.tx()->getTransactionID();
|
||||
BEAST_EXPECT(aliceInMeta());
|
||||
BEAST_EXPECT(touchCount() == before + (withFix ? 1 : 0));
|
||||
BEAST_EXPECT(stateIs(1, txid));
|
||||
}
|
||||
|
||||
// 2. overwrite of the existing key: alice is not a stakeholder,
|
||||
// so without the fix her root is untouched and unthreaded
|
||||
{
|
||||
auto const before = touchCount();
|
||||
auto const prev = prevTxnID();
|
||||
env(payTo(cho, bob, XRP(1)),
|
||||
fee(XRP(1)),
|
||||
M("touch: overwrite"),
|
||||
ter(tesSUCCESS));
|
||||
auto const txid = env.tx()->getTransactionID();
|
||||
BEAST_EXPECT(aliceInMeta() == withFix);
|
||||
BEAST_EXPECT(touchCount() == before + (withFix ? 1 : 0));
|
||||
BEAST_EXPECT(prevTxnID() == (withFix ? txid : prev));
|
||||
BEAST_EXPECT(stateIs(1, txid));
|
||||
}
|
||||
|
||||
// 3. alice is also a strong stakeholder (payment destination) and
|
||||
// bob's outgoing hook writes her state: touched exactly once
|
||||
{
|
||||
auto const before = touchCount();
|
||||
env(payTo(bob, alice, XRP(1)),
|
||||
fee(XRP(1)),
|
||||
M("touch: tsh"),
|
||||
ter(tesSUCCESS));
|
||||
BEAST_EXPECT(aliceInMeta());
|
||||
BEAST_EXPECT(touchCount() == before + 1);
|
||||
}
|
||||
|
||||
// 4. a rejected invocation writes nothing and touches nothing
|
||||
{
|
||||
auto const before = touchCount();
|
||||
Json::Value json = pay(cho, bob, XRP(1));
|
||||
json[jss::InvoiceID] =
|
||||
"0000000000000000000000000000000000000000000000000000000000"
|
||||
"000001";
|
||||
env(json,
|
||||
fee(XRP(1)),
|
||||
M("touch: rejected"),
|
||||
ter(tecHOOK_REJECTED));
|
||||
BEAST_EXPECT(!aliceInMeta());
|
||||
BEAST_EXPECT(touchCount() == before);
|
||||
}
|
||||
|
||||
// the otxn account is a weak stakeholder under fixHookAPI20251128
|
||||
bool const senderTouched =
|
||||
env.current()->rules().enabled(fixHookAPI20251128);
|
||||
|
||||
// 5. alice sends to bob: bob's strong hook overwrites her key 1
|
||||
// before the weak pass touches her as the sender. Under the fix
|
||||
// that write has already touched her, so the weak pass must
|
||||
// not touch her again.
|
||||
{
|
||||
auto const before = touchCount();
|
||||
env(payTo(alice, bob, XRP(1)),
|
||||
fee(XRP(1)),
|
||||
M("touch: foreign write, then weak tsh"),
|
||||
ter(tesSUCCESS));
|
||||
auto const txid = env.tx()->getTransactionID();
|
||||
BEAST_EXPECT(aliceInMeta());
|
||||
BEAST_EXPECT(
|
||||
touchCount() ==
|
||||
before + ((withFix || senderTouched) ? 1 : 0));
|
||||
BEAST_EXPECT(stateIs(1, txid));
|
||||
}
|
||||
|
||||
// 6. as 5, but the payment fails after the strong pass. The reset
|
||||
// discards the strong pass' state write and touch, so the weak
|
||||
// pass must touch alice afresh.
|
||||
{
|
||||
auto const before = touchCount();
|
||||
auto const sle = aliceState(1);
|
||||
BEAST_REQUIRE(sle);
|
||||
auto const value = sle->getFieldVL(sfHookStateData);
|
||||
env(payTo(alice, bob, XRP(100000)),
|
||||
fee(XRP(1)),
|
||||
M("touch: reset"),
|
||||
ter(tecUNFUNDED_PAYMENT));
|
||||
BEAST_EXPECT(aliceInMeta());
|
||||
BEAST_EXPECT(touchCount() == before + (senderTouched ? 1 : 0));
|
||||
auto const after = aliceState(1);
|
||||
BEAST_EXPECT(
|
||||
after && after->getFieldVL(sfHookStateData) == value);
|
||||
}
|
||||
|
||||
// every execution of the last txn's hooks accepted
|
||||
auto const allAccepted =
|
||||
[&](std::shared_ptr<STObject const> const& meta,
|
||||
std::size_t count) -> bool {
|
||||
if (!meta || !meta->isFieldPresent(sfHookExecutions))
|
||||
return false;
|
||||
auto const& executions = meta->getFieldArray(sfHookExecutions);
|
||||
if (executions.size() != count)
|
||||
return false;
|
||||
for (auto const& execution : executions)
|
||||
if (execution.getFieldU8(sfHookResult) !=
|
||||
static_cast<std::uint8_t>(hook_api::ExitType::ACCEPT))
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
// 7. weak pass: dan's hook writes key 2 only when it is executed
|
||||
// again as weak, after the payment has applied. The first
|
||||
// write creates the key and so modifies alice's root either
|
||||
// way; the second only overwrites it.
|
||||
for (bool const create : {true, false})
|
||||
{
|
||||
auto const before = touchCount();
|
||||
auto const prev = prevTxnID();
|
||||
env(payTo(cho, dan, XRP(1)),
|
||||
fee(XRP(1)),
|
||||
M(create ? "touch: weak create" : "touch: weak overwrite"),
|
||||
ter(tesSUCCESS));
|
||||
auto const txid = env.tx()->getTransactionID();
|
||||
auto const meta = env.meta();
|
||||
BEAST_EXPECT(allAccepted(meta, 2));
|
||||
BEAST_EXPECT(inMeta(meta) == (create || withFix));
|
||||
BEAST_EXPECT(touchCount() == before + (withFix ? 1 : 0));
|
||||
BEAST_EXPECT(
|
||||
prevTxnID() == ((create || withFix) ? txid : prev));
|
||||
BEAST_EXPECT(stateIs(2, txid));
|
||||
}
|
||||
|
||||
// 8. dan's weak execution deletes key 4, which alice never had.
|
||||
// Nothing of hers changes, so nothing touches her.
|
||||
{
|
||||
auto const before = touchCount();
|
||||
auto const prev = prevTxnID();
|
||||
Json::Value params{Json::arrayValue};
|
||||
params[0U][jss::HookParameter][jss::HookParameterName] =
|
||||
strHex(std::string("D"));
|
||||
params[0U][jss::HookParameter][jss::HookParameterValue] = "01";
|
||||
Json::Value json = payTo(cho, dan, XRP(1));
|
||||
json[jss::HookParameters] = params;
|
||||
env(json,
|
||||
fee(XRP(1)),
|
||||
M("touch: weak delete of a missing key"),
|
||||
ter(tesSUCCESS));
|
||||
auto const meta = env.meta();
|
||||
BEAST_EXPECT(allAccepted(meta, 2));
|
||||
BEAST_EXPECT(!inMeta(meta));
|
||||
BEAST_EXPECT(touchCount() == before);
|
||||
BEAST_EXPECT(prevTxnID() == prev);
|
||||
BEAST_EXPECT(!aliceState(4));
|
||||
}
|
||||
|
||||
// 9. callback: eve's hook emits an Invoke, whose callback writes
|
||||
// key 3 when the Invoke is applied in the following ledger.
|
||||
// Again the first write creates the key, the second overwrites.
|
||||
for (bool const create : {true, false})
|
||||
{
|
||||
auto const before = touchCount();
|
||||
auto const prev = prevTxnID();
|
||||
env(invoke::invoke(eve),
|
||||
fee(XRP(1)),
|
||||
M(create ? "touch: callback create"
|
||||
: "touch: callback overwrite"),
|
||||
ter(tesSUCCESS));
|
||||
env.close();
|
||||
|
||||
auto const meta = env.meta();
|
||||
BEAST_REQUIRE(meta && meta->isFieldPresent(sfHookEmissions));
|
||||
auto const etxn =
|
||||
meta->getFieldArray(sfHookEmissions)[0u].getFieldH256(
|
||||
sfEmittedTxnID);
|
||||
|
||||
// the emitted txn, and with it the callback, applies here
|
||||
env.close();
|
||||
auto const emitted = env.closed()->txRead(etxn);
|
||||
BEAST_REQUIRE(emitted.first && emitted.second);
|
||||
BEAST_EXPECT(allAccepted(emitted.second, 1));
|
||||
BEAST_EXPECT(inMeta(emitted.second) == (create || withFix));
|
||||
BEAST_EXPECT(touchCount() == before + (withFix ? 1 : 0));
|
||||
BEAST_EXPECT(
|
||||
prevTxnID() == ((create || withFix) ? etxn : prev));
|
||||
BEAST_EXPECT(stateIs(3, etxn));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_state_set(FeatureBitset features)
|
||||
{
|
||||
@@ -15630,11 +16211,12 @@ public:
|
||||
test_slot_subfield(features); //
|
||||
test_slot_type(features); //
|
||||
|
||||
test_state(features); //
|
||||
test_state_foreign(features); //
|
||||
test_state_foreign_set(features); //
|
||||
test_state_foreign_set_max(features); //
|
||||
test_state_set(features); //
|
||||
test_state(features); //
|
||||
test_state_foreign(features); //
|
||||
test_state_foreign_set(features); //
|
||||
test_state_foreign_set_max(features); //
|
||||
test_state_foreign_set_touch(features); //
|
||||
test_state_set(features); //
|
||||
|
||||
test_sto_emplace(features); //
|
||||
test_sto_erase(features); //
|
||||
|
||||
@@ -14858,6 +14858,759 @@ std::map<std::string, std::vector<uint8_t>> wasm = {
|
||||
0x3DU, 0x20U, 0x33U, 0x32U, 0x00U,
|
||||
}},
|
||||
|
||||
{R"[test.hook](
|
||||
#include <stdint.h>
|
||||
#define sfInvoiceID ((5U << 16U) + 17U)
|
||||
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 rollback (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
extern int64_t state_foreign (
|
||||
uint32_t, uint32_t, uint32_t, uint32_t,
|
||||
uint32_t, uint32_t, uint32_t, uint32_t
|
||||
);
|
||||
extern int64_t state_foreign_set (
|
||||
uint32_t, uint32_t, uint32_t, uint32_t,
|
||||
uint32_t, uint32_t, uint32_t, uint32_t
|
||||
);
|
||||
extern int64_t otxn_id(uint32_t, uint32_t, uint32_t);
|
||||
extern int64_t otxn_field(uint32_t, uint32_t, uint32_t);
|
||||
#define ASSERT(x)\
|
||||
if (!(x))\
|
||||
rollback((uint32_t)#x, sizeof(#x), __LINE__);
|
||||
|
||||
#define TOO_BIG (-3)
|
||||
#define TOO_SMALL (-4)
|
||||
#define OUT_OF_BOUNDS (-1)
|
||||
#define DOESNT_EXIST (-5)
|
||||
#define INVALID_ARGUMENT (-7)
|
||||
#define SBUF(x) (uint32_t)(x), sizeof(x)
|
||||
int64_t hook(uint32_t reserved )
|
||||
{
|
||||
_g(1,1);
|
||||
|
||||
// bounds tests
|
||||
int64_t y;
|
||||
ASSERT((y=state_foreign_set(1111111, 32, 1, 32, 1, 32, 1, 20)) == OUT_OF_BOUNDS);
|
||||
ASSERT((y=state_foreign_set(1, 1111111, 1, 32, 1, 32, 1, 20)) == OUT_OF_BOUNDS);
|
||||
ASSERT((y=state_foreign_set(1, 32, 1111111, 32, 1, 32, 1, 20)) == OUT_OF_BOUNDS);
|
||||
ASSERT((y=state_foreign_set(1, 32, 1, 1111111, 1, 32, 1, 20)) == TOO_BIG);
|
||||
ASSERT((y=state_foreign_set(1, 32, 1, 32, 1111111, 32, 1, 20)) == OUT_OF_BOUNDS);
|
||||
ASSERT((y=state_foreign_set(1, 32, 1, 32, 1, 1111111, 1, 20)) == INVALID_ARGUMENT);
|
||||
ASSERT((y=state_foreign_set(1, 32, 1, 32, 1, 32, 1111111, 20)) == OUT_OF_BOUNDS);
|
||||
ASSERT((y=state_foreign_set(1, 32, 1, 32, 1, 32, 1, 1111111)) == INVALID_ARGUMENT);
|
||||
|
||||
// get this transaction id
|
||||
uint8_t txn[32];
|
||||
ASSERT(otxn_id(SBUF(txn), 0) == 32);
|
||||
|
||||
// get the invoice id, which contains the grantor account
|
||||
uint8_t grantor[32];
|
||||
ASSERT(otxn_field(SBUF(grantor), sfInvoiceID) == 32);
|
||||
|
||||
// set the current txn id on the grantor's state under key 1, namespace 0
|
||||
uint8_t one[32]; one[31] = 1U;
|
||||
uint8_t zero[32];
|
||||
ASSERT(state_foreign_set(SBUF(txn), SBUF(one), SBUF(zero), grantor + 12, 20) == 32);
|
||||
|
||||
return accept(0,0,0);
|
||||
}
|
||||
)[test.hook]",
|
||||
{
|
||||
0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x26U,
|
||||
0x05U, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, 0x08U, 0x7FU,
|
||||
0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x01U, 0x7EU, 0x60U,
|
||||
0x03U, 0x7FU, 0x7FU, 0x7EU, 0x01U, 0x7EU, 0x60U, 0x03U, 0x7FU, 0x7FU,
|
||||
0x7FU, 0x01U, 0x7EU, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU, 0x02U, 0x5DU,
|
||||
0x06U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x02U, 0x5FU, 0x67U, 0x00U, 0x00U,
|
||||
0x03U, 0x65U, 0x6EU, 0x76U, 0x11U, 0x73U, 0x74U, 0x61U, 0x74U, 0x65U,
|
||||
0x5FU, 0x66U, 0x6FU, 0x72U, 0x65U, 0x69U, 0x67U, 0x6EU, 0x5FU, 0x73U,
|
||||
0x65U, 0x74U, 0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x08U, 0x72U,
|
||||
0x6FU, 0x6CU, 0x6CU, 0x62U, 0x61U, 0x63U, 0x6BU, 0x00U, 0x02U, 0x03U,
|
||||
0x65U, 0x6EU, 0x76U, 0x07U, 0x6FU, 0x74U, 0x78U, 0x6EU, 0x5FU, 0x69U,
|
||||
0x64U, 0x00U, 0x03U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x0AU, 0x6FU, 0x74U,
|
||||
0x78U, 0x6EU, 0x5FU, 0x66U, 0x69U, 0x65U, 0x6CU, 0x64U, 0x00U, 0x03U,
|
||||
0x03U, 0x65U, 0x6EU, 0x76U, 0x06U, 0x61U, 0x63U, 0x63U, 0x65U, 0x70U,
|
||||
0x74U, 0x00U, 0x02U, 0x03U, 0x02U, 0x01U, 0x04U, 0x05U, 0x03U, 0x01U,
|
||||
0x00U, 0x02U, 0x06U, 0x21U, 0x05U, 0x7FU, 0x01U, 0x41U, 0xE0U, 0x8DU,
|
||||
0x04U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0xD9U, 0x0DU, 0x0BU, 0x7FU, 0x00U,
|
||||
0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0xE0U, 0x8DU, 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, 0x01U, 0x7FU, 0x01U, 0x7EU,
|
||||
0x23U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x41U, 0x80U, 0x01U, 0x6BU,
|
||||
0x22U, 0x01U, 0x24U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x41U, 0x01U,
|
||||
0x41U, 0x01U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x02U,
|
||||
0x40U, 0x41U, 0xC7U, 0xE8U, 0xC3U, 0x00U, 0x41U, 0x20U, 0x41U, 0x01U,
|
||||
0x41U, 0x20U, 0x41U, 0x01U, 0x41U, 0x20U, 0x41U, 0x01U, 0x41U, 0x14U,
|
||||
0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U, 0x7FU, 0x51U, 0x0DU,
|
||||
0x00U, 0x41U, 0x80U, 0x88U, 0x80U, 0x80U, 0x00U, 0x41U, 0xC9U, 0x00U,
|
||||
0x42U, 0x22U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU,
|
||||
0x02U, 0x40U, 0x41U, 0x01U, 0x41U, 0xC7U, 0xE8U, 0xC3U, 0x00U, 0x41U,
|
||||
0x01U, 0x41U, 0x20U, 0x41U, 0x01U, 0x41U, 0x20U, 0x41U, 0x01U, 0x41U,
|
||||
0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U, 0x7FU, 0x51U,
|
||||
0x0DU, 0x00U, 0x41U, 0xC9U, 0x88U, 0x80U, 0x80U, 0x00U, 0x41U, 0xC8U,
|
||||
0x00U, 0x42U, 0x23U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU,
|
||||
0x0BU, 0x02U, 0x40U, 0x41U, 0x01U, 0x41U, 0x20U, 0x41U, 0xC7U, 0xE8U,
|
||||
0xC3U, 0x00U, 0x41U, 0x20U, 0x41U, 0x01U, 0x41U, 0x20U, 0x41U, 0x01U,
|
||||
0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U, 0x7FU,
|
||||
0x51U, 0x0DU, 0x00U, 0x41U, 0x91U, 0x89U, 0x80U, 0x80U, 0x00U, 0x41U,
|
||||
0xC9U, 0x00U, 0x42U, 0x24U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x1AU, 0x0BU, 0x02U, 0x40U, 0x41U, 0x01U, 0x41U, 0x20U, 0x41U, 0x01U,
|
||||
0x41U, 0xC7U, 0xE8U, 0xC3U, 0x00U, 0x41U, 0x01U, 0x41U, 0x20U, 0x41U,
|
||||
0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U,
|
||||
0x7DU, 0x51U, 0x0DU, 0x00U, 0x41U, 0xDAU, 0x89U, 0x80U, 0x80U, 0x00U,
|
||||
0x41U, 0xC2U, 0x00U, 0x42U, 0x25U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x41U, 0x01U, 0x41U, 0x20U, 0x41U,
|
||||
0x01U, 0x41U, 0x20U, 0x41U, 0xC7U, 0xE8U, 0xC3U, 0x00U, 0x41U, 0x20U,
|
||||
0x41U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x42U, 0x7FU, 0x51U, 0x0DU, 0x00U, 0x41U, 0x9CU, 0x8AU, 0x80U, 0x80U,
|
||||
0x00U, 0x41U, 0xC9U, 0x00U, 0x42U, 0x26U, 0x10U, 0x82U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x41U, 0x01U, 0x41U, 0x20U,
|
||||
0x41U, 0x01U, 0x41U, 0x20U, 0x41U, 0x01U, 0x41U, 0xC7U, 0xE8U, 0xC3U,
|
||||
0x00U, 0x41U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x42U, 0x79U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xE5U, 0x8AU, 0x80U,
|
||||
0x80U, 0x00U, 0x41U, 0xCBU, 0x00U, 0x42U, 0x27U, 0x10U, 0x82U, 0x80U,
|
||||
0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x41U, 0x01U, 0x41U,
|
||||
0x20U, 0x41U, 0x01U, 0x41U, 0x20U, 0x41U, 0x01U, 0x41U, 0x20U, 0x41U,
|
||||
0xC7U, 0xE8U, 0xC3U, 0x00U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x42U, 0x7FU, 0x51U, 0x0DU, 0x00U, 0x41U, 0xB0U, 0x8BU,
|
||||
0x80U, 0x80U, 0x00U, 0x41U, 0xC9U, 0x00U, 0x42U, 0x28U, 0x10U, 0x82U,
|
||||
0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x41U, 0x01U,
|
||||
0x41U, 0x20U, 0x41U, 0x01U, 0x41U, 0x20U, 0x41U, 0x01U, 0x41U, 0x20U,
|
||||
0x41U, 0x01U, 0x41U, 0xC7U, 0xE8U, 0xC3U, 0x00U, 0x10U, 0x81U, 0x80U,
|
||||
0x80U, 0x80U, 0x00U, 0x42U, 0x79U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xF9U,
|
||||
0x8BU, 0x80U, 0x80U, 0x00U, 0x41U, 0xCBU, 0x00U, 0x42U, 0x29U, 0x10U,
|
||||
0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x20U,
|
||||
0x01U, 0x41U, 0xE0U, 0x00U, 0x6AU, 0x41U, 0x20U, 0x41U, 0x00U, 0x10U,
|
||||
0x83U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U, 0x20U, 0x51U, 0x0DU, 0x00U,
|
||||
0x41U, 0xC4U, 0x8CU, 0x80U, 0x80U, 0x00U, 0x41U, 0x1CU, 0x42U, 0x2DU,
|
||||
0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U,
|
||||
0x20U, 0x01U, 0x41U, 0xC0U, 0x00U, 0x6AU, 0x41U, 0x20U, 0x41U, 0x91U,
|
||||
0x80U, 0x14U, 0x10U, 0x84U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U, 0x20U,
|
||||
0x51U, 0x0DU, 0x00U, 0x41U, 0xE0U, 0x8CU, 0x80U, 0x80U, 0x00U, 0x41U,
|
||||
0x2DU, 0x42U, 0x31U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU,
|
||||
0x0BU, 0x20U, 0x01U, 0x41U, 0x01U, 0x3AU, 0x00U, 0x3FU, 0x02U, 0x40U,
|
||||
0x20U, 0x01U, 0x41U, 0xE0U, 0x00U, 0x6AU, 0x41U, 0x20U, 0x20U, 0x01U,
|
||||
0x41U, 0x20U, 0x6AU, 0x41U, 0x20U, 0x20U, 0x01U, 0x41U, 0x20U, 0x20U,
|
||||
0x01U, 0x41U, 0xC0U, 0x00U, 0x6AU, 0x41U, 0x0CU, 0x72U, 0x41U, 0x14U,
|
||||
0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U, 0x20U, 0x51U, 0x0DU,
|
||||
0x00U, 0x41U, 0x8DU, 0x8DU, 0x80U, 0x80U, 0x00U, 0x41U, 0xCCU, 0x00U,
|
||||
0x42U, 0x36U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU,
|
||||
0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x00U, 0x10U, 0x85U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x21U, 0x02U, 0x20U, 0x01U, 0x41U, 0x80U, 0x01U, 0x6AU,
|
||||
0x24U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x20U, 0x02U, 0x0BU, 0x0BU,
|
||||
0xE1U, 0x05U, 0x01U, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0xD9U, 0x05U,
|
||||
0x28U, 0x79U, 0x3DU, 0x73U, 0x74U, 0x61U, 0x74U, 0x65U, 0x5FU, 0x66U,
|
||||
0x6FU, 0x72U, 0x65U, 0x69U, 0x67U, 0x6EU, 0x5FU, 0x73U, 0x65U, 0x74U,
|
||||
0x28U, 0x31U, 0x31U, 0x31U, 0x31U, 0x31U, 0x31U, 0x31U, 0x2CU, 0x20U,
|
||||
0x33U, 0x32U, 0x2CU, 0x20U, 0x31U, 0x2CU, 0x20U, 0x33U, 0x32U, 0x2CU,
|
||||
0x20U, 0x31U, 0x2CU, 0x20U, 0x33U, 0x32U, 0x2CU, 0x20U, 0x31U, 0x2CU,
|
||||
0x20U, 0x32U, 0x30U, 0x29U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x4FU,
|
||||
0x55U, 0x54U, 0x5FU, 0x4FU, 0x46U, 0x5FU, 0x42U, 0x4FU, 0x55U, 0x4EU,
|
||||
0x44U, 0x53U, 0x00U, 0x28U, 0x79U, 0x3DU, 0x73U, 0x74U, 0x61U, 0x74U,
|
||||
0x65U, 0x5FU, 0x66U, 0x6FU, 0x72U, 0x65U, 0x69U, 0x67U, 0x6EU, 0x5FU,
|
||||
0x73U, 0x65U, 0x74U, 0x28U, 0x31U, 0x2CU, 0x20U, 0x31U, 0x31U, 0x31U,
|
||||
0x31U, 0x31U, 0x31U, 0x31U, 0x2CU, 0x20U, 0x31U, 0x2CU, 0x20U, 0x33U,
|
||||
0x32U, 0x2CU, 0x20U, 0x31U, 0x2CU, 0x20U, 0x33U, 0x32U, 0x2CU, 0x20U,
|
||||
0x31U, 0x2CU, 0x20U, 0x32U, 0x30U, 0x29U, 0x29U, 0x20U, 0x3DU, 0x3DU,
|
||||
0x20U, 0x4FU, 0x55U, 0x54U, 0x5FU, 0x4FU, 0x46U, 0x5FU, 0x42U, 0x4FU,
|
||||
0x55U, 0x4EU, 0x44U, 0x53U, 0x00U, 0x28U, 0x79U, 0x3DU, 0x73U, 0x74U,
|
||||
0x61U, 0x74U, 0x65U, 0x5FU, 0x66U, 0x6FU, 0x72U, 0x65U, 0x69U, 0x67U,
|
||||
0x6EU, 0x5FU, 0x73U, 0x65U, 0x74U, 0x28U, 0x31U, 0x2CU, 0x20U, 0x33U,
|
||||
0x32U, 0x2CU, 0x20U, 0x31U, 0x31U, 0x31U, 0x31U, 0x31U, 0x31U, 0x31U,
|
||||
0x2CU, 0x20U, 0x33U, 0x32U, 0x2CU, 0x20U, 0x31U, 0x2CU, 0x20U, 0x33U,
|
||||
0x32U, 0x2CU, 0x20U, 0x31U, 0x2CU, 0x20U, 0x32U, 0x30U, 0x29U, 0x29U,
|
||||
0x20U, 0x3DU, 0x3DU, 0x20U, 0x4FU, 0x55U, 0x54U, 0x5FU, 0x4FU, 0x46U,
|
||||
0x5FU, 0x42U, 0x4FU, 0x55U, 0x4EU, 0x44U, 0x53U, 0x00U, 0x28U, 0x79U,
|
||||
0x3DU, 0x73U, 0x74U, 0x61U, 0x74U, 0x65U, 0x5FU, 0x66U, 0x6FU, 0x72U,
|
||||
0x65U, 0x69U, 0x67U, 0x6EU, 0x5FU, 0x73U, 0x65U, 0x74U, 0x28U, 0x31U,
|
||||
0x2CU, 0x20U, 0x33U, 0x32U, 0x2CU, 0x20U, 0x31U, 0x2CU, 0x20U, 0x31U,
|
||||
0x31U, 0x31U, 0x31U, 0x31U, 0x31U, 0x31U, 0x2CU, 0x20U, 0x31U, 0x2CU,
|
||||
0x20U, 0x33U, 0x32U, 0x2CU, 0x20U, 0x31U, 0x2CU, 0x20U, 0x32U, 0x30U,
|
||||
0x29U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x54U, 0x4FU, 0x4FU, 0x5FU,
|
||||
0x42U, 0x49U, 0x47U, 0x00U, 0x28U, 0x79U, 0x3DU, 0x73U, 0x74U, 0x61U,
|
||||
0x74U, 0x65U, 0x5FU, 0x66U, 0x6FU, 0x72U, 0x65U, 0x69U, 0x67U, 0x6EU,
|
||||
0x5FU, 0x73U, 0x65U, 0x74U, 0x28U, 0x31U, 0x2CU, 0x20U, 0x33U, 0x32U,
|
||||
0x2CU, 0x20U, 0x31U, 0x2CU, 0x20U, 0x33U, 0x32U, 0x2CU, 0x20U, 0x31U,
|
||||
0x31U, 0x31U, 0x31U, 0x31U, 0x31U, 0x31U, 0x2CU, 0x20U, 0x33U, 0x32U,
|
||||
0x2CU, 0x20U, 0x31U, 0x2CU, 0x20U, 0x32U, 0x30U, 0x29U, 0x29U, 0x20U,
|
||||
0x3DU, 0x3DU, 0x20U, 0x4FU, 0x55U, 0x54U, 0x5FU, 0x4FU, 0x46U, 0x5FU,
|
||||
0x42U, 0x4FU, 0x55U, 0x4EU, 0x44U, 0x53U, 0x00U, 0x28U, 0x79U, 0x3DU,
|
||||
0x73U, 0x74U, 0x61U, 0x74U, 0x65U, 0x5FU, 0x66U, 0x6FU, 0x72U, 0x65U,
|
||||
0x69U, 0x67U, 0x6EU, 0x5FU, 0x73U, 0x65U, 0x74U, 0x28U, 0x31U, 0x2CU,
|
||||
0x20U, 0x33U, 0x32U, 0x2CU, 0x20U, 0x31U, 0x2CU, 0x20U, 0x33U, 0x32U,
|
||||
0x2CU, 0x20U, 0x31U, 0x2CU, 0x20U, 0x31U, 0x31U, 0x31U, 0x31U, 0x31U,
|
||||
0x31U, 0x31U, 0x2CU, 0x20U, 0x31U, 0x2CU, 0x20U, 0x32U, 0x30U, 0x29U,
|
||||
0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x49U, 0x4EU, 0x56U, 0x41U, 0x4CU,
|
||||
0x49U, 0x44U, 0x5FU, 0x41U, 0x52U, 0x47U, 0x55U, 0x4DU, 0x45U, 0x4EU,
|
||||
0x54U, 0x00U, 0x28U, 0x79U, 0x3DU, 0x73U, 0x74U, 0x61U, 0x74U, 0x65U,
|
||||
0x5FU, 0x66U, 0x6FU, 0x72U, 0x65U, 0x69U, 0x67U, 0x6EU, 0x5FU, 0x73U,
|
||||
0x65U, 0x74U, 0x28U, 0x31U, 0x2CU, 0x20U, 0x33U, 0x32U, 0x2CU, 0x20U,
|
||||
0x31U, 0x2CU, 0x20U, 0x33U, 0x32U, 0x2CU, 0x20U, 0x31U, 0x2CU, 0x20U,
|
||||
0x33U, 0x32U, 0x2CU, 0x20U, 0x31U, 0x31U, 0x31U, 0x31U, 0x31U, 0x31U,
|
||||
0x31U, 0x2CU, 0x20U, 0x32U, 0x30U, 0x29U, 0x29U, 0x20U, 0x3DU, 0x3DU,
|
||||
0x20U, 0x4FU, 0x55U, 0x54U, 0x5FU, 0x4FU, 0x46U, 0x5FU, 0x42U, 0x4FU,
|
||||
0x55U, 0x4EU, 0x44U, 0x53U, 0x00U, 0x28U, 0x79U, 0x3DU, 0x73U, 0x74U,
|
||||
0x61U, 0x74U, 0x65U, 0x5FU, 0x66U, 0x6FU, 0x72U, 0x65U, 0x69U, 0x67U,
|
||||
0x6EU, 0x5FU, 0x73U, 0x65U, 0x74U, 0x28U, 0x31U, 0x2CU, 0x20U, 0x33U,
|
||||
0x32U, 0x2CU, 0x20U, 0x31U, 0x2CU, 0x20U, 0x33U, 0x32U, 0x2CU, 0x20U,
|
||||
0x31U, 0x2CU, 0x20U, 0x33U, 0x32U, 0x2CU, 0x20U, 0x31U, 0x2CU, 0x20U,
|
||||
0x31U, 0x31U, 0x31U, 0x31U, 0x31U, 0x31U, 0x31U, 0x29U, 0x29U, 0x20U,
|
||||
0x3DU, 0x3DU, 0x20U, 0x49U, 0x4EU, 0x56U, 0x41U, 0x4CU, 0x49U, 0x44U,
|
||||
0x5FU, 0x41U, 0x52U, 0x47U, 0x55U, 0x4DU, 0x45U, 0x4EU, 0x54U, 0x00U,
|
||||
0x6FU, 0x74U, 0x78U, 0x6EU, 0x5FU, 0x69U, 0x64U, 0x28U, 0x53U, 0x42U,
|
||||
0x55U, 0x46U, 0x28U, 0x74U, 0x78U, 0x6EU, 0x29U, 0x2CU, 0x20U, 0x30U,
|
||||
0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x33U, 0x32U, 0x00U, 0x6FU, 0x74U,
|
||||
0x78U, 0x6EU, 0x5FU, 0x66U, 0x69U, 0x65U, 0x6CU, 0x64U, 0x28U, 0x53U,
|
||||
0x42U, 0x55U, 0x46U, 0x28U, 0x67U, 0x72U, 0x61U, 0x6EU, 0x74U, 0x6FU,
|
||||
0x72U, 0x29U, 0x2CU, 0x20U, 0x73U, 0x66U, 0x49U, 0x6EU, 0x76U, 0x6FU,
|
||||
0x69U, 0x63U, 0x65U, 0x49U, 0x44U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U,
|
||||
0x33U, 0x32U, 0x00U, 0x73U, 0x74U, 0x61U, 0x74U, 0x65U, 0x5FU, 0x66U,
|
||||
0x6FU, 0x72U, 0x65U, 0x69U, 0x67U, 0x6EU, 0x5FU, 0x73U, 0x65U, 0x74U,
|
||||
0x28U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U, 0x74U, 0x78U, 0x6EU, 0x29U,
|
||||
0x2CU, 0x20U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U, 0x6FU, 0x6EU, 0x65U,
|
||||
0x29U, 0x2CU, 0x20U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U, 0x7AU, 0x65U,
|
||||
0x72U, 0x6FU, 0x29U, 0x2CU, 0x20U, 0x67U, 0x72U, 0x61U, 0x6EU, 0x74U,
|
||||
0x6FU, 0x72U, 0x20U, 0x2BU, 0x20U, 0x31U, 0x32U, 0x2CU, 0x20U, 0x32U,
|
||||
0x30U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x33U, 0x32U, 0x00U,
|
||||
}},
|
||||
|
||||
{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 rollback (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
extern int64_t otxn_field (uint32_t, uint32_t, uint32_t);
|
||||
extern int64_t hook_account(uint32_t write_ptr, uint32_t write_len);
|
||||
extern int64_t state_foreign_set (
|
||||
uint32_t, uint32_t, uint32_t, uint32_t,
|
||||
uint32_t, uint32_t, uint32_t, uint32_t
|
||||
);
|
||||
#define DOESNT_EXIST (-5)
|
||||
#define ASSERT(x)\
|
||||
if (!(x))\
|
||||
rollback((uint32_t)#x, sizeof(#x), __LINE__);
|
||||
|
||||
#define BUFFER_EQUAL_20(buf1, buf2)\
|
||||
(\
|
||||
*(((uint64_t*)(buf1)) + 0) == *(((uint64_t*)(buf2)) + 0) &&\
|
||||
*(((uint64_t*)(buf1)) + 1) == *(((uint64_t*)(buf2)) + 1) &&\
|
||||
*(((uint32_t*)(buf1)) + 4) == *(((uint32_t*)(buf2)) + 4))
|
||||
#define SBUF(x) (uint32_t)(x), sizeof(x)
|
||||
|
||||
#define sfAccount ((8U << 16U) + 1U)
|
||||
int64_t hook(uint32_t reserved )
|
||||
{
|
||||
_g(1,1);
|
||||
uint8_t otxnacc[20];
|
||||
ASSERT(otxn_field(SBUF(otxnacc), sfAccount) == 20);
|
||||
|
||||
uint8_t hookacc[20];
|
||||
ASSERT(hook_account(SBUF(hookacc)) == 20);
|
||||
|
||||
if (BUFFER_EQUAL_20(otxnacc, hookacc))
|
||||
{
|
||||
// outgoin txn, delete the state
|
||||
uint8_t one[32]; one[31] = 1U;
|
||||
uint8_t zero[32];
|
||||
// we can use state_foreign_set to do the deletion, a concise way to test this functionality too
|
||||
int64_t y = state_foreign_set(0,0, SBUF(one), SBUF(zero), SBUF(hookacc));
|
||||
ASSERT(y == 0 || y == DOESNT_EXIST);
|
||||
}
|
||||
|
||||
|
||||
return accept(0,0,0);
|
||||
}
|
||||
)[test.hook]",
|
||||
{
|
||||
0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x2CU,
|
||||
0x06U, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, 0x03U, 0x7FU,
|
||||
0x7FU, 0x7FU, 0x01U, 0x7EU, 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7EU, 0x01U,
|
||||
0x7EU, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7EU, 0x60U, 0x08U, 0x7FU,
|
||||
0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x01U, 0x7EU, 0x60U,
|
||||
0x01U, 0x7FU, 0x01U, 0x7EU, 0x02U, 0x62U, 0x06U, 0x03U, 0x65U, 0x6EU,
|
||||
0x76U, 0x02U, 0x5FU, 0x67U, 0x00U, 0x00U, 0x03U, 0x65U, 0x6EU, 0x76U,
|
||||
0x0AU, 0x6FU, 0x74U, 0x78U, 0x6EU, 0x5FU, 0x66U, 0x69U, 0x65U, 0x6CU,
|
||||
0x64U, 0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x08U, 0x72U, 0x6FU,
|
||||
0x6CU, 0x6CU, 0x62U, 0x61U, 0x63U, 0x6BU, 0x00U, 0x02U, 0x03U, 0x65U,
|
||||
0x6EU, 0x76U, 0x0CU, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x5FU, 0x61U, 0x63U,
|
||||
0x63U, 0x6FU, 0x75U, 0x6EU, 0x74U, 0x00U, 0x03U, 0x03U, 0x65U, 0x6EU,
|
||||
0x76U, 0x11U, 0x73U, 0x74U, 0x61U, 0x74U, 0x65U, 0x5FU, 0x66U, 0x6FU,
|
||||
0x72U, 0x65U, 0x69U, 0x67U, 0x6EU, 0x5FU, 0x73U, 0x65U, 0x74U, 0x00U,
|
||||
0x04U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x06U, 0x61U, 0x63U, 0x63U, 0x65U,
|
||||
0x70U, 0x74U, 0x00U, 0x02U, 0x03U, 0x02U, 0x01U, 0x05U, 0x05U, 0x03U,
|
||||
0x01U, 0x00U, 0x02U, 0x06U, 0x21U, 0x05U, 0x7FU, 0x01U, 0x41U, 0xF0U,
|
||||
0x88U, 0x04U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0xE9U, 0x08U, 0x0BU, 0x7FU,
|
||||
0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0xF0U, 0x88U,
|
||||
0x04U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x07U, 0x08U,
|
||||
0x01U, 0x04U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x06U, 0x0AU, 0x8DU,
|
||||
0x82U, 0x00U, 0x01U, 0x89U, 0x82U, 0x00U, 0x02U, 0x01U, 0x7FU, 0x01U,
|
||||
0x7EU, 0x23U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x41U, 0x80U, 0x01U,
|
||||
0x6BU, 0x22U, 0x01U, 0x24U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x41U,
|
||||
0x01U, 0x41U, 0x01U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU,
|
||||
0x02U, 0x40U, 0x20U, 0x01U, 0x41U, 0xE0U, 0x00U, 0x6AU, 0x41U, 0x14U,
|
||||
0x41U, 0x81U, 0x80U, 0x20U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x42U, 0x14U, 0x51U, 0x0DU, 0x00U, 0x41U, 0x80U, 0x88U, 0x80U, 0x80U,
|
||||
0x00U, 0x41U, 0x2BU, 0x42U, 0x1EU, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x20U, 0x01U, 0x41U, 0xC0U, 0x00U,
|
||||
0x6AU, 0x41U, 0x14U, 0x10U, 0x83U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U,
|
||||
0x14U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xABU, 0x88U, 0x80U, 0x80U, 0x00U,
|
||||
0x41U, 0x22U, 0x42U, 0x21U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x1AU, 0x0BU, 0x02U, 0x40U, 0x20U, 0x01U, 0x29U, 0x03U, 0x60U, 0x20U,
|
||||
0x01U, 0x29U, 0x03U, 0x40U, 0x52U, 0x0DU, 0x00U, 0x20U, 0x01U, 0x29U,
|
||||
0x03U, 0x68U, 0x20U, 0x01U, 0x29U, 0x03U, 0x48U, 0x52U, 0x0DU, 0x00U,
|
||||
0x20U, 0x01U, 0x28U, 0x02U, 0x70U, 0x20U, 0x01U, 0x28U, 0x02U, 0x50U,
|
||||
0x47U, 0x0DU, 0x00U, 0x20U, 0x01U, 0x41U, 0x01U, 0x3AU, 0x00U, 0x3FU,
|
||||
0x02U, 0x40U, 0x41U, 0x00U, 0x41U, 0x00U, 0x20U, 0x01U, 0x41U, 0x20U,
|
||||
0x6AU, 0x41U, 0x20U, 0x20U, 0x01U, 0x41U, 0x20U, 0x20U, 0x01U, 0x41U,
|
||||
0xC0U, 0x00U, 0x6AU, 0x41U, 0x14U, 0x10U, 0x84U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x42U, 0x05U, 0x7CU, 0x22U, 0x02U, 0x42U, 0x05U, 0x56U, 0x0DU,
|
||||
0x00U, 0x20U, 0x02U, 0xA7U, 0x0EU, 0x06U, 0x01U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x01U, 0x01U, 0x0BU, 0x41U, 0xCDU, 0x88U, 0x80U, 0x80U, 0x00U,
|
||||
0x41U, 0x1CU, 0x42U, 0x2AU, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x1AU, 0x0BU, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x00U, 0x10U, 0x85U,
|
||||
0x80U, 0x80U, 0x80U, 0x00U, 0x21U, 0x02U, 0x20U, 0x01U, 0x41U, 0x80U,
|
||||
0x01U, 0x6AU, 0x24U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x20U, 0x02U,
|
||||
0x0BU, 0x0BU, 0x70U, 0x01U, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x69U,
|
||||
0x6FU, 0x74U, 0x78U, 0x6EU, 0x5FU, 0x66U, 0x69U, 0x65U, 0x6CU, 0x64U,
|
||||
0x28U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U, 0x6FU, 0x74U, 0x78U, 0x6EU,
|
||||
0x61U, 0x63U, 0x63U, 0x29U, 0x2CU, 0x20U, 0x73U, 0x66U, 0x41U, 0x63U,
|
||||
0x63U, 0x6FU, 0x75U, 0x6EU, 0x74U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U,
|
||||
0x32U, 0x30U, 0x00U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x5FU, 0x61U, 0x63U,
|
||||
0x63U, 0x6FU, 0x75U, 0x6EU, 0x74U, 0x28U, 0x53U, 0x42U, 0x55U, 0x46U,
|
||||
0x28U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x61U, 0x63U, 0x63U, 0x29U, 0x29U,
|
||||
0x20U, 0x3DU, 0x3DU, 0x20U, 0x32U, 0x30U, 0x00U, 0x79U, 0x20U, 0x3DU,
|
||||
0x3DU, 0x20U, 0x30U, 0x20U, 0x7CU, 0x7CU, 0x20U, 0x79U, 0x20U, 0x3DU,
|
||||
0x3DU, 0x20U, 0x44U, 0x4FU, 0x45U, 0x53U, 0x4EU, 0x54U, 0x5FU, 0x45U,
|
||||
0x58U, 0x49U, 0x53U, 0x54U, 0x00U,
|
||||
}},
|
||||
|
||||
{R"[test.hook](
|
||||
#include <stdint.h>
|
||||
extern int32_t _g (uint32_t id, uint32_t maxiter);
|
||||
extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
extern int64_t rollback (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
extern int64_t hook_again (void);
|
||||
extern int64_t otxn_id (uint32_t, uint32_t, uint32_t);
|
||||
extern int64_t otxn_field (uint32_t, uint32_t, uint32_t);
|
||||
extern int64_t otxn_param (uint32_t, uint32_t, uint32_t, uint32_t);
|
||||
extern int64_t state_foreign_set (
|
||||
uint32_t, uint32_t, uint32_t, uint32_t,
|
||||
uint32_t, uint32_t, uint32_t, uint32_t
|
||||
);
|
||||
#define sfInvoiceID ((5U << 16U) + 17U)
|
||||
#define SBUF(x) (uint32_t)(x), sizeof(x)
|
||||
#define ASSERT(x)\
|
||||
if (!(x))\
|
||||
rollback((uint32_t)#x, sizeof(#x), __LINE__);
|
||||
|
||||
uint8_t ns[32];
|
||||
uint8_t write_key[32] = { [31] = 2U };
|
||||
uint8_t delete_key[32] = { [31] = 4U };
|
||||
|
||||
int64_t hook(uint32_t r)
|
||||
{
|
||||
_g(1,1);
|
||||
|
||||
// strong execution: write nothing, ask to be executed again weakly
|
||||
if (r == 0)
|
||||
{
|
||||
ASSERT(hook_again() == 1);
|
||||
return accept(0,0,0);
|
||||
}
|
||||
|
||||
// the grantor is the account in the low 20 bytes of the InvoiceID
|
||||
uint8_t grantor[32];
|
||||
ASSERT(otxn_field(SBUF(grantor), sfInvoiceID) == 32);
|
||||
|
||||
// with otxn parameter D, delete a key the grantor does not have
|
||||
uint8_t d[1];
|
||||
if (otxn_param(SBUF(d), (uint32_t)"D", 1) == 1)
|
||||
{
|
||||
ASSERT(state_foreign_set(0, 0, SBUF(delete_key), SBUF(ns), (uint32_t)(grantor + 12), 20) == 0);
|
||||
return accept(0,0,0);
|
||||
}
|
||||
|
||||
// otherwise write the otxn id under key 2
|
||||
uint8_t txn[32];
|
||||
ASSERT(otxn_id(SBUF(txn), 0) == 32);
|
||||
ASSERT(state_foreign_set(SBUF(txn), SBUF(write_key), SBUF(ns), (uint32_t)(grantor + 12), 20) == 32);
|
||||
|
||||
return accept(0,0,0);
|
||||
}
|
||||
)[test.hook]",
|
||||
{
|
||||
0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x32U,
|
||||
0x07U, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, 0x00U, 0x01U,
|
||||
0x7EU, 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7EU, 0x01U, 0x7EU, 0x60U, 0x03U,
|
||||
0x7FU, 0x7FU, 0x7FU, 0x01U, 0x7EU, 0x60U, 0x04U, 0x7FU, 0x7FU, 0x7FU,
|
||||
0x7FU, 0x01U, 0x7EU, 0x60U, 0x08U, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU,
|
||||
0x7FU, 0x7FU, 0x7FU, 0x01U, 0x7EU, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU,
|
||||
0x02U, 0x7FU, 0x08U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x02U, 0x5FU, 0x67U,
|
||||
0x00U, 0x00U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x0AU, 0x68U, 0x6FU, 0x6FU,
|
||||
0x6BU, 0x5FU, 0x61U, 0x67U, 0x61U, 0x69U, 0x6EU, 0x00U, 0x01U, 0x03U,
|
||||
0x65U, 0x6EU, 0x76U, 0x08U, 0x72U, 0x6FU, 0x6CU, 0x6CU, 0x62U, 0x61U,
|
||||
0x63U, 0x6BU, 0x00U, 0x02U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x06U, 0x61U,
|
||||
0x63U, 0x63U, 0x65U, 0x70U, 0x74U, 0x00U, 0x02U, 0x03U, 0x65U, 0x6EU,
|
||||
0x76U, 0x0AU, 0x6FU, 0x74U, 0x78U, 0x6EU, 0x5FU, 0x66U, 0x69U, 0x65U,
|
||||
0x6CU, 0x64U, 0x00U, 0x03U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x0AU, 0x6FU,
|
||||
0x74U, 0x78U, 0x6EU, 0x5FU, 0x70U, 0x61U, 0x72U, 0x61U, 0x6DU, 0x00U,
|
||||
0x04U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x11U, 0x73U, 0x74U, 0x61U, 0x74U,
|
||||
0x65U, 0x5FU, 0x66U, 0x6FU, 0x72U, 0x65U, 0x69U, 0x67U, 0x6EU, 0x5FU,
|
||||
0x73U, 0x65U, 0x74U, 0x00U, 0x05U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x07U,
|
||||
0x6FU, 0x74U, 0x78U, 0x6EU, 0x5FU, 0x69U, 0x64U, 0x00U, 0x03U, 0x03U,
|
||||
0x02U, 0x01U, 0x06U, 0x05U, 0x03U, 0x01U, 0x00U, 0x02U, 0x06U, 0x51U,
|
||||
0x0DU, 0x7FU, 0x01U, 0x41U, 0xF0U, 0x8AU, 0x04U, 0x0BU, 0x7FU, 0x00U,
|
||||
0x41U, 0xB0U, 0x0AU, 0x0BU, 0x7FU, 0x00U, 0x41U, 0xD0U, 0x0AU, 0x0BU,
|
||||
0x7FU, 0x00U, 0x41U, 0x90U, 0x0AU, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U,
|
||||
0x08U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0xF0U, 0x0AU, 0x0BU, 0x7FU, 0x00U,
|
||||
0x41U, 0xF0U, 0x0AU, 0x0BU, 0x7FU, 0x00U, 0x41U, 0xF0U, 0x8AU, 0x04U,
|
||||
0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU, 0x00U, 0x41U,
|
||||
0xF0U, 0x8AU, 0x04U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x80U, 0x08U,
|
||||
0x0BU, 0x7FU, 0x00U, 0x41U, 0x00U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x01U,
|
||||
0x0BU, 0x07U, 0x08U, 0x01U, 0x04U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U,
|
||||
0x08U, 0x0AU, 0xF2U, 0x82U, 0x00U, 0x01U, 0xEEU, 0x82U, 0x00U, 0x02U,
|
||||
0x01U, 0x7FU, 0x01U, 0x7EU, 0x23U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x41U, 0xD0U, 0x00U, 0x6BU, 0x22U, 0x01U, 0x24U, 0x80U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, 0x80U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x1AU, 0x02U, 0x40U, 0x02U, 0x40U, 0x20U, 0x00U, 0x0DU,
|
||||
0x00U, 0x02U, 0x40U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U,
|
||||
0x01U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xA7U, 0x89U, 0x80U, 0x80U, 0x00U,
|
||||
0x41U, 0x12U, 0x42U, 0x1FU, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x1AU, 0x0BU, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x00U, 0x10U, 0x83U,
|
||||
0x80U, 0x80U, 0x80U, 0x00U, 0x21U, 0x02U, 0x0CU, 0x01U, 0x0BU, 0x02U,
|
||||
0x40U, 0x20U, 0x01U, 0x41U, 0x30U, 0x6AU, 0x41U, 0x20U, 0x41U, 0x91U,
|
||||
0x80U, 0x14U, 0x10U, 0x84U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U, 0x20U,
|
||||
0x51U, 0x0DU, 0x00U, 0x41U, 0x82U, 0x88U, 0x80U, 0x80U, 0x00U, 0x41U,
|
||||
0x2DU, 0x42U, 0x25U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU,
|
||||
0x0BU, 0x02U, 0x40U, 0x20U, 0x01U, 0x41U, 0x2FU, 0x6AU, 0x41U, 0x01U,
|
||||
0x41U, 0x80U, 0x88U, 0x80U, 0x80U, 0x00U, 0x41U, 0x01U, 0x10U, 0x85U,
|
||||
0x80U, 0x80U, 0x80U, 0x00U, 0x42U, 0x01U, 0x52U, 0x0DU, 0x00U, 0x02U,
|
||||
0x40U, 0x41U, 0x00U, 0x41U, 0x00U, 0x41U, 0xB0U, 0x8AU, 0x80U, 0x80U,
|
||||
0x00U, 0x41U, 0x20U, 0x41U, 0xD0U, 0x8AU, 0x80U, 0x80U, 0x00U, 0x41U,
|
||||
0x20U, 0x20U, 0x01U, 0x41U, 0x30U, 0x6AU, 0x41U, 0x0CU, 0x72U, 0x41U,
|
||||
0x14U, 0x10U, 0x86U, 0x80U, 0x80U, 0x80U, 0x00U, 0x50U, 0x0DU, 0x00U,
|
||||
0x41U, 0xB9U, 0x89U, 0x80U, 0x80U, 0x00U, 0x41U, 0xD7U, 0x00U, 0x42U,
|
||||
0x2BU, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x41U,
|
||||
0x00U, 0x41U, 0x00U, 0x42U, 0x00U, 0x10U, 0x83U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x21U, 0x02U, 0x0CU, 0x01U, 0x0BU, 0x02U, 0x40U, 0x20U, 0x01U,
|
||||
0x41U, 0x20U, 0x41U, 0x00U, 0x10U, 0x87U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x42U, 0x20U, 0x51U, 0x0DU, 0x00U, 0x41U, 0x8BU, 0x89U, 0x80U, 0x80U,
|
||||
0x00U, 0x41U, 0x1CU, 0x42U, 0x31U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x20U, 0x01U, 0x41U, 0x20U, 0x41U,
|
||||
0x90U, 0x8AU, 0x80U, 0x80U, 0x00U, 0x41U, 0x20U, 0x41U, 0xD0U, 0x8AU,
|
||||
0x80U, 0x80U, 0x00U, 0x41U, 0x20U, 0x20U, 0x01U, 0x41U, 0x30U, 0x6AU,
|
||||
0x41U, 0x0CU, 0x72U, 0x41U, 0x14U, 0x10U, 0x86U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x42U, 0x20U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xAFU, 0x88U, 0x80U,
|
||||
0x80U, 0x00U, 0x41U, 0xDCU, 0x00U, 0x42U, 0x32U, 0x10U, 0x82U, 0x80U,
|
||||
0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U,
|
||||
0x00U, 0x10U, 0x83U, 0x80U, 0x80U, 0x80U, 0x00U, 0x21U, 0x02U, 0x0BU,
|
||||
0x20U, 0x01U, 0x41U, 0xD0U, 0x00U, 0x6AU, 0x24U, 0x80U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x20U, 0x02U, 0x0BU, 0x0BU, 0xDEU, 0x02U, 0x02U, 0x00U,
|
||||
0x41U, 0x80U, 0x08U, 0x0BU, 0x90U, 0x02U, 0x44U, 0x00U, 0x6FU, 0x74U,
|
||||
0x78U, 0x6EU, 0x5FU, 0x66U, 0x69U, 0x65U, 0x6CU, 0x64U, 0x28U, 0x53U,
|
||||
0x42U, 0x55U, 0x46U, 0x28U, 0x67U, 0x72U, 0x61U, 0x6EU, 0x74U, 0x6FU,
|
||||
0x72U, 0x29U, 0x2CU, 0x20U, 0x73U, 0x66U, 0x49U, 0x6EU, 0x76U, 0x6FU,
|
||||
0x69U, 0x63U, 0x65U, 0x49U, 0x44U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U,
|
||||
0x33U, 0x32U, 0x00U, 0x73U, 0x74U, 0x61U, 0x74U, 0x65U, 0x5FU, 0x66U,
|
||||
0x6FU, 0x72U, 0x65U, 0x69U, 0x67U, 0x6EU, 0x5FU, 0x73U, 0x65U, 0x74U,
|
||||
0x28U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U, 0x74U, 0x78U, 0x6EU, 0x29U,
|
||||
0x2CU, 0x20U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U, 0x77U, 0x72U, 0x69U,
|
||||
0x74U, 0x65U, 0x5FU, 0x6BU, 0x65U, 0x79U, 0x29U, 0x2CU, 0x20U, 0x53U,
|
||||
0x42U, 0x55U, 0x46U, 0x28U, 0x6EU, 0x73U, 0x29U, 0x2CU, 0x20U, 0x28U,
|
||||
0x75U, 0x69U, 0x6EU, 0x74U, 0x33U, 0x32U, 0x5FU, 0x74U, 0x29U, 0x28U,
|
||||
0x67U, 0x72U, 0x61U, 0x6EU, 0x74U, 0x6FU, 0x72U, 0x20U, 0x2BU, 0x20U,
|
||||
0x31U, 0x32U, 0x29U, 0x2CU, 0x20U, 0x32U, 0x30U, 0x29U, 0x20U, 0x3DU,
|
||||
0x3DU, 0x20U, 0x33U, 0x32U, 0x00U, 0x6FU, 0x74U, 0x78U, 0x6EU, 0x5FU,
|
||||
0x69U, 0x64U, 0x28U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U, 0x74U, 0x78U,
|
||||
0x6EU, 0x29U, 0x2CU, 0x20U, 0x30U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U,
|
||||
0x33U, 0x32U, 0x00U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x5FU, 0x61U, 0x67U,
|
||||
0x61U, 0x69U, 0x6EU, 0x28U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x31U,
|
||||
0x00U, 0x73U, 0x74U, 0x61U, 0x74U, 0x65U, 0x5FU, 0x66U, 0x6FU, 0x72U,
|
||||
0x65U, 0x69U, 0x67U, 0x6EU, 0x5FU, 0x73U, 0x65U, 0x74U, 0x28U, 0x30U,
|
||||
0x2CU, 0x20U, 0x30U, 0x2CU, 0x20U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U,
|
||||
0x64U, 0x65U, 0x6CU, 0x65U, 0x74U, 0x65U, 0x5FU, 0x6BU, 0x65U, 0x79U,
|
||||
0x29U, 0x2CU, 0x20U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U, 0x6EU, 0x73U,
|
||||
0x29U, 0x2CU, 0x20U, 0x28U, 0x75U, 0x69U, 0x6EU, 0x74U, 0x33U, 0x32U,
|
||||
0x5FU, 0x74U, 0x29U, 0x28U, 0x67U, 0x72U, 0x61U, 0x6EU, 0x74U, 0x6FU,
|
||||
0x72U, 0x20U, 0x2BU, 0x20U, 0x31U, 0x32U, 0x29U, 0x2CU, 0x20U, 0x32U,
|
||||
0x30U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x30U, 0x00U, 0x00U, 0x41U,
|
||||
0x90U, 0x0AU, 0x0BU, 0x40U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x04U,
|
||||
}},
|
||||
|
||||
{R"[test.hook](
|
||||
#include <stdint.h>
|
||||
extern int32_t _g (uint32_t id, uint32_t maxiter);
|
||||
extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
extern int64_t rollback (uint32_t read_ptr, uint32_t read_len, int64_t error_code);
|
||||
extern int64_t emit (uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
|
||||
extern int64_t hook_account (uint32_t write_ptr, uint32_t write_len);
|
||||
extern int64_t hook_param (uint32_t, uint32_t, uint32_t, uint32_t);
|
||||
extern int64_t etxn_reserve (uint32_t);
|
||||
extern int64_t etxn_fee_base (uint32_t read_ptr, uint32_t read_len);
|
||||
extern int64_t etxn_details (uint32_t write_ptr, uint32_t write_len);
|
||||
extern int64_t ledger_seq (void);
|
||||
extern int64_t otxn_id (uint32_t, uint32_t, uint32_t);
|
||||
extern int64_t state_foreign_set (
|
||||
uint32_t, uint32_t, uint32_t, uint32_t,
|
||||
uint32_t, uint32_t, uint32_t, uint32_t
|
||||
);
|
||||
#define SBUF(x) (uint32_t)(x), sizeof(x)
|
||||
#define ASSERT(x)\
|
||||
if (!(x))\
|
||||
rollback((uint32_t)#x, sizeof(#x), __LINE__);
|
||||
|
||||
uint8_t ns[32];
|
||||
uint8_t write_key[32] = { [31] = 3U };
|
||||
|
||||
// an Invoke from the hook account, emitted so its callback runs
|
||||
uint8_t txn[229] =
|
||||
{
|
||||
/* size, upto, field name */
|
||||
/* 3, 0, tt = Invoke */ 0x12U, 0x00U, 0x63U,
|
||||
/* 5, 3, flags */ 0x22U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
/* 5, 8, sequence */ 0x24U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
/* 6, 13, firstledgersequence */ 0x20U, 0x1AU, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
/* 6, 19, lastledgersequence */ 0x20U, 0x1BU, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
/* 9, 25, fee */ 0x68U, 0x40U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
/* 35, 34, signingpubkey */ 0x73U, 0x21U, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
/* 22, 69, account */ 0x81U, 0x14U, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
/* 138, 91, emit details */
|
||||
/* 0, 229, */
|
||||
};
|
||||
#define FLS_OUT (txn + 15U)
|
||||
#define LLS_OUT (txn + 21U)
|
||||
#define FEE_OUT (txn + 26U)
|
||||
#define ACCOUNT_OUT (txn + 71U)
|
||||
#define EMIT_OUT (txn + 91U)
|
||||
#define SET_UINT32(ptr, value)\
|
||||
{\
|
||||
uint32_t v = (value);\
|
||||
(ptr)[0] = v >> 24U; (ptr)[1] = v >> 16U; (ptr)[2] = v >> 8U; (ptr)[3] = v;\
|
||||
}
|
||||
#define SET_NATIVE_AMOUNT(ptr, amount)\
|
||||
{\
|
||||
uint64_t a = (amount);\
|
||||
(ptr)[0] = 0x40U + ((a >> 56U) & 0x3FU);\
|
||||
(ptr)[1] = a >> 48U; (ptr)[2] = a >> 40U; (ptr)[3] = a >> 32U;\
|
||||
(ptr)[4] = a >> 24U; (ptr)[5] = a >> 16U; (ptr)[6] = a >> 8U; (ptr)[7] = a;\
|
||||
}
|
||||
|
||||
int64_t cbak(uint32_t r)
|
||||
{
|
||||
_g(1,1);
|
||||
|
||||
// the grantor is the hook parameter G
|
||||
uint8_t grantor[20];
|
||||
ASSERT(hook_param(SBUF(grantor), (uint32_t)"G", 1) == 20);
|
||||
|
||||
// in a callback the otxn is the emitted txn: write its id under key 3
|
||||
uint8_t id[32];
|
||||
ASSERT(otxn_id(SBUF(id), 0) == 32);
|
||||
ASSERT(state_foreign_set(SBUF(id), SBUF(write_key), SBUF(ns), SBUF(grantor)) == 32);
|
||||
|
||||
return accept(0,0,0);
|
||||
}
|
||||
|
||||
int64_t hook(uint32_t r)
|
||||
{
|
||||
_g(1,1);
|
||||
|
||||
ASSERT(etxn_reserve(1) == 1);
|
||||
uint32_t fls = (uint32_t)ledger_seq() + 1;
|
||||
SET_UINT32(FLS_OUT, fls);
|
||||
SET_UINT32(LLS_OUT, fls + 4);
|
||||
ASSERT(hook_account(ACCOUNT_OUT, 20) == 20);
|
||||
ASSERT(etxn_details(EMIT_OUT, 138U) == 138);
|
||||
int64_t fee = etxn_fee_base(SBUF(txn));
|
||||
ASSERT(fee > 0);
|
||||
SET_NATIVE_AMOUNT(FEE_OUT, fee);
|
||||
|
||||
uint8_t emithash[32];
|
||||
ASSERT(emit(SBUF(emithash), SBUF(txn)) == 32);
|
||||
|
||||
return accept(0,0,0);
|
||||
}
|
||||
)[test.hook]",
|
||||
{
|
||||
0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, 0x38U,
|
||||
0x08U, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, 0x04U, 0x7FU,
|
||||
0x7FU, 0x7FU, 0x7FU, 0x01U, 0x7EU, 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7EU,
|
||||
0x01U, 0x7EU, 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7FU, 0x01U, 0x7EU, 0x60U,
|
||||
0x08U, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x01U,
|
||||
0x7EU, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU, 0x60U, 0x00U, 0x01U, 0x7EU,
|
||||
0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7EU, 0x02U, 0xC6U, 0x01U, 0x0CU,
|
||||
0x03U, 0x65U, 0x6EU, 0x76U, 0x02U, 0x5FU, 0x67U, 0x00U, 0x00U, 0x03U,
|
||||
0x65U, 0x6EU, 0x76U, 0x0AU, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x5FU, 0x70U,
|
||||
0x61U, 0x72U, 0x61U, 0x6DU, 0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U,
|
||||
0x08U, 0x72U, 0x6FU, 0x6CU, 0x6CU, 0x62U, 0x61U, 0x63U, 0x6BU, 0x00U,
|
||||
0x02U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x07U, 0x6FU, 0x74U, 0x78U, 0x6EU,
|
||||
0x5FU, 0x69U, 0x64U, 0x00U, 0x03U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x11U,
|
||||
0x73U, 0x74U, 0x61U, 0x74U, 0x65U, 0x5FU, 0x66U, 0x6FU, 0x72U, 0x65U,
|
||||
0x69U, 0x67U, 0x6EU, 0x5FU, 0x73U, 0x65U, 0x74U, 0x00U, 0x04U, 0x03U,
|
||||
0x65U, 0x6EU, 0x76U, 0x06U, 0x61U, 0x63U, 0x63U, 0x65U, 0x70U, 0x74U,
|
||||
0x00U, 0x02U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x0CU, 0x65U, 0x74U, 0x78U,
|
||||
0x6EU, 0x5FU, 0x72U, 0x65U, 0x73U, 0x65U, 0x72U, 0x76U, 0x65U, 0x00U,
|
||||
0x05U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x0AU, 0x6CU, 0x65U, 0x64U, 0x67U,
|
||||
0x65U, 0x72U, 0x5FU, 0x73U, 0x65U, 0x71U, 0x00U, 0x06U, 0x03U, 0x65U,
|
||||
0x6EU, 0x76U, 0x0CU, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x5FU, 0x61U, 0x63U,
|
||||
0x63U, 0x6FU, 0x75U, 0x6EU, 0x74U, 0x00U, 0x07U, 0x03U, 0x65U, 0x6EU,
|
||||
0x76U, 0x0CU, 0x65U, 0x74U, 0x78U, 0x6EU, 0x5FU, 0x64U, 0x65U, 0x74U,
|
||||
0x61U, 0x69U, 0x6CU, 0x73U, 0x00U, 0x07U, 0x03U, 0x65U, 0x6EU, 0x76U,
|
||||
0x0DU, 0x65U, 0x74U, 0x78U, 0x6EU, 0x5FU, 0x66U, 0x65U, 0x65U, 0x5FU,
|
||||
0x62U, 0x61U, 0x73U, 0x65U, 0x00U, 0x07U, 0x03U, 0x65U, 0x6EU, 0x76U,
|
||||
0x04U, 0x65U, 0x6DU, 0x69U, 0x74U, 0x00U, 0x01U, 0x03U, 0x03U, 0x02U,
|
||||
0x05U, 0x05U, 0x05U, 0x03U, 0x01U, 0x00U, 0x02U, 0x06U, 0x51U, 0x0DU,
|
||||
0x7FU, 0x01U, 0x41U, 0xE0U, 0x8CU, 0x04U, 0x0BU, 0x7FU, 0x00U, 0x41U,
|
||||
0xB0U, 0x0AU, 0x0BU, 0x7FU, 0x00U, 0x41U, 0xC0U, 0x0CU, 0x0BU, 0x7FU,
|
||||
0x00U, 0x41U, 0xD0U, 0x0AU, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U,
|
||||
0x0BU, 0x7FU, 0x00U, 0x41U, 0xE0U, 0x0CU, 0x0BU, 0x7FU, 0x00U, 0x41U,
|
||||
0xE0U, 0x0CU, 0x0BU, 0x7FU, 0x00U, 0x41U, 0xE0U, 0x8CU, 0x04U, 0x0BU,
|
||||
0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0xE0U,
|
||||
0x8CU, 0x04U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x80U, 0x08U, 0x0BU,
|
||||
0x7FU, 0x00U, 0x41U, 0x00U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x01U, 0x0BU,
|
||||
0x07U, 0x0FU, 0x02U, 0x04U, 0x63U, 0x62U, 0x61U, 0x6BU, 0x00U, 0x0CU,
|
||||
0x04U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x0DU, 0x0AU, 0xD0U, 0x85U,
|
||||
0x00U, 0x02U, 0xD0U, 0x81U, 0x00U, 0x02U, 0x01U, 0x7FU, 0x01U, 0x7EU,
|
||||
0x23U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x41U, 0xC0U, 0x00U, 0x6BU,
|
||||
0x22U, 0x01U, 0x24U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x41U, 0x01U,
|
||||
0x41U, 0x01U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x02U,
|
||||
0x40U, 0x20U, 0x01U, 0x41U, 0x20U, 0x6AU, 0x41U, 0x14U, 0x41U, 0x80U,
|
||||
0x88U, 0x80U, 0x80U, 0x00U, 0x41U, 0x01U, 0x10U, 0x81U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x42U, 0x14U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xC8U, 0x89U,
|
||||
0x80U, 0x80U, 0x00U, 0x41U, 0x32U, 0x42U, 0xC1U, 0x00U, 0x10U, 0x82U,
|
||||
0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x20U, 0x01U,
|
||||
0x41U, 0x20U, 0x41U, 0x00U, 0x10U, 0x83U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x42U, 0x20U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xA6U, 0x88U, 0x80U, 0x80U,
|
||||
0x00U, 0x41U, 0x1BU, 0x42U, 0xC5U, 0x00U, 0x10U, 0x82U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x20U, 0x01U, 0x41U, 0x20U,
|
||||
0x41U, 0xB0U, 0x8AU, 0x80U, 0x80U, 0x00U, 0x41U, 0x20U, 0x41U, 0xC0U,
|
||||
0x8CU, 0x80U, 0x80U, 0x00U, 0x41U, 0x20U, 0x20U, 0x01U, 0x41U, 0x20U,
|
||||
0x6AU, 0x41U, 0x14U, 0x10U, 0x84U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U,
|
||||
0x20U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xC1U, 0x88U, 0x80U, 0x80U, 0x00U,
|
||||
0x41U, 0xCCU, 0x00U, 0x42U, 0xC6U, 0x00U, 0x10U, 0x82U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x1AU, 0x0BU, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x00U,
|
||||
0x10U, 0x85U, 0x80U, 0x80U, 0x80U, 0x00U, 0x21U, 0x02U, 0x20U, 0x01U,
|
||||
0x41U, 0xC0U, 0x00U, 0x6AU, 0x24U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U,
|
||||
0x20U, 0x02U, 0x0BU, 0xF9U, 0x83U, 0x00U, 0x02U, 0x03U, 0x7FU, 0x01U,
|
||||
0x7EU, 0x23U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x41U, 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, 0x86U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U,
|
||||
0x01U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xB3U, 0x89U, 0x80U, 0x80U, 0x00U,
|
||||
0x41U, 0x15U, 0x42U, 0xCFU, 0x00U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0x1AU, 0x0BU, 0x41U, 0x00U, 0x10U, 0x87U, 0x80U, 0x80U, 0x80U,
|
||||
0x00U, 0xA7U, 0x22U, 0x02U, 0x41U, 0x05U, 0x6AU, 0x22U, 0x03U, 0x3AU,
|
||||
0x00U, 0xE8U, 0x8AU, 0x80U, 0x80U, 0x00U, 0x41U, 0x00U, 0x20U, 0x02U,
|
||||
0x41U, 0x01U, 0x6AU, 0x22U, 0x02U, 0x3AU, 0x00U, 0xE2U, 0x8AU, 0x80U,
|
||||
0x80U, 0x00U, 0x41U, 0x00U, 0x20U, 0x03U, 0x41U, 0x08U, 0x76U, 0x3AU,
|
||||
0x00U, 0xE7U, 0x8AU, 0x80U, 0x80U, 0x00U, 0x41U, 0x00U, 0x20U, 0x03U,
|
||||
0x41U, 0x10U, 0x76U, 0x3AU, 0x00U, 0xE6U, 0x8AU, 0x80U, 0x80U, 0x00U,
|
||||
0x41U, 0x00U, 0x20U, 0x03U, 0x41U, 0x18U, 0x76U, 0x3AU, 0x00U, 0xE5U,
|
||||
0x8AU, 0x80U, 0x80U, 0x00U, 0x41U, 0x00U, 0x20U, 0x02U, 0x41U, 0x08U,
|
||||
0x76U, 0x3AU, 0x00U, 0xE1U, 0x8AU, 0x80U, 0x80U, 0x00U, 0x41U, 0x00U,
|
||||
0x20U, 0x02U, 0x41U, 0x10U, 0x76U, 0x3AU, 0x00U, 0xE0U, 0x8AU, 0x80U,
|
||||
0x80U, 0x00U, 0x41U, 0x00U, 0x20U, 0x02U, 0x41U, 0x18U, 0x76U, 0x3AU,
|
||||
0x00U, 0xDFU, 0x8AU, 0x80U, 0x80U, 0x00U, 0x02U, 0x40U, 0x41U, 0x97U,
|
||||
0x8BU, 0x80U, 0x80U, 0x00U, 0x41U, 0x14U, 0x10U, 0x88U, 0x80U, 0x80U,
|
||||
0x80U, 0x00U, 0x42U, 0x14U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xFAU, 0x89U,
|
||||
0x80U, 0x80U, 0x00U, 0x41U, 0x24U, 0x42U, 0xD3U, 0x00U, 0x10U, 0x82U,
|
||||
0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x41U, 0xABU,
|
||||
0x8BU, 0x80U, 0x80U, 0x00U, 0x41U, 0x8AU, 0x01U, 0x10U, 0x89U, 0x80U,
|
||||
0x80U, 0x80U, 0x00U, 0x42U, 0x8AU, 0x01U, 0x51U, 0x0DU, 0x00U, 0x41U,
|
||||
0x82U, 0x88U, 0x80U, 0x80U, 0x00U, 0x41U, 0x24U, 0x42U, 0xD4U, 0x00U,
|
||||
0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U,
|
||||
0x41U, 0xD0U, 0x8AU, 0x80U, 0x80U, 0x00U, 0x41U, 0xE5U, 0x01U, 0x10U,
|
||||
0x8AU, 0x80U, 0x80U, 0x80U, 0x00U, 0x22U, 0x04U, 0x42U, 0x00U, 0x55U,
|
||||
0x0DU, 0x00U, 0x41U, 0x9EU, 0x8AU, 0x80U, 0x80U, 0x00U, 0x41U, 0x08U,
|
||||
0x42U, 0xD6U, 0x00U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU,
|
||||
0x0BU, 0x41U, 0x00U, 0x20U, 0x04U, 0x3CU, 0x00U, 0xF1U, 0x8AU, 0x80U,
|
||||
0x80U, 0x00U, 0x41U, 0x00U, 0x20U, 0x04U, 0x42U, 0x08U, 0x88U, 0x3CU,
|
||||
0x00U, 0xF0U, 0x8AU, 0x80U, 0x80U, 0x00U, 0x41U, 0x00U, 0x20U, 0x04U,
|
||||
0x42U, 0x10U, 0x88U, 0x3CU, 0x00U, 0xEFU, 0x8AU, 0x80U, 0x80U, 0x00U,
|
||||
0x41U, 0x00U, 0x20U, 0x04U, 0x42U, 0x18U, 0x88U, 0x3CU, 0x00U, 0xEEU,
|
||||
0x8AU, 0x80U, 0x80U, 0x00U, 0x41U, 0x00U, 0x20U, 0x04U, 0x42U, 0x20U,
|
||||
0x88U, 0x3CU, 0x00U, 0xEDU, 0x8AU, 0x80U, 0x80U, 0x00U, 0x41U, 0x00U,
|
||||
0x20U, 0x04U, 0x42U, 0x28U, 0x88U, 0x3CU, 0x00U, 0xECU, 0x8AU, 0x80U,
|
||||
0x80U, 0x00U, 0x41U, 0x00U, 0x20U, 0x04U, 0x42U, 0x30U, 0x88U, 0x3CU,
|
||||
0x00U, 0xEBU, 0x8AU, 0x80U, 0x80U, 0x00U, 0x41U, 0x00U, 0x20U, 0x04U,
|
||||
0x42U, 0x38U, 0x88U, 0xA7U, 0x41U, 0x3FU, 0x71U, 0x41U, 0xC0U, 0x00U,
|
||||
0x72U, 0x3AU, 0x00U, 0xEAU, 0x8AU, 0x80U, 0x80U, 0x00U, 0x02U, 0x40U,
|
||||
0x20U, 0x01U, 0x41U, 0x20U, 0x41U, 0xD0U, 0x8AU, 0x80U, 0x80U, 0x00U,
|
||||
0x41U, 0xE5U, 0x01U, 0x10U, 0x8BU, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U,
|
||||
0x20U, 0x51U, 0x0DU, 0x00U, 0x41U, 0x8DU, 0x89U, 0x80U, 0x80U, 0x00U,
|
||||
0x41U, 0x26U, 0x42U, 0xDAU, 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,
|
||||
0x20U, 0x6AU, 0x24U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x20U, 0x04U,
|
||||
0x0BU, 0x0BU, 0xBAU, 0x04U, 0x02U, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU,
|
||||
0xA6U, 0x02U, 0x47U, 0x00U, 0x65U, 0x74U, 0x78U, 0x6EU, 0x5FU, 0x64U,
|
||||
0x65U, 0x74U, 0x61U, 0x69U, 0x6CU, 0x73U, 0x28U, 0x45U, 0x4DU, 0x49U,
|
||||
0x54U, 0x5FU, 0x4FU, 0x55U, 0x54U, 0x2CU, 0x20U, 0x31U, 0x33U, 0x38U,
|
||||
0x55U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x31U, 0x33U, 0x38U, 0x00U,
|
||||
0x6FU, 0x74U, 0x78U, 0x6EU, 0x5FU, 0x69U, 0x64U, 0x28U, 0x53U, 0x42U,
|
||||
0x55U, 0x46U, 0x28U, 0x69U, 0x64U, 0x29U, 0x2CU, 0x20U, 0x30U, 0x29U,
|
||||
0x20U, 0x3DU, 0x3DU, 0x20U, 0x33U, 0x32U, 0x00U, 0x73U, 0x74U, 0x61U,
|
||||
0x74U, 0x65U, 0x5FU, 0x66U, 0x6FU, 0x72U, 0x65U, 0x69U, 0x67U, 0x6EU,
|
||||
0x5FU, 0x73U, 0x65U, 0x74U, 0x28U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U,
|
||||
0x69U, 0x64U, 0x29U, 0x2CU, 0x20U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U,
|
||||
0x77U, 0x72U, 0x69U, 0x74U, 0x65U, 0x5FU, 0x6BU, 0x65U, 0x79U, 0x29U,
|
||||
0x2CU, 0x20U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U, 0x6EU, 0x73U, 0x29U,
|
||||
0x2CU, 0x20U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U, 0x67U, 0x72U, 0x61U,
|
||||
0x6EU, 0x74U, 0x6FU, 0x72U, 0x29U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U,
|
||||
0x33U, 0x32U, 0x00U, 0x65U, 0x6DU, 0x69U, 0x74U, 0x28U, 0x53U, 0x42U,
|
||||
0x55U, 0x46U, 0x28U, 0x65U, 0x6DU, 0x69U, 0x74U, 0x68U, 0x61U, 0x73U,
|
||||
0x68U, 0x29U, 0x2CU, 0x20U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U, 0x74U,
|
||||
0x78U, 0x6EU, 0x29U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x33U, 0x32U,
|
||||
0x00U, 0x65U, 0x74U, 0x78U, 0x6EU, 0x5FU, 0x72U, 0x65U, 0x73U, 0x65U,
|
||||
0x72U, 0x76U, 0x65U, 0x28U, 0x31U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U,
|
||||
0x31U, 0x00U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x5FU, 0x70U, 0x61U, 0x72U,
|
||||
0x61U, 0x6DU, 0x28U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U, 0x67U, 0x72U,
|
||||
0x61U, 0x6EU, 0x74U, 0x6FU, 0x72U, 0x29U, 0x2CU, 0x20U, 0x28U, 0x75U,
|
||||
0x69U, 0x6EU, 0x74U, 0x33U, 0x32U, 0x5FU, 0x74U, 0x29U, 0x22U, 0x47U,
|
||||
0x22U, 0x2CU, 0x20U, 0x31U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x32U,
|
||||
0x30U, 0x00U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x5FU, 0x61U, 0x63U, 0x63U,
|
||||
0x6FU, 0x75U, 0x6EU, 0x74U, 0x28U, 0x41U, 0x43U, 0x43U, 0x4FU, 0x55U,
|
||||
0x4EU, 0x54U, 0x5FU, 0x4FU, 0x55U, 0x54U, 0x2CU, 0x20U, 0x32U, 0x30U,
|
||||
0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x32U, 0x30U, 0x00U, 0x66U, 0x65U,
|
||||
0x65U, 0x20U, 0x3EU, 0x20U, 0x30U, 0x00U, 0x00U, 0x41U, 0xB0U, 0x0AU,
|
||||
0x0BU, 0x85U, 0x02U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x03U, 0x12U, 0x00U, 0x63U, 0x22U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x24U, 0x00U, 0x00U, 0x00U, 0x00U, 0x20U, 0x1AU,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x20U, 0x1BU, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x68U, 0x40U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x73U,
|
||||
0x21U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x81U, 0x14U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||
0x00U, 0x00U, 0x00U, 0x00U,
|
||||
}},
|
||||
|
||||
{R"[test.hook](
|
||||
#include <stdint.h>
|
||||
extern int32_t _g (uint32_t id, uint32_t maxiter);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <wasmedge/wasmedge.h>
|
||||
@@ -257,11 +258,15 @@ finalizeHookResult(
|
||||
bool doEmit);
|
||||
|
||||
// write state map to ledger
|
||||
// if `written` is supplied, every account whose hook state was successfully
|
||||
// written is inserted into it (own and foreign namespaces alike); deleting an
|
||||
// entry that does not exist is not a write
|
||||
ripple::TER
|
||||
finalizeHookState(
|
||||
HookStateMap const&,
|
||||
ripple::ApplyContext&,
|
||||
ripple::uint256 const&);
|
||||
ripple::uint256 const&,
|
||||
std::set<ripple::AccountID>* written = nullptr);
|
||||
|
||||
// if the txn being executed was an emitted txn then this removes it from the
|
||||
// emission directory
|
||||
|
||||
@@ -1368,7 +1368,8 @@ ripple::TER
|
||||
hook::finalizeHookState(
|
||||
HookStateMap const& stateMap,
|
||||
ripple::ApplyContext& applyCtx,
|
||||
ripple::uint256 const& txnID)
|
||||
ripple::uint256 const& txnID,
|
||||
std::set<ripple::AccountID>* written)
|
||||
{
|
||||
auto const& j = applyCtx.app.journal("View");
|
||||
uint16_t changeCount = 0;
|
||||
@@ -1400,6 +1401,12 @@ hook::finalizeHookState(
|
||||
// this entry isn't just cached, it was actually modified
|
||||
auto slice = Slice(blob.data(), blob.size());
|
||||
|
||||
// deleting an entry that does not exist leaves the
|
||||
// ledger unchanged, so it does not count as a write
|
||||
bool const changesLedger = !written || !blob.empty() ||
|
||||
applyCtx.view().exists(
|
||||
ripple::keylet::hookState(acc, key, ns));
|
||||
|
||||
TER result = setHookState(applyCtx, acc, ns, key, slice);
|
||||
|
||||
if (!isTesSuccess(result))
|
||||
@@ -1411,6 +1418,9 @@ hook::finalizeHookState(
|
||||
return result;
|
||||
}
|
||||
// ^ should not fail... checks were done before map insert
|
||||
|
||||
if (written && changesLedger)
|
||||
written->insert(acc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1198,6 +1198,46 @@ touchAccount(ApplyView& view, AccountID const& id)
|
||||
view.update(sle);
|
||||
}
|
||||
|
||||
void
|
||||
Transactor::touchOnce(AccountID const& id)
|
||||
{
|
||||
auto& view = ctx_.view();
|
||||
|
||||
// before fix20261005 every request touches, and touched_ stays empty
|
||||
if (!view.rules().enabled(fix20261005))
|
||||
{
|
||||
touchAccount(view, id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (touched_.insert(id).second)
|
||||
touchAccount(view, id);
|
||||
}
|
||||
|
||||
void
|
||||
Transactor::touchHookStateOwners(std::set<AccountID> const& written)
|
||||
{
|
||||
if (!view().rules().enabled(fix20261005))
|
||||
return;
|
||||
|
||||
// A hook may write into another account's namespace (state_foreign_set
|
||||
// under a HookGrant) without that account being a transactional
|
||||
// stakeholder. Touch it so the transaction threads to its AccountRoot.
|
||||
for (auto const& acc : written)
|
||||
touchOnce(acc);
|
||||
}
|
||||
|
||||
void
|
||||
Transactor::discardView()
|
||||
{
|
||||
ctx_.discard();
|
||||
|
||||
// The touches touched_ records were discarded with the view. touched_ is
|
||||
// only populated under fix20261005, so before the fix this is a no-op and
|
||||
// needs no amendment guard.
|
||||
touched_.clear();
|
||||
}
|
||||
|
||||
static void
|
||||
removeUnfundedOffers(
|
||||
ApplyView& view,
|
||||
@@ -1284,7 +1324,7 @@ Transactor::reset(XRPAmount fee)
|
||||
std::vector<STObject> executions;
|
||||
std::vector<STObject> emissions;
|
||||
avi.copyHookMetaData(executions, emissions);
|
||||
ctx_.discard();
|
||||
discardView();
|
||||
ApplyViewImpl& avi2 = dynamic_cast<ApplyViewImpl&>(ctx_.view());
|
||||
avi2.setHookMetaData(std::move(executions), std::move(emissions));
|
||||
|
||||
@@ -1595,8 +1635,12 @@ Transactor::doHookCallback(
|
||||
|
||||
// write any state changes if cbak resulted in accept()
|
||||
if (success)
|
||||
{
|
||||
std::set<AccountID> written;
|
||||
hook::finalizeHookState(
|
||||
stateMap, ctx_, ctx_.tx.getTransactionID());
|
||||
stateMap, ctx_, ctx_.tx.getTransactionID(), &written);
|
||||
touchHookStateOwners(written);
|
||||
}
|
||||
|
||||
// write the final result
|
||||
ripple::TER result =
|
||||
@@ -1707,7 +1751,10 @@ Transactor::doTSH(
|
||||
if ((!canRollback && strong) || (canRollback && !strong))
|
||||
continue;
|
||||
|
||||
touchAccount(view, tshAccountID);
|
||||
// under fix20261005 an account is touched at most once per
|
||||
// transaction (a foreign state write in the strong pass or a callback
|
||||
// may already have touched an account that is a weak TSH)
|
||||
touchOnce(tshAccountID);
|
||||
|
||||
if (view.rules().enabled(fixHookAPI20251128))
|
||||
{
|
||||
@@ -2017,7 +2064,12 @@ Transactor::operator()()
|
||||
|
||||
// write state if all chains executed successfully
|
||||
if (isTesSuccess(result))
|
||||
hook::finalizeHookState(stateMap, ctx_, ctx_.tx.getTransactionID());
|
||||
{
|
||||
std::set<AccountID> written;
|
||||
hook::finalizeHookState(
|
||||
stateMap, ctx_, ctx_.tx.getTransactionID(), &written);
|
||||
touchHookStateOwners(written);
|
||||
}
|
||||
|
||||
// write hook results
|
||||
// this happens irrespective of whether final result was a tesSUCCESS
|
||||
@@ -2071,7 +2123,7 @@ Transactor::finishApply(
|
||||
{
|
||||
// If the tapFAIL_HARD flag is set, a tec result
|
||||
// must not do anything
|
||||
ctx_.discard();
|
||||
discardView();
|
||||
applied = false;
|
||||
}
|
||||
else if (
|
||||
@@ -2407,7 +2459,12 @@ Transactor::finishApply(
|
||||
doAgainAsWeak(accID, hookHashes, stateMap, weakResults, proMeta);
|
||||
|
||||
// write hook results
|
||||
hook::finalizeHookState(stateMap, ctx_, ctx_.tx.getTransactionID());
|
||||
{
|
||||
std::set<AccountID> written;
|
||||
hook::finalizeHookState(
|
||||
stateMap, ctx_, ctx_.tx.getTransactionID(), &written);
|
||||
touchHookStateOwners(written);
|
||||
}
|
||||
for (auto& weakResult : weakResults)
|
||||
hook::finalizeHookResult(weakResult, ctx_, isTesSuccess(result));
|
||||
|
||||
|
||||
@@ -218,6 +218,21 @@ protected:
|
||||
void
|
||||
addWeakTSHFromBalanceChanges(detail::ApplyViewBase const& pv);
|
||||
|
||||
// Touch an account (featureTouch). Under fix20261005 each account is
|
||||
// touched at most once per transaction.
|
||||
void
|
||||
touchOnce(AccountID const& id);
|
||||
|
||||
// fix20261005: touch every account whose hook state finalizeHookState
|
||||
// wrote, so the transaction threads to the AccountRoot of each
|
||||
void
|
||||
touchHookStateOwners(std::set<AccountID> const& written);
|
||||
|
||||
// Discard every change made to the view, together with the record of
|
||||
// which accounts were touched in it.
|
||||
void
|
||||
discardView();
|
||||
|
||||
// hooks amendment fields, these are unpopulated and unused unless
|
||||
// featureHooks is enabled
|
||||
int executedHookCount_ =
|
||||
@@ -227,6 +242,10 @@ protected:
|
||||
// end of the transactor, who isn't able to be
|
||||
// deduced until after apply i.e. pathing
|
||||
// participants, crossed offers
|
||||
std::set<AccountID>
|
||||
touched_; // fix20261005: accounts touched (featureTouch) in the
|
||||
// current view. Never populated before the fix, emptied
|
||||
// whenever the view is discarded.
|
||||
|
||||
// The post-apply pipeline of operator(): tec handling (reset),
|
||||
// invariants, balance rewards, weak hooks and commit.
|
||||
|
||||
Reference in new issue
Block a user