example burn2mint xls20->uritoken

This commit is contained in:
Richard Holland
2023-07-11 21:06:48 +00:00
parent 96af8735ba
commit 076b8e3e11
6 changed files with 217 additions and 7 deletions

View File

@@ -346,5 +346,7 @@ util_verify(
uint32_t sread_len,
uint32_t kread_ptr,
uint32_t kread_len);
extern int64_t xpop_slot(uint32_t, uint32_t);
#define HOOK_EXTERN
#endif // HOOK_EXTERN

View File

@@ -37,7 +37,6 @@
*
* Topics:
* 'H[0-9]' - Hook Hash in positions 0-9 <32 byte hash> on genesis
* 'h[0-9]' - Hook Hash in positions 0-9 <32 byte hash> on local L2 table (when applicable)
* 'RR' - reward rate <le xfl 8 bytes>
* 'RD' - reward delay <le xfl 8 bytes>
* 'S[0-19]' - who is a governance member occupying that seat <20 byte accid>

View File

@@ -136,11 +136,7 @@ int out_len = 0;\
*(((uint64_t*)(buf1)) + 0) == *(((uint64_t*)(buf2)) + 0) &&\
*(((uint64_t*)(buf1)) + 1) == *(((uint64_t*)(buf2)) + 1) &&\
*(((uint64_t*)(buf1)) + 2) == *(((uint64_t*)(buf2)) + 2) &&\
*(((uint64_t*)(buf1)) + 3) == *(((uint64_t*)(buf2)) + 3) &&\
*(((uint64_t*)(buf1)) + 4) == *(((uint64_t*)(buf2)) + 4) &&\
*(((uint64_t*)(buf1)) + 5) == *(((uint64_t*)(buf2)) + 5) &&\
*(((uint64_t*)(buf1)) + 6) == *(((uint64_t*)(buf2)) + 6) &&\
*(((uint64_t*)(buf1)) + 7) == *(((uint64_t*)(buf2)) + 7))
*(((uint64_t*)(buf1)) + 3) == *(((uint64_t*)(buf2)) + 3))
// when using this macro buf1len may be dynamic but buf2len must be static

View File

@@ -164,3 +164,6 @@ mint:
-Oz
hook-cleaner mint.wasm
guard_checker mint.wasm
xpop:
wasmcc xpop.c -o xpop.wasm -Oz -Wl,--allow-undefined -I../
hook-cleaner xpop.wasm

210
hook/xpop.c Normal file
View File

@@ -0,0 +1,210 @@
#include <stdint.h>
#include "hookapi.h"
#define SVAR(x) &x, sizeof(x)
#define SBUF(x) (x), sizeof(x)
#define NOPE(x)\
{\
return rollback((x), sizeof(x), __LINE__);\
}
#define ttNFTOKEN_BURN 26
#define ttIMPORT 97
#define ttURITOKEN_MINT 45
int64_t hook(uint32_t r)
{
_g(1,1);
uint8_t hook_acc[20];
hook_account(SBUF(hook_acc));
uint8_t otxn_acc[20];
otxn_field(SBUF(otxn_acc), sfAccount);
// outgoing
if (BUFFER_EQUAL_20(hook_acc, otxn_acc))
accept(SBUF("NFTImport: Passing outgoing txn."), __LINE__);
if (otxn_type() != ttIMPORT)
accept(SBUF("NFTImport: Passing non ttIMPORT txn."), otxn_type());
int64_t retval = xpop_slot(1,2);
if (retval <= 0)
NOPE("Failed to slot xpop");
#define tx_slot 1
#define meta_slot 2
trace_num("Slotted xpop", 12, retval);
uint8_t dump1[2048];
uint8_t dump2[2048];
int64_t len1 = slot(dump1, sizeof(dump1), tx_slot);
int64_t len2 = slot(dump2, sizeof(dump2), meta_slot);
trace("tx", 2, dump1, len1, 1);
trace("meta", 4, dump2, len2, 1);
if (slot_subfield(meta_slot, sfTransactionResult, 3) != 3)
NOPE("Failed to slot transaction result");
uint8_t tr;
if (slot(SVAR(tr), 3) != 1)
NOPE("Failed to dump transaction result");
trace_num(SBUF("Inner Transaction Result:"), tr);
if (tr != 0)
NOPE("Inner Transaction Result not tesSUCCESS (0).");
// execution to here means tesSUCCESS on inner
if (slot_subfield(tx_slot, sfTransactionType, 4) != 4)
NOPE("Could not slot transaction type");
uint8_t tt_buf[2];
if (slot(SBUF(tt_buf), 4) != 2)
NOPE("Could not dump transaction type");
uint16_t tt = UINT16_FROM_BUF(tt_buf);
if (tt != ttNFTOKEN_BURN)
NOPE("Only NFTokenBurn is accepted");
// go track down the URI of the token (this is a huge pain, has to be done through metadata)
//
#define nodes 5
if (slot_subfield(meta_slot, sfAffectedNodes, nodes) != nodes)
NOPE("Could not slot sfAffectedNodes");
uint8_t dump4[1024];
trace(SBUF("slot nodes"), dump4, slot(SBUF(dump4), nodes), 1);
int64_t count = slot_count(nodes);
if (count > 5) count = 5;
int64_t found;
for (int i = 0; GUARD(5), i < count; ++i)
{
if (slot_subarray(nodes, i, 6) != 6)
break;
if (slot_subfield(6, sfLedgerEntryType, 7) != 7)
NOPE("Could not slot LedgerEntryType");
uint8_t buf[2];
slot(SVAR(buf), 7);
if (UINT16_FROM_BUF(buf) == 0x0050U)
{
found = 1;
break;
}
}
if (!found)
NOPE("Could not find NFTokenPage in xpop metadata");
if (slot_subfield(6, sfPreviousFields, 6) != 6 && slot_subfield(6, sfFinalFields, 6) != 6)
NOPE("Could not slot sfPreviousFields");
if (slot_subfield(6, sfNFTokens, 6) != 6)
NOPE("Could not slot sfNFTokens");
count = slot_count(6);
if (count > 32) count = 32;
trace_num(SBUF("Modified node count:"), count);
uint8_t burned_tid[32];
if (slot_subfield(tx_slot, sfNFTokenID, 7) != 7 || slot(SBUF(burned_tid), 7) != 32)
NOPE("Xpop txn did not contain valid nftokenid");
uint8_t uri[256];
int64_t urilen;
found = 0;
for (int i = 0; GUARD(32), i < count; ++i)
{
if (slot_subarray(6, i, 7) != 7)
break;
{
uint8_t dump4[1024];
int64_t len = slot(SBUF(dump4), 7);
trace(SBUF("dump4"), dump4, len, 1);
}
uint8_t tid[32];
int64_t r;
if ((r=slot_subfield(7, sfNFTokenID, 8)) != 8)
{
trace_num(SBUF("r"), r);
break;
}
slot(SBUF(tid), 8);
if (slot_subfield(7, sfURI, 8) != 8)
continue;
urilen = slot(SBUF(uri), 8);
trace(SBUF("uri: "), uri, urilen, 1);
trace(SBUF("tid1"), tid, 32, 1);
trace(SBUF("tid2"), burned_tid, 32, 1);
found = BUFFER_EQUAL_32(tid, burned_tid);
if (found)
{
trace(SBUF("found"), 0,0,0);
found = 1;
break;
}
}
if (!found)
NOPE("Could not find the NFTokenID in the metadata");
trace(SBUF("URI from xpop: "), uri, urilen, 1);
etxn_reserve(1);
uint8_t txn_buf[1024];
int64_t txn_len;
{
uint8_t* buf_out = txn_buf;
uint32_t cls = (uint32_t)ledger_seq();
_01_02_ENCODE_TT (buf_out, ttURITOKEN_MINT ); /* uint16 | size 3 */
_02_02_ENCODE_FLAGS (buf_out, tfCANONICAL ); /* uint32 | size 5 */
_02_04_ENCODE_SEQUENCE (buf_out, 0 ); /* uint32 | size 5 */
_02_26_ENCODE_FLS (buf_out, cls + 1 ); /* uint32 | size 6 */
_02_27_ENCODE_LLS (buf_out, cls + 5 ); /* uint32 | size 6 */
uint8_t* fee_ptr = buf_out;
_06_08_ENCODE_DROPS_FEE (buf_out, 0 ); /* amount | size 9 */
_07_03_ENCODE_SIGNING_PUBKEY_NULL (buf_out ); /* pk | size 35 */
// URI
*buf_out++ = 0x75U;
for (int i = 0; GUARD(32), i < 32; ++i)
*(((uint64_t*)buf_out) + i) = *(((uint64_t*)uri) + i);
buf_out += urilen;
_08_01_ENCODE_ACCOUNT_SRC (buf_out, hook_acc ); /* account | size 22 */
_08_03_ENCODE_ACCOUNT_DST (buf_out, otxn_acc ); /* account | size 22 */
int64_t edlen = etxn_details((uint32_t)buf_out, 512); /* emitdet | size 1?? */
trace_num(SBUF("edlen"), edlen);
buf_out += edlen;
txn_len = buf_out - txn_buf;
int64_t fee = etxn_fee_base(txn_buf, txn_len);
_06_08_ENCODE_DROPS_FEE (fee_ptr, fee );
}
uint8_t etxid[32];
if (emit(SBUF(etxid), txn_buf, txn_len) < 0)
NOPE("Emission failed");
trace(SBUF("Emission success"), etxid, 32, 1);
return accept(0UL, 0UL, __LINE__);
}

View File

@@ -363,10 +363,10 @@ CONSTRUCT_UNTYPED_SFIELD(sfDisabledValidators, "DisabledValidators", ARRAY,
CONSTRUCT_UNTYPED_SFIELD(sfHookExecutions, "HookExecutions", ARRAY, 18);
CONSTRUCT_UNTYPED_SFIELD(sfHookParameters, "HookParameters", ARRAY, 19);
CONSTRUCT_UNTYPED_SFIELD(sfHookGrants, "HookGrants", ARRAY, 20);
CONSTRUCT_UNTYPED_SFIELD(sfHookEmissions, "HookEmissions", ARRAY, 95);
CONSTRUCT_UNTYPED_SFIELD(sfGenesisMints, "GenesisMints", ARRAY, 96);
CONSTRUCT_UNTYPED_SFIELD(sfActiveValidators, "ActiveValidators", ARRAY, 95);
CONSTRUCT_UNTYPED_SFIELD(sfImportVLKeys, "ImportVLKeys", ARRAY, 94);
CONSTRUCT_UNTYPED_SFIELD(sfHookEmissions, "HookEmissions", ARRAY, 93);
// clang-format on