diff --git a/hook/error.h b/hook/error.h new file mode 100644 index 000000000..8ea4c3fa4 --- /dev/null +++ b/hook/error.h @@ -0,0 +1,46 @@ +// For documentation please see: https://xrpl-hooks.readme.io/reference/ +// Generated using generate_error.sh +#ifndef HOOK_ERROR_CODES +#define SUCCESS 0 +#define OUT_OF_BOUNDS -1 +#define INTERNAL_ERROR -2 +#define TOO_BIG -3 +#define TOO_SMALL -4 +#define DOESNT_EXIST -5 +#define NO_FREE_SLOTS -6 +#define INVALID_ARGUMENT -7 +#define ALREADY_SET -8 +#define PREREQUISITE_NOT_MET -9 +#define FEE_TOO_LARGE -10 +#define EMISSION_FAILURE -11 +#define TOO_MANY_NONCES -12 +#define TOO_MANY_EMITTED_TXN -13 +#define NOT_IMPLEMENTED -14 +#define INVALID_ACCOUNT -15 +#define GUARD_VIOLATION -16 +#define INVALID_FIELD -17 +#define PARSE_ERROR -18 +#define RC_ROLLBACK -19 +#define RC_ACCEPT -20 +#define NO_SUCH_KEYLET -21 +#define NOT_AN_ARRAY -22 +#define NOT_AN_OBJECT -23 +#define INVALID_FLOAT -10024 +#define DIVISION_BY_ZERO -25 +#define MANTISSA_OVERSIZED -26 +#define MANTISSA_UNDERSIZED -27 +#define EXPONENT_OVERSIZED -28 +#define EXPONENT_UNDERSIZED -29 +#define OVERFLOW -30 +#define NOT_IOU_AMOUNT -31 +#define NOT_AN_AMOUNT -32 +#define CANT_RETURN_NEGATIVE -33 +#define NOT_AUTHORIZED -34 +#define PREVIOUS_FAILURE_PREVENTS_RETRY -35 +#define TOO_MANY_PARAMS -36 +#define INVALID_TXN -37 +#define RESERVE_INSUFFICIENT -38 +#define COMPLEX_NOT_SUPPORTED -39 +#define DOES_NOT_MATCH -40 +#define HOOK_ERROR_CODES +#endif //HOOK_ERROR_CODES diff --git a/hook/extern.h b/hook/extern.h new file mode 100644 index 000000000..c1c24e921 --- /dev/null +++ b/hook/extern.h @@ -0,0 +1,343 @@ +// For documentation please see: https://xrpl-hooks.readme.io/reference/ +// Generated using generate_extern.sh +#include +#ifndef HOOK_EXTERN + +extern int32_t __attribute__((noduplicate)) +_g(uint32_t guard_id, uint32_t maxiter); + +extern int64_t +accept(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 +etxn_burden(void); + +extern int64_t +etxn_details(uint32_t write_ptr, uint32_t write_len); + +extern int64_t +etxn_fee_base(uint32_t read_ptr, uint32_t read_len); + +extern int64_t +etxn_generation(void); + +extern int64_t +etxn_nonce(uint32_t write_ptr, uint32_t write_len); + +extern int64_t +etxn_reserve(uint32_t count); + +extern int64_t +fee_base(void); + +extern int64_t +float_compare(int64_t float1, int64_t float2, uint32_t mode); + +extern int64_t +float_divide(int64_t float1, int64_t float2); + +extern int64_t +float_exponent(int64_t float1); + +extern int64_t +float_exponent_set(int64_t float1, int32_t exponent); + +extern int64_t +float_int(int64_t float1, uint32_t decimal_places, uint32_t abs); + +extern int64_t +float_invert(int64_t float1); + +extern int64_t +float_log(int64_t float1); + +extern int64_t +float_mantissa(int64_t float1); + +extern int64_t +float_mantissa_set(int64_t float1, int64_t mantissa); + +extern int64_t +float_mulratio( + int64_t float1, + uint32_t round_up, + uint32_t numerator, + uint32_t denominator); + +extern int64_t +float_multiply(int64_t float1, int64_t float2); + +extern int64_t +float_negate(int64_t float1); + +extern int64_t +float_one(void); + +extern int64_t +float_root(int64_t float1, uint32_t n); + +extern int64_t +float_set(int32_t exponent, int64_t mantissa); + +extern int64_t +float_sign(int64_t float1); + +extern int64_t +float_sign_set(int64_t float1, uint32_t negative); + +extern int64_t +float_sto( + uint32_t write_ptr, + uint32_t write_len, + uint32_t cread_ptr, + uint32_t cread_len, + uint32_t iread_ptr, + uint32_t iread_len, + int64_t float1, + uint32_t field_code); + +extern int64_t +float_sto_set(uint32_t read_ptr, uint32_t read_len); + +extern int64_t +float_sum(int64_t float1, int64_t float2); + +extern int64_t +hook_account(uint32_t write_ptr, uint32_t write_len); + +extern int64_t +hook_again(void); + +extern int64_t +hook_hash(uint32_t write_ptr, uint32_t write_len, int32_t hook_no); + +extern int64_t +hook_param( + uint32_t write_ptr, + uint32_t write_len, + uint32_t read_ptr, + uint32_t read_len); + +extern int64_t +hook_param_set( + uint32_t read_ptr, + uint32_t read_len, + uint32_t kread_ptr, + uint32_t kread_len, + uint32_t hread_ptr, + uint32_t hread_len); + +extern int64_t +hook_pos(void); + +extern int64_t +hook_skip(uint32_t read_ptr, uint32_t read_len, uint32_t flags); + +extern int64_t +ledger_keylet( + uint32_t write_ptr, + uint32_t write_len, + uint32_t lread_ptr, + uint32_t lread_len, + uint32_t hread_ptr, + uint32_t hread_len); + +extern int64_t +ledger_last_hash(uint32_t write_ptr, uint32_t write_len); + +extern int64_t +ledger_last_time(void); + +extern int64_t +ledger_nonce(uint32_t write_ptr, uint32_t write_len); + +extern int64_t +ledger_seq(void); + +extern int64_t +meta_slot(uint32_t slot_no); + +extern int64_t +otxn_burden(void); + +extern int64_t +otxn_field(uint32_t write_ptr, uint32_t write_len, uint32_t field_id); + +extern int64_t +otxn_field_txt(uint32_t write_ptr, uint32_t write_len, uint32_t field_id); + +extern int64_t +otxn_generation(void); + +extern int64_t +otxn_id(uint32_t write_ptr, uint32_t write_len, uint32_t flags); + +extern int64_t +otxn_slot(uint32_t slot_no); + +extern int64_t +otxn_type(void); + +extern int64_t +rollback(uint32_t read_ptr, uint32_t read_len, int64_t error_code); + +extern int64_t +slot(uint32_t write_ptr, uint32_t write_len, uint32_t slot); + +extern int64_t +slot_clear(uint32_t slot); + +extern int64_t +slot_count(uint32_t slot); + +extern int64_t +slot_float(uint32_t slot_no); + +extern int64_t +slot_id(uint32_t write_ptr, uint32_t write_len, uint32_t slot); + +extern int64_t +slot_set(uint32_t read_ptr, uint32_t read_len, uint32_t slot); + +extern int64_t +slot_size(uint32_t slot); + +extern int64_t +slot_subarray(uint32_t parent_slot, uint32_t array_id, uint32_t new_slot); + +extern int64_t +slot_subfield(uint32_t parent_slot, uint32_t field_id, uint32_t new_slot); + +extern int64_t +slot_type(uint32_t slot_no, uint32_t flags); + +extern int64_t +state( + uint32_t write_ptr, + uint32_t write_len, + uint32_t kread_ptr, + uint32_t kread_len); + +extern int64_t +state_foreign( + uint32_t write_ptr, + uint32_t write_len, + uint32_t kread_ptr, + uint32_t kread_len, + uint32_t nread_ptr, + uint32_t nread_len, + uint32_t aread_ptr, + uint32_t aread_len); + +extern int64_t +state_foreign_set( + uint32_t read_ptr, + uint32_t read_len, + uint32_t kread_ptr, + uint32_t kread_len, + uint32_t nread_ptr, + uint32_t nread_len, + uint32_t aread_ptr, + uint32_t aread_len); + +extern int64_t +state_set( + uint32_t read_ptr, + uint32_t read_len, + uint32_t kread_ptr, + uint32_t kread_len); + +extern int64_t +sto_emplace( + uint32_t write_ptr, + uint32_t write_len, + uint32_t sread_ptr, + uint32_t sread_len, + uint32_t fread_ptr, + uint32_t fread_len, + uint32_t field_id); + +extern int64_t +sto_erase( + uint32_t write_ptr, + uint32_t write_len, + uint32_t read_ptr, + uint32_t read_len, + uint32_t field_id); + +extern int64_t +sto_subarray(uint32_t read_ptr, uint32_t read_len, uint32_t array_id); + +extern int64_t +sto_subfield(uint32_t read_ptr, uint32_t read_len, uint32_t field_id); + +extern int64_t +sto_validate(uint32_t tread_ptr, uint32_t tread_len); + +extern int64_t +trace( + uint32_t mread_ptr, + uint32_t mread_len, + uint32_t dread_ptr, + uint32_t dread_len, + uint32_t as_hex); + +extern int64_t +trace_float(uint32_t read_ptr, uint32_t read_len, int64_t float1); + +extern int64_t +trace_num(uint32_t read_ptr, uint32_t read_len, int64_t number); + +extern int64_t +trace_slot(uint32_t read_ptr, uint32_t read_len, uint32_t slot); + +extern int64_t +util_accid( + uint32_t write_ptr, + uint32_t write_len, + uint32_t read_ptr, + uint32_t read_len); + +extern int64_t +util_keylet( + uint32_t write_ptr, + uint32_t write_len, + uint32_t keylet_type, + uint32_t a, + uint32_t b, + uint32_t c, + uint32_t d, + uint32_t e, + uint32_t f); + +extern int64_t +util_raddr( + uint32_t write_ptr, + uint32_t write_len, + uint32_t read_ptr, + uint32_t read_len); + +extern int64_t +util_sha512h( + uint32_t write_ptr, + uint32_t write_len, + uint32_t read_ptr, + uint32_t read_len); + +extern int64_t +util_verify( + uint32_t dread_ptr, + uint32_t dread_len, + uint32_t sread_ptr, + uint32_t sread_len, + uint32_t kread_ptr, + uint32_t kread_len); +#define HOOK_EXTERN +#endif // HOOK_EXTERN diff --git a/hook/hookapi.h b/hook/hookapi.h new file mode 100644 index 000000000..680af611a --- /dev/null +++ b/hook/hookapi.h @@ -0,0 +1,49 @@ +/** + * Hook API include file + * + * Note to the reader: + * This include defines two types of things: external functions and macros + * Functions are used sparingly because a non-inlining compiler may produce + * undesirable output. + * + * Find documentation here: https://xrpl-hooks.readme.io/reference/ + */ + +#ifndef HOOKAPI_INCLUDED +#define HOOKAPI_INCLUDED 1 + +#define KEYLET_HOOK 1 +#define KEYLET_HOOK_STATE 2 +#define KEYLET_ACCOUNT 3 +#define KEYLET_AMENDMENTS 4 +#define KEYLET_CHILD 5 +#define KEYLET_SKIP 6 +#define KEYLET_FEES 7 +#define KEYLET_NEGATIVE_UNL 8 +#define KEYLET_LINE 9 +#define KEYLET_OFFER 10 +#define KEYLET_QUALITY 11 +#define KEYLET_EMITTED_DIR 12 +#define KEYLET_TICKET 13 +#define KEYLET_SIGNERS 14 +#define KEYLET_CHECK 15 +#define KEYLET_DEPOSIT_PREAUTH 16 +#define KEYLET_UNCHECKED 17 +#define KEYLET_OWNER_DIR 18 +#define KEYLET_PAGE 19 +#define KEYLET_ESCROW 20 +#define KEYLET_PAYCHAN 21 +#define KEYLET_EMITTED 22 +#define KEYLET_NFT_OFFER 23 +#define KEYLET_HOOK_DEFINITION 24 + +#define COMPARE_EQUAL 1U +#define COMPARE_LESS 2U +#define COMPARE_GREATER 4U + +#include "error.h" +#include "extern.h" +#include "sfcodes.h" +#include "macro.h" + +#endif diff --git a/hook/macro.h b/hook/macro.h new file mode 100644 index 000000000..47484cbd8 --- /dev/null +++ b/hook/macro.h @@ -0,0 +1,621 @@ +/** + * These are helper macros for writing hooks, all of them are optional as is including hookmacro.h at all + */ + +#include +#include "hookapi.h" +#include "sfcodes.h" + +#ifndef HOOKMACROS_INCLUDED +#define HOOKMACROS_INCLUDED 1 + + +#ifdef NDEBUG +#define DEBUG 0 +#else +#define DEBUG 1 +#endif + +#define TRACEVAR(v) if (DEBUG) trace_num((uint32_t)(#v), (uint32_t)(sizeof(#v) - 1), (int64_t)v); +#define TRACEHEX(v) if (DEBUG) trace((uint32_t)(#v), (uint32_t)(sizeof(#v) - 1), (uint32_t)(v), (uint32_t)(sizeof(v)), 1); +#define TRACEXFL(v) if (DEBUG) trace_float((uint32_t)(#v), (uint32_t)(sizeof(#v) - 1), (int64_t)v); +#define TRACESTR(v) if (DEBUG) trace((uint32_t)(#v), (uint32_t)(sizeof(#v) - 1), (uint32_t)(v), sizeof(v), 0); + +// hook developers should use this guard macro, simply GUARD() +#define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) +#define GUARDM(maxiter, n) _g(( (1ULL << 31U) + (__LINE__ << 16) + n), (maxiter)+1) + +#define SBUF(str) (uint32_t)(str), sizeof(str) + +#define REQUIRE(cond, str)\ +{\ + if (!(cond))\ + rollback(SBUF(str), __LINE__);\ +} + +// make a report buffer as a c-string +// provide a name for a buffer to declare (buf) +// provide a static string +// provide an integer to print after the string +#define RBUF(buf, out_len, str, num)\ +unsigned char buf[sizeof(str) + 21];\ +int out_len = 0;\ +{\ + int i = 0;\ + for (; GUARDM(sizeof(str),1),i < sizeof(str); ++i)\ + (buf)[i] = str[i];\ + if ((buf)[sizeof(str)-1] == 0) i--;\ + if ((num) < 0) (buf)[i++] = '-';\ + uint64_t unsigned_num = (uint64_t)( (num) < 0 ? (num) * -1 : (num) );\ + uint64_t j = 10000000000000000000ULL;\ + int start = 1;\ + for (; GUARDM(20,2), unsigned_num > 0 && j > 0; j /= 10)\ + {\ + unsigned char digit = ( unsigned_num / j ) % 10;\ + if (digit == 0 && start)\ + continue;\ + start = 0;\ + (buf)[i++] = '0' + digit;\ + }\ + (buf)[i] = '\0';\ + out_len = i;\ +} + +#define RBUF2(buff, out_len, str, num, str2, num2)\ +unsigned char buff[sizeof(str) + sizeof(str2) + 42];\ +int out_len = 0;\ +{\ + unsigned char* buf = buff;\ + int i = 0;\ + for (; GUARDM(sizeof(str),1),i < sizeof(str); ++i)\ + (buf)[i] = str[i];\ + if ((buf)[sizeof(str)-1] == 0) i--;\ + if ((num) < 0) (buf)[i++] = '-';\ + uint64_t unsigned_num = (uint64_t)( (num) < 0 ? (num) * -1 : (num) );\ + uint64_t j = 10000000000000000000ULL;\ + int start = 1;\ + for (; GUARDM(20,2), unsigned_num > 0 && j > 0; j /= 10)\ + {\ + unsigned char digit = ( unsigned_num / j ) % 10;\ + if (digit == 0 && start)\ + continue;\ + start = 0;\ + (buf)[i++] = '0' + digit;\ + }\ + buf += i;\ + out_len += i;\ + i = 0;\ + for (; GUARDM(sizeof(str2),3),i < sizeof(str2); ++i)\ + (buf)[i] = str2[i];\ + if ((buf)[sizeof(str2)-1] == 0) i--;\ + if ((num2) < 0) (buf)[i++] = '-';\ + unsigned_num = (uint64_t)( (num2) < 0 ? (num2) * -1 : (num2) );\ + j = 10000000000000000000ULL;\ + start = 1;\ + for (; GUARDM(20,4), unsigned_num > 0 && j > 0; j /= 10)\ + {\ + unsigned char digit = ( unsigned_num / j ) % 10;\ + if (digit == 0 && start)\ + continue;\ + start = 0;\ + (buf)[i++] = '0' + digit;\ + }\ + (buf)[i] = '\0';\ + out_len += i;\ +} + +#define CLEARBUF(b)\ +{\ + for (int x = 0; GUARD(sizeof(b)), x < sizeof(b); ++x)\ + b[x] = 0;\ +} + +// returns an in64_t, negative if error, non-negative if valid drops +#define AMOUNT_TO_DROPS(amount_buffer)\ + (((amount_buffer)[0] >> 7) ? -2 : (\ + ((((uint64_t)((amount_buffer)[0])) & 0xb00111111) << 56) +\ + (((uint64_t)((amount_buffer)[1])) << 48) +\ + (((uint64_t)((amount_buffer)[2])) << 40) +\ + (((uint64_t)((amount_buffer)[3])) << 32) +\ + (((uint64_t)((amount_buffer)[4])) << 24) +\ + (((uint64_t)((amount_buffer)[5])) << 16) +\ + (((uint64_t)((amount_buffer)[6])) << 8) +\ + (((uint64_t)((amount_buffer)[7]))))) + +#define SUB_OFFSET(x) ((int32_t)(x >> 32)) +#define SUB_LENGTH(x) ((int32_t)(x & 0xFFFFFFFFULL)) + +// when using this macro buf1len may be dynamic but buf2len must be static +// provide n >= 1 to indicate how many times the macro will be hit on the line of code +// e.g. if it is in a loop that loops 10 times n = 10 + +#define BUFFER_EQUAL_GUARD(output, buf1, buf1len, buf2, buf2len, n)\ +{\ + output = ((buf1len) == (buf2len) ? 1 : 0);\ + for (int x = 0; GUARDM( (buf2len) * (n), 1 ), output && x < (buf2len);\ + ++x)\ + output = *(((uint8_t*)(buf1)) + x) == *(((uint8_t*)(buf2)) + x);\ +} + +#define BUFFER_SWAP(x,y)\ +{\ + uint8_t* z = x;\ + x = y;\ + y = z;\ +} + +#define ACCOUNT_COMPARE(compare_result, buf1, buf2)\ +{\ + compare_result = 0;\ + for (int i = 0; GUARD(20), i < 20; ++i)\ + {\ + if (buf1[i] > buf2[i])\ + {\ + compare_result = 1;\ + break;\ + }\ + else if (buf1[i] < buf2[i])\ + {\ + compare_result = -1;\ + break;\ + }\ + }\ +} + +#define BUFFER_EQUAL_STR_GUARD(output, buf1, buf1len, str, n)\ + BUFFER_EQUAL_GUARD(output, buf1, buf1len, str, (sizeof(str)-1), n) + +#define BUFFER_EQUAL_STR(output, buf1, buf1len, str)\ + BUFFER_EQUAL_GUARD(output, buf1, buf1len, str, (sizeof(str)-1), 1) + +#define BUFFER_EQUAL(output, buf1, buf2, compare_len)\ + BUFFER_EQUAL_GUARD(output, buf1, compare_len, buf2, compare_len, 1) + +#define UINT16_TO_BUF(buf_raw, i)\ +{\ + unsigned char* buf = (unsigned char*)buf_raw;\ + buf[0] = (((uint64_t)i) >> 8) & 0xFFUL;\ + buf[1] = (((uint64_t)i) >> 0) & 0xFFUL;\ +} + +#define UINT16_FROM_BUF(buf)\ + (((uint64_t)((buf)[0]) << 8) +\ + ((uint64_t)((buf)[1]) << 0)) + +#define UINT32_TO_BUF(buf_raw, i)\ +{\ + unsigned char* buf = (unsigned char*)buf_raw;\ + buf[0] = (((uint64_t)i) >> 24) & 0xFFUL;\ + buf[1] = (((uint64_t)i) >> 16) & 0xFFUL;\ + buf[2] = (((uint64_t)i) >> 8) & 0xFFUL;\ + buf[3] = (((uint64_t)i) >> 0) & 0xFFUL;\ +} + + +#define UINT32_FROM_BUF(buf)\ + (((uint64_t)((buf)[0]) << 24) +\ + ((uint64_t)((buf)[1]) << 16) +\ + ((uint64_t)((buf)[2]) << 8) +\ + ((uint64_t)((buf)[3]) << 0)) + +#define UINT64_TO_BUF(buf_raw, i)\ +{\ + unsigned char* buf = (unsigned char*)buf_raw;\ + buf[0] = (((uint64_t)i) >> 56) & 0xFFUL;\ + buf[1] = (((uint64_t)i) >> 48) & 0xFFUL;\ + buf[2] = (((uint64_t)i) >> 40) & 0xFFUL;\ + buf[3] = (((uint64_t)i) >> 32) & 0xFFUL;\ + buf[4] = (((uint64_t)i) >> 24) & 0xFFUL;\ + buf[5] = (((uint64_t)i) >> 16) & 0xFFUL;\ + buf[6] = (((uint64_t)i) >> 8) & 0xFFUL;\ + buf[7] = (((uint64_t)i) >> 0) & 0xFFUL;\ +} + + +#define UINT64_FROM_BUF(buf)\ + (((uint64_t)((buf)[0]) << 56) +\ + ((uint64_t)((buf)[1]) << 48) +\ + ((uint64_t)((buf)[2]) << 40) +\ + ((uint64_t)((buf)[3]) << 32) +\ + ((uint64_t)((buf)[4]) << 24) +\ + ((uint64_t)((buf)[5]) << 16) +\ + ((uint64_t)((buf)[6]) << 8) +\ + ((uint64_t)((buf)[7]) << 0)) + + +#define INT64_FROM_BUF(buf)\ + ((((uint64_t)((buf)[0] & 0x7FU) << 56) +\ + ((uint64_t)((buf)[1]) << 48) +\ + ((uint64_t)((buf)[2]) << 40) +\ + ((uint64_t)((buf)[3]) << 32) +\ + ((uint64_t)((buf)[4]) << 24) +\ + ((uint64_t)((buf)[5]) << 16) +\ + ((uint64_t)((buf)[6]) << 8) +\ + ((uint64_t)((buf)[7]) << 0)) * (buf[0] & 0x80U ? -1 : 1)) + +#define INT64_TO_BUF(buf_raw, i)\ +{\ + unsigned char* buf = (unsigned char*)buf_raw;\ + buf[0] = (((uint64_t)i) >> 56) & 0x7FUL;\ + buf[1] = (((uint64_t)i) >> 48) & 0xFFUL;\ + buf[2] = (((uint64_t)i) >> 40) & 0xFFUL;\ + buf[3] = (((uint64_t)i) >> 32) & 0xFFUL;\ + buf[4] = (((uint64_t)i) >> 24) & 0xFFUL;\ + buf[5] = (((uint64_t)i) >> 16) & 0xFFUL;\ + buf[6] = (((uint64_t)i) >> 8) & 0xFFUL;\ + buf[7] = (((uint64_t)i) >> 0) & 0xFFUL;\ + if (i < 0) buf[0] |= 0x80U;\ +} + +#define ttPAYMENT 0 +#define ttCHECK_CREATE 16 +#define ttNFT_ACCEPT_OFFER 29 +#define ttHOOK_SET 22 +#define tfCANONICAL 0x80000000UL + +#define atACCOUNT 1U +#define atOWNER 2U +#define atDESTINATION 3U +#define atISSUER 4U +#define atAUTHORIZE 5U +#define atUNAUTHORIZE 6U +#define atTARGET 7U +#define atREGULARKEY 8U +#define atPSEUDOCALLBACK 9U + +#define amAMOUNT 1U +#define amBALANCE 2U +#define amLIMITAMOUNT 3U +#define amTAKERPAYS 4U +#define amTAKERGETS 5U +#define amLOWLIMIT 6U +#define amHIGHLIMIT 7U +#define amFEE 8U +#define amSENDMAX 9U +#define amDELIVERMIN 10U +#define amMINIMUMOFFER 16U +#define amRIPPLEESCROW 17U +#define amDELIVEREDAMOUNT 18U + +/** + * RH NOTE -- PAY ATTENTION + * + * ALL 'ENCODE' MACROS INCREMENT BUF_OUT + * THIS IS TO MAKE CHAINING EASY + * BUF_OUT IS A SACRIFICIAL POINTER + * + * 'ENCODE' MACROS WITH CONSTANTS HAVE + * ALIASING TO ASSIST YOU WITH ORDER + * _TYPECODE_FIELDCODE_ENCODE_MACRO + * TO PRODUCE A SERIALIZED OBJECT + * IN CANONICAL FORMAT YOU MUST ORDER + * FIRST BY TYPE CODE THEN BY FIELD CODE + * + * ALL 'PREPARE' MACROS PRESERVE POINTERS + * + **/ + + +#define ENCODE_TL_SIZE 49 +#define ENCODE_TL(buf_out, tlamt, amount_type)\ +{\ + uint8_t uat = amount_type; \ + buf_out[0] = 0x60U +(uat & 0x0FU ); \ + for (int i = 1; GUARDM(48, 1), i < 49; ++i)\ + buf_out[i] = tlamt[i-1];\ + buf_out += ENCODE_TL_SIZE;\ +} +#define _06_XX_ENCODE_TL(buf_out, drops, amount_type )\ + ENCODE_TL(buf_out, drops, amount_type ); +#define ENCODE_TL_AMOUNT(buf_out, drops )\ + ENCODE_TL(buf_out, drops, amAMOUNT ); +#define _06_01_ENCODE_TL_AMOUNT(buf_out, drops )\ + ENCODE_TL_AMOUNT(buf_out, drops ); + + +// Encode drops to serialization format +// consumes 9 bytes +#define ENCODE_DROPS_SIZE 9 +#define ENCODE_DROPS(buf_out, drops, amount_type ) \ + {\ + uint8_t uat = amount_type; \ + uint64_t udrops = drops; \ + buf_out[0] = 0x60U +(uat & 0x0FU ); \ + buf_out[1] = 0b01000000 + (( udrops >> 56 ) & 0b00111111 ); \ + buf_out[2] = (udrops >> 48) & 0xFFU; \ + buf_out[3] = (udrops >> 40) & 0xFFU; \ + buf_out[4] = (udrops >> 32) & 0xFFU; \ + buf_out[5] = (udrops >> 24) & 0xFFU; \ + buf_out[6] = (udrops >> 16) & 0xFFU; \ + buf_out[7] = (udrops >> 8) & 0xFFU; \ + buf_out[8] = (udrops >> 0) & 0xFFU; \ + buf_out += ENCODE_DROPS_SIZE; \ + } + +#define _06_XX_ENCODE_DROPS(buf_out, drops, amount_type )\ + ENCODE_DROPS(buf_out, drops, amount_type ); + +#define ENCODE_DROPS_AMOUNT(buf_out, drops )\ + ENCODE_DROPS(buf_out, drops, amAMOUNT ); +#define _06_01_ENCODE_DROPS_AMOUNT(buf_out, drops )\ + ENCODE_DROPS_AMOUNT(buf_out, drops ); + +#define ENCODE_DROPS_FEE(buf_out, drops )\ + ENCODE_DROPS(buf_out, drops, amFEE ); +#define _06_08_ENCODE_DROPS_FEE(buf_out, drops )\ + ENCODE_DROPS_FEE(buf_out, drops ); + +#define ENCODE_TT_SIZE 3 +#define ENCODE_TT(buf_out, tt )\ + {\ + uint8_t utt = tt;\ + buf_out[0] = 0x12U;\ + buf_out[1] =(utt >> 8 ) & 0xFFU;\ + buf_out[2] =(utt >> 0 ) & 0xFFU;\ + buf_out += ENCODE_TT_SIZE; \ + } +#define _01_02_ENCODE_TT(buf_out, tt)\ + ENCODE_TT(buf_out, tt); + + +#define ENCODE_ACCOUNT_SIZE 22 +#define ENCODE_ACCOUNT(buf_out, account_id, account_type)\ + {\ + uint8_t uat = account_type;\ + buf_out[0] = 0x80U + uat;\ + buf_out[1] = 0x14U;\ + *(uint64_t*)(buf_out + 2) = *(uint64_t*)(account_id + 0);\ + *(uint64_t*)(buf_out + 10) = *(uint64_t*)(account_id + 8);\ + *(uint32_t*)(buf_out + 18) = *(uint32_t*)(account_id + 16);\ + buf_out += ENCODE_ACCOUNT_SIZE;\ + } +#define _08_XX_ENCODE_ACCOUNT(buf_out, account_id, account_type)\ + ENCODE_ACCOUNT(buf_out, account_id, account_type); + +#define ENCODE_ACCOUNT_SRC_SIZE 22 +#define ENCODE_ACCOUNT_SRC(buf_out, account_id)\ + ENCODE_ACCOUNT(buf_out, account_id, atACCOUNT); +#define _08_01_ENCODE_ACCOUNT_SRC(buf_out, account_id)\ + ENCODE_ACCOUNT_SRC(buf_out, account_id); + +#define ENCODE_ACCOUNT_DST_SIZE 22 +#define ENCODE_ACCOUNT_DST(buf_out, account_id)\ + ENCODE_ACCOUNT(buf_out, account_id, atDESTINATION); +#define _08_03_ENCODE_ACCOUNT_DST(buf_out, account_id)\ + ENCODE_ACCOUNT_DST(buf_out, account_id); + +#define ENCODE_ACCOUNT_OWNER_SIZE 22 +#define ENCODE_ACCOUNT_OWNER(buf_out, account_id) \ + ENCODE_ACCOUNT(buf_out, account_id, atOWNER); +#define _08_02_ENCODE_ACCOUNT_OWNER(buf_out, account_id) \ + ENCODE_ACCOUNT_OWNER(buf_out, account_id); + +#define ENCODE_UINT32_COMMON_SIZE 5U +#define ENCODE_UINT32_COMMON(buf_out, i, field)\ + {\ + uint32_t ui = i; \ + uint8_t uf = field; \ + buf_out[0] = 0x20U +(uf & 0x0FU); \ + buf_out[1] =(ui >> 24 ) & 0xFFU; \ + buf_out[2] =(ui >> 16 ) & 0xFFU; \ + buf_out[3] =(ui >> 8 ) & 0xFFU; \ + buf_out[4] =(ui >> 0 ) & 0xFFU; \ + buf_out += ENCODE_UINT32_COMMON_SIZE; \ + } +#define _02_XX_ENCODE_UINT32_COMMON(buf_out, i, field)\ + ENCODE_UINT32_COMMON(buf_out, i, field)\ + +#define ENCODE_UINT32_UNCOMMON_SIZE 6U +#define ENCODE_UINT32_UNCOMMON(buf_out, i, field)\ + {\ + uint32_t ui = i; \ + uint8_t uf = field; \ + buf_out[0] = 0x20U; \ + buf_out[1] = uf; \ + buf_out[2] =(ui >> 24 ) & 0xFFU; \ + buf_out[3] =(ui >> 16 ) & 0xFFU; \ + buf_out[4] =(ui >> 8 ) & 0xFFU; \ + buf_out[5] =(ui >> 0 ) & 0xFFU; \ + buf_out += ENCODE_UINT32_UNCOMMON_SIZE; \ + } +#define _02_XX_ENCODE_UINT32_UNCOMMON(buf_out, i, field)\ + ENCODE_UINT32_UNCOMMON(buf_out, i, field)\ + +#define ENCODE_LLS_SIZE 6U +#define ENCODE_LLS(buf_out, lls )\ + ENCODE_UINT32_UNCOMMON(buf_out, lls, 0x1B ); +#define _02_27_ENCODE_LLS(buf_out, lls )\ + ENCODE_LLS(buf_out, lls ); + +#define ENCODE_FLS_SIZE 6U +#define ENCODE_FLS(buf_out, fls )\ + ENCODE_UINT32_UNCOMMON(buf_out, fls, 0x1A ); +#define _02_26_ENCODE_FLS(buf_out, fls )\ + ENCODE_FLS(buf_out, fls ); + +#define ENCODE_TAG_SRC_SIZE 5 +#define ENCODE_TAG_SRC(buf_out, tag )\ + ENCODE_UINT32_COMMON(buf_out, tag, 0x3U ); +#define _02_03_ENCODE_TAG_SRC(buf_out, tag )\ + ENCODE_TAG_SRC(buf_out, tag ); + +#define ENCODE_TAG_DST_SIZE 5 +#define ENCODE_TAG_DST(buf_out, tag )\ + ENCODE_UINT32_COMMON(buf_out, tag, 0xEU ); +#define _02_14_ENCODE_TAG_DST(buf_out, tag )\ + ENCODE_TAG_DST(buf_out, tag ); + +#define ENCODE_SEQUENCE_SIZE 5 +#define ENCODE_SEQUENCE(buf_out, sequence )\ + ENCODE_UINT32_COMMON(buf_out, sequence, 0x4U ); +#define _02_04_ENCODE_SEQUENCE(buf_out, sequence )\ + ENCODE_SEQUENCE(buf_out, sequence ); + +#define ENCODE_FLAGS_SIZE 5 +#define ENCODE_FLAGS(buf_out, tag )\ + ENCODE_UINT32_COMMON(buf_out, tag, 0x2U ); +#define _02_02_ENCODE_FLAGS(buf_out, tag )\ + ENCODE_FLAGS(buf_out, tag ); + +#define ENCODE_SIGNING_PUBKEY_SIZE 35 +#define ENCODE_SIGNING_PUBKEY(buf_out, pkey )\ + {\ + buf_out[0] = 0x73U;\ + buf_out[1] = 0x21U;\ + *(uint64_t*)(buf_out + 2) = *(uint64_t*)(pkey + 0);\ + *(uint64_t*)(buf_out + 10) = *(uint64_t*)(pkey + 8);\ + *(uint64_t*)(buf_out + 18) = *(uint64_t*)(pkey + 16);\ + *(uint64_t*)(buf_out + 26) = *(uint64_t*)(pkey + 24);\ + buf[34] = pkey[32];\ + buf_out += ENCODE_SIGNING_PUBKEY_SIZE;\ + } + +#define _07_03_ENCODE_SIGNING_PUBKEY(buf_out, pkey )\ + ENCODE_SIGNING_PUBKEY(buf_out, pkey ); + +#define ENCODE_SIGNING_PUBKEY_NULL_SIZE 35 +#define ENCODE_SIGNING_PUBKEY_NULL(buf_out )\ + {\ + buf_out[0] = 0x73U;\ + buf_out[1] = 0x21U;\ + *(uint64_t*)(buf_out+2) = 0;\ + *(uint64_t*)(buf_out+10) = 0;\ + *(uint64_t*)(buf_out+18) = 0;\ + *(uint64_t*)(buf_out+25) = 0;\ + buf_out += ENCODE_SIGNING_PUBKEY_NULL_SIZE;\ + } + +#define _07_03_ENCODE_SIGNING_PUBKEY_NULL(buf_out )\ + ENCODE_SIGNING_PUBKEY_NULL(buf_out ); + + +#define _0E_0E_ENCODE_HOOKOBJ(buf_out, hhash)\ +{\ + uint8_t* hook0 = (hhash);\ + *buf_out++ = 0xEEU; /* hook obj start */ \ + if (hook0 == 0) /* noop */\ + {\ + /* do nothing */ \ + }\ + else\ + {\ + *buf_out++ = 0x22U; /* flags = override */\ + *buf_out++ = 0x00U;\ + *buf_out++ = 0x00U;\ + *buf_out++ = 0x00U;\ + *buf_out++ = 0x01U;\ + if (hook0 == 0xFFFFFFFFUL) /* delete operation */ \ + {\ + *buf_out++ = 0x7BU; /* empty createcode */ \ + *buf_out++ = 0x00U;\ + }\ + else\ + {\ + *buf_out++ = 0x1FU; /* HookHash */\ + *buf_out++ = *hook0++; *buf_out++ = *hook0++; *buf_out++ = *hook0++; *buf_out++ = *hook0++; \ + *buf_out++ = *hook0++; *buf_out++ = *hook0++; *buf_out++ = *hook0++; *buf_out++ = *hook0++; \ + *buf_out++ = *hook0++; *buf_out++ = *hook0++; *buf_out++ = *hook0++; *buf_out++ = *hook0++; \ + *buf_out++ = *hook0++; *buf_out++ = *hook0++; *buf_out++ = *hook0++; *buf_out++ = *hook0++; \ + }\ + }\ + *buf_out++ = 0xE1U;\ +} + +#define PREPARE_HOOKSET(buf_out_master, maxlen, hash0, hash1, hash2, hash3, sizeout)\ + {\ + uint8_t* buf_out = (buf_out_master); \ + uint8_t acc[20]; \ + uint32_t cls = (uint32_t)ledger_seq(); \ + hook_account(SBUF(acc)); \ + _01_02_ENCODE_TT (buf_out, ttHOOK_SET ); \ + _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 ); \ + uint8_t* fee_ptr = buf_out; \ + _06_08_ENCODE_DROPS_FEE (buf_out, 0 ); \ + _07_03_ENCODE_SIGNING_PUBKEY_NULL (buf_out ); \ + _08_01_ENCODE_ACCOUNT_SRC (buf_out, acc ); \ + uint32_t remaining_size = (maxlen) - (buf_out - (buf_out_master)); \ + int64_t edlen = etxn_details((uint32_t)buf_out, remaining_size); \ + buf_out += edlen; \ + *buf_out++ = 0xFBU; /* hook array start */ \ + _0E_0E_ENCODE_HOOKOBJ (buf_out, hash0); \ + _0E_0E_ENCODE_HOOKOBJ (buf_out, hash1); \ + _0E_0E_ENCODE_HOOKOBJ (buf_out, hash2); \ + _0E_0E_ENCODE_HOOKOBJ (buf_out, hash3); \ + *buf_out++ = 0xF1U; /* hook array end */ \ + sizeout = (buf_out - (buf_out_master)); \ + int64_t fee = etxn_fee_base(buf_out_master, sizeout); \ + _06_08_ENCODE_DROPS_FEE (fee_ptr, fee ); \ + } + +#ifdef HAS_CALLBACK +#define PREPARE_PAYMENT_SIMPLE_SIZE 270U +#else +#define PREPARE_PAYMENT_SIMPLE_SIZE 248U +#endif + +#define PREPARE_PAYMENT_SIMPLE(buf_out_master, drops_amount_raw, to_address, dest_tag_raw, src_tag_raw)\ + {\ + uint8_t* buf_out = buf_out_master;\ + uint8_t acc[20];\ + uint64_t drops_amount = (drops_amount_raw);\ + uint32_t dest_tag = (dest_tag_raw);\ + uint32_t src_tag = (src_tag_raw);\ + uint32_t cls = (uint32_t)ledger_seq();\ + hook_account(SBUF(acc));\ + _01_02_ENCODE_TT (buf_out, ttPAYMENT ); /* uint16 | size 3 */ \ + _02_02_ENCODE_FLAGS (buf_out, tfCANONICAL ); /* uint32 | size 5 */ \ + _02_03_ENCODE_TAG_SRC (buf_out, src_tag ); /* uint32 | size 5 */ \ + _02_04_ENCODE_SEQUENCE (buf_out, 0 ); /* uint32 | size 5 */ \ + _02_14_ENCODE_TAG_DST (buf_out, dest_tag ); /* 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 */ \ + _06_01_ENCODE_DROPS_AMOUNT (buf_out, drops_amount ); /* amount | size 9 */ \ + 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 */ \ + _08_01_ENCODE_ACCOUNT_SRC (buf_out, acc ); /* account | size 22 */ \ + _08_03_ENCODE_ACCOUNT_DST (buf_out, to_address ); /* account | size 22 */ \ + int64_t edlen = etxn_details((uint32_t)buf_out, PREPARE_PAYMENT_SIMPLE_SIZE); /* emitdet | size 1?? */ \ + int64_t fee = etxn_fee_base(buf_out_master, PREPARE_PAYMENT_SIMPLE_SIZE); \ + _06_08_ENCODE_DROPS_FEE (fee_ptr, fee ); \ + } + +#ifdef HAS_CALLBACK +#define PREPARE_PAYMENT_SIMPLE_TRUSTLINE_SIZE 309 +#else +#define PREPARE_PAYMENT_SIMPLE_TRUSTLINE_SIZE 287 +#endif +#define PREPARE_PAYMENT_SIMPLE_TRUSTLINE(buf_out_master, tlamt, to_address, dest_tag_raw, src_tag_raw)\ + {\ + uint8_t* buf_out = buf_out_master;\ + uint8_t acc[20];\ + uint32_t dest_tag = (dest_tag_raw);\ + uint32_t src_tag = (src_tag_raw);\ + uint32_t cls = (uint32_t)ledger_seq();\ + hook_account(SBUF(acc));\ + _01_02_ENCODE_TT (buf_out, ttPAYMENT ); /* uint16 | size 3 */ \ + _02_02_ENCODE_FLAGS (buf_out, tfCANONICAL ); /* uint32 | size 5 */ \ + _02_03_ENCODE_TAG_SRC (buf_out, src_tag ); /* uint32 | size 5 */ \ + _02_04_ENCODE_SEQUENCE (buf_out, 0 ); /* uint32 | size 5 */ \ + _02_14_ENCODE_TAG_DST (buf_out, dest_tag ); /* 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 */ \ + _06_01_ENCODE_TL_AMOUNT (buf_out, tlamt ); /* amount | size 48 */ \ + 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 */ \ + _08_01_ENCODE_ACCOUNT_SRC (buf_out, acc ); /* account | size 22 */ \ + _08_03_ENCODE_ACCOUNT_DST (buf_out, to_address ); /* account | size 22 */ \ + etxn_details((uint32_t)buf_out, PREPARE_PAYMENT_SIMPLE_TRUSTLINE_SIZE); /* emitdet | size 1?? */ \ + int64_t fee = etxn_fee_base(buf_out_master, PREPARE_PAYMENT_SIMPLE_TRUSTLINE_SIZE); \ + _06_08_ENCODE_DROPS_FEE (fee_ptr, fee ); \ + } + + + +#endif + +