diff --git a/.env b/.env new file mode 100644 index 000000000..884cd0f98 --- /dev/null +++ b/.env @@ -0,0 +1 @@ +C2WASM_CLI_HOST=http://localhost:9000 diff --git a/hook/genesis/callback.c b/hook/genesis/callback.c new file mode 100644 index 000000000..fb110161c --- /dev/null +++ b/hook/genesis/callback.c @@ -0,0 +1,127 @@ +/** + * Payment Txn + */ +#include "hookapi.h" +#include + +// clang-format off +uint8_t txn[305] = +{ +/* size,upto */ +/* 3, 0 */ 0x12U, 0x00U, 0x00U, /* tt = Payment */ +/* 5, 3*/ 0x22U, 0x80U, 0x00U, 0x00U, 0x00U, /* flags = tfCanonical */ +/* 5, 8 */ 0x24U, 0x00U, 0x00U, 0x00U, 0x00U, /* sequence = 0 */ +/* 5, 13 */ 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, /* dtag, flipped */ +/* 6, 18 */ 0x20U, 0x1AU, 0x00U, 0x00U, 0x00U, 0x00U, /* first ledger seq */ +/* 6, 24 */ 0x20U, 0x1BU, 0x00U, 0x00U, 0x00U, 0x00U, /* last ledger seq */ +/* 49, 30 */ 0x61U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, /* amount field 9 or 49 bytes */ + 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, + 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, + 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, + 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, + 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99U, 0x99, +/* 9, 79 */ 0x68U, 0x40U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, /* fee */ +/* 35, 88 */ 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, /* pubkey */ +/* 22,123 */ 0x81U, 0x14U, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* src acc */ +/* 22,145 */ 0x83U, 0x14U, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* dst acc */ +/* 138,167 */ /* emit details */ +/* 0,305 */ +}; +// clang-format on + +// TX BUILDER +#define FLS_OUT (txn + 20U) +#define LLS_OUT (txn + 26U) +#define DTAG_OUT (txn + 14U) +#define AMOUNT_OUT (txn + 30U) +#define FEE_OUT (txn + 80U) +#define HOOK_ACC (txn + 125U) +#define OTX_ACC (txn + 147U) +#define EMIT_OUT (txn + 167U) + +int64_t cbak(uint32_t f) +{ + uint8_t f_buf[4]; + UINT32_TO_BUF(f_buf, f); + accept(SBUF(f_buf), __LINE__); + return 0; +} + +int64_t hook(uint32_t reserved) +{ + + TRACESTR("callback.c: Called."); + + // ACCOUNT: Hook Account + uint8_t hook_acc[20]; + hook_account(HOOK_ACC, 20); + + // TXN: PREPARE: Init + etxn_reserve(2); + + for (int64_t i = 0; GUARD(2), i < 2; i++) + { + TRACEVAR(i); + switch (i) + { + case 0: + util_accid(OTX_ACC, 20, SBUF("rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK")); + case 1: + util_accid(OTX_ACC, 20, SBUF("rH4KEcG9dEwGwpn6AyoWK9cZPLL4RLSmWW")); + default: + break; + } + + uint32_t fls = (uint32_t)ledger_seq() + 1; + *((uint32_t *)(FLS_OUT)) = FLIP_ENDIAN(fls); + + // TXN PREPARE: LastLedgerSequense + uint32_t lls = fls + 4; + *((uint32_t *)(LLS_OUT)) = FLIP_ENDIAN(lls); + + // TXN PREPARE: Amount + uint64_t drops = 1000000; + uint8_t *b = AMOUNT_OUT + 1; + *b++ = 0b01000000 + ((drops >> 56) & 0b00111111); + *b++ = (drops >> 48) & 0xFFU; + *b++ = (drops >> 40) & 0xFFU; + *b++ = (drops >> 32) & 0xFFU; + *b++ = (drops >> 24) & 0xFFU; + *b++ = (drops >> 16) & 0xFFU; + *b++ = (drops >> 8) & 0xFFU; + *b++ = (drops >> 0) & 0xFFU; + + // TXN PREPARE: Dest Tag <- Source Tag + if (otxn_field(DTAG_OUT, 4, sfSourceTag) == 4) + *(DTAG_OUT - 1) = 0x2EU; + + // TXN PREPARE: Emit Metadata + etxn_details(EMIT_OUT, 138U); + + // TXN PREPARE: Fee + { + int64_t fee = etxn_fee_base(SBUF(txn)); + uint8_t *b = FEE_OUT; + *b++ = 0b01000000 + ((fee >> 56) & 0b00111111); + *b++ = (fee >> 48) & 0xFFU; + *b++ = (fee >> 40) & 0xFFU; + *b++ = (fee >> 32) & 0xFFU; + *b++ = (fee >> 24) & 0xFFU; + *b++ = (fee >> 16) & 0xFFU; + *b++ = (fee >> 8) & 0xFFU; + *b++ = (fee >> 0) & 0xFFU; + } + + TRACEHEX(txn); // <- final tx blob + + // TXN: Emit/Send Txn + uint8_t emithash[32]; + int64_t emit_result = emit(SBUF(emithash), SBUF(txn)); + TRACEVAR(emit_result); + } + + accept(SBUF("callback.c: Successful."), __LINE__); + + // unreachable + return 0; +} \ No newline at end of file diff --git a/hook/genesis/tsh.c b/hook/genesis/tsh.c new file mode 100644 index 000000000..6cb176437 --- /dev/null +++ b/hook/genesis/tsh.c @@ -0,0 +1,32 @@ +#include "hookapi.h" + +int64_t hook(uint32_t reserved) { + TRACESTR("tsh.c: Start."); + + uint8_t aaw_buffer[1]; + if (otxn_param(SBUF(aaw_buffer), "AAW", 3) == 1) + hook_again(); + + switch (reserved) + { + case 0: + TRACESTR("tsh.c: Strong. Execute BEFORE transaction is applied to ledger"); + break; + case 1: + TRACESTR("tsh.c: Weak. Execute AFTER transaction is applied to ledger"); + break; + case 2: + TRACESTR("tsh.c: Weak Again. Execute AFTER transaction is applied to ledger"); + break; + default: + break; + } + + TRACESTR("tsh.c: End."); + uint8_t r_buf[4]; + UINT32_TO_BUF(r_buf, reserved); + accept(SBUF(r_buf), __LINE__); + _g(1,1); + // unreachable + return 0; +} \ No newline at end of file diff --git a/hook/macro.h b/hook/macro.h index a8f8d7cf9..f25c21fd3 100644 --- a/hook/macro.h +++ b/hook/macro.h @@ -9,6 +9,34 @@ #ifndef HOOKMACROS_INCLUDED #define HOOKMACROS_INCLUDED 1 +#define DONEEMPTY()\ + accept(0,0,__LINE__) + +#define DONEMSG(msg)\ + accept(msg, sizeof(msg),__LINE__) + +#define DONE(x)\ + accept(SVAR(x),(uint32_t)__LINE__); + + +#define SVAR(x) &x, sizeof(x) + +#define ASSERT(x)\ +{\ + if (!(x))\ + rollback(0,0,__LINE__);\ +} + +#define NOPE(x)\ +{\ + return rollback((x), sizeof(x), __LINE__);\ +} + +#define FLIP_ENDIAN(n) ((uint32_t) (((n & 0xFFU) << 24U) | \ + ((n & 0xFF00U) << 8U) | \ + ((n & 0xFF0000U) >> 8U) | \ + ((n & 0xFF000000U) >> 24U))) + #ifdef NDEBUG #define DEBUG 0 @@ -138,6 +166,18 @@ int out_len = 0;\ *(((uint64_t*)(buf1)) + 2) == *(((uint64_t*)(buf2)) + 2) &&\ *(((uint64_t*)(buf1)) + 3) == *(((uint64_t*)(buf2)) + 3)) +#define BUFFER_EQUAL_64(buf1, buf2) \ + ( \ + (*((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)) \ + ) + // 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 @@ -483,11 +523,16 @@ int out_len = 0;\ #define _07_03_ENCODE_SIGNING_PUBKEY(buf_out, pkey )\ ENCODE_SIGNING_PUBKEY(buf_out, pkey ); -#define ENCODE_SIGNING_PUBKEY_NULL_SIZE 2 +#define ENCODE_SIGNING_PUBKEY_NULL_SIZE 35 #define ENCODE_SIGNING_PUBKEY_NULL(buf_out )\ {\ - *buf_out++ = 0x73U;\ - *buf_out++ = 0x00U;\ + 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 )\ @@ -516,8 +561,7 @@ int out_len = 0;\ }\ else\ {\ - *buf_out++ = 0x50U; /* HookHash */\ - *buf_out++ = 0x1FU;\ + *buf_out++ = 0x1FU; /* HookHash */\ uint64_t* d = (uint64_t*)buf_out;\ uint64_t* s = (uint64_t*)hook0;\ *d++ = *s++;\ diff --git a/hook/wasm_from_carray.py b/hook/wasm_from_carray.py new file mode 100644 index 000000000..c1d1d4bb7 --- /dev/null +++ b/hook/wasm_from_carray.py @@ -0,0 +1,35 @@ +import re +import sys + +# Check if the file name is provided as a command-line argument +if len(sys.argv) < 2: + print("Usage: python script.py ") + sys.exit(1) + +# Read the .h file content +file_name = sys.argv[1] # Get the file name from command-line arguments +try: + with open(file_name, "r") as file: + content = file.read() + + # Find the C array using a regular expression + match = re.search(r'\{(.+?)\};', content, re.DOTALL) + if match: + c_array = match.group(1) + + # Extract the hexadecimal values and remove the 'U' suffix + hex_values = re.findall(r'0x([0-9A-F]+)U', c_array) + + # Convert the list of hex values to a byte array + byte_array = bytearray.fromhex(''.join(hex_values)) + + # Convert the byte array to a hex string + hex_string = byte_array.hex().upper() + + print(hex_string) + else: + print("C array not found in the file.") +except FileNotFoundError: + print(f"File not found: {file_name}") +except Exception as e: + print(f"An error occurred: {e}") diff --git a/hook/wasm_to_carray.py b/hook/wasm_to_carray.py new file mode 100644 index 000000000..7bc0ed228 --- /dev/null +++ b/hook/wasm_to_carray.py @@ -0,0 +1,33 @@ +import sys +import binascii + +# Check if the name is provided as a command-line argument +if len(sys.argv) != 2: + print("Usage: python script.py ") + sys.exit(1) + +name: str = sys.argv[1] + +try: + with open(f"build/{name}.wasm", "rb") as file: + wasm = file.read() +except FileNotFoundError: + print(f"Error: File build/{name}.wasm not found.") + sys.exit(1) + +data = wasm.hex().upper() + +# Convert hexadecimal data to bytes +binary_data = binascii.unhexlify(data) + +# Generate C array +c_array = ', '.join([f"0x{b:02X}U" for b in binary_data]) + +try: + with open(f"hook/{name}_a.h", "w") as file: + file.write(f'static const std::vector {name.capitalize()}Hook = {"{"}') + file.write(c_array) + file.write("};\n") +except IOError as e: + print(f"Error: Unable to write to file {name}_a.h. {e}") + sys.exit(1) \ No newline at end of file diff --git a/hook/wasm_verify.py b/hook/wasm_verify.py new file mode 100644 index 000000000..e1b5031bb --- /dev/null +++ b/hook/wasm_verify.py @@ -0,0 +1,46 @@ +import re +import sys + +# Function to extract hexadecimal values from a C array in a .h file +def extract_hex_values(file_name): + try: + with open(file_name, "r") as file: + content = file.read() + except FileNotFoundError: + print(f"File {file_name} not found.") + return None + + # Find the C array using a regular expression + match = re.search(r'\{(.+?)\};', content, re.DOTALL) + if match: + c_array = match.group(1) + + # Extract the hexadecimal values and remove the 'U' suffix + hex_values = re.findall(r'0x([0-9A-F]+)U', c_array) + return hex_values + else: + print(f"C array not found in the file {file_name}.") + return None + +# Check if the correct number of arguments are provided +if len(sys.argv) != 3: + print("Usage: python script.py ") + sys.exit(1) + +# File names of the .h files to compare +file_name1 = sys.argv[1] +file_name2 = sys.argv[2] + +# Extract hexadecimal values from both files +hex_values1 = extract_hex_values(file_name1) +hex_values2 = extract_hex_values(file_name2) + +print(len(hex_values1)) +print(len(hex_values2)) + +# Compare the hexadecimal values if both files have been read successfully +if hex_values1 is not None and hex_values2 is not None: + if hex_values1 == hex_values2: + print("The hexadecimal values in both files match.") + else: + print("The hexadecimal values in both files do not match.") \ No newline at end of file