Compare commits

...
Author SHA1 Message Date
Richard Holland a90944e09d Merge branch 'dev' into hook_state_touch 2026-10-05 18:41:37 +10:00
Richard Holland 37161f82d5 fixes for hook state touch 2026-10-05 17:39:03 +11:00
Richard Holland e690bee955 Merge branch 'dev' into hook_state_touch 2026-10-05 15:52:29 +10:00
Richard Holland 871dbc2596 clang 2026-10-04 17:16:55 +11:00
Richard Holland 653927eb49 init 2026-10-04 16:57:41 +11:00
6 changed files with 1439 additions and 13 deletions

No files matched your search

+587 -5
View File
@@ -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); //
+753
View File
@@ -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);
+6 -1
View File
@@ -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
+11 -1
View File
@@ -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);
}
}
}
+63 -6
View File
@@ -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));
+19
View File
@@ -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.