Files
xahaud/hook/nftoken.c
2023-07-14 09:26:18 +00:00

214 lines
6.0 KiB
C

#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 );
_02_02_ENCODE_FLAGS (buf_out, tfCANONICAL );
_02_04_ENCODE_SEQUENCE (buf_out, 0 );
_02_26_ENCODE_FLS (buf_out, cls + 1 );
_02_27_ENCODE_LLS (buf_out, cls + 5 );
_06_01_ENCODE_DROPS_AMOUNT (buf_out, 0 );
uint8_t* fee_ptr = buf_out;
_06_08_ENCODE_DROPS_FEE (buf_out, 0 );
_07_03_ENCODE_SIGNING_PUBKEY_NULL (buf_out );
// 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 );
_08_03_ENCODE_ACCOUNT_DST (buf_out, otxn_acc );
int64_t edlen = etxn_details((uint32_t)buf_out, 512);
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 );
}
trace(SBUF("emit txn"), txn_buf, txn_len, 1);
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__);
}