Skip to content

Commit

Permalink
Add Soroban support. (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
overcat authored Apr 25, 2024
1 parent dc17619 commit ae99370
Show file tree
Hide file tree
Showing 971 changed files with 4,630 additions and 1,051 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@ tests_common_js/node_modules/
fuzz/build
fuzz/testcases/
tests_generate_binary/node_modules/
.DS_Store
.DS_Store
.idea
installer/
linkermap.html
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
{
"files.associations": {
"*.h": "c",
"random": "c"
"random": "c",
"array": "c",
"string": "c",
"string_view": "c"
},
"C_Cpp.clang_format_path": "/usr/bin/clang-format",
"editor.formatOnSave": true
Expand Down
12 changes: 1 addition & 11 deletions fuzz/fuzz_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,8 @@
#include "stellar/parser.h"
#include "stellar/formatter.h"

/*
* Captions don't scroll so there is no use in having more capacity than can fit on screen at once.
*/
#define DETAIL_CAPTION_MAX_LENGTH 20

/*
* DETAIL_VALUE_MAX_LENGTH value of 89 is due to the maximum length of managed data value which can
* be 64 bytes long. Managed data values are displayed as base64 encoded strings, which are
* 4*((len+2)/3) characters long. (An additional slot is required for the end-of-string character of
* course)
*/
#define DETAIL_VALUE_MAX_LENGTH 89
#define DETAIL_VALUE_MAX_LENGTH 104

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
envelope_t envelope;
Expand Down
1,245 changes: 766 additions & 479 deletions libstellar/formatter.c

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions libstellar/include/stellar/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,23 @@ bool parse_transaction_operation(const uint8_t *data,
size_t data_len,
envelope_t *envelope,
uint8_t operation_index);

bool parse_soroban_authorization_envelope(const uint8_t *data,
size_t data_len,
envelope_t *envelope);

bool parse_bool(buffer_t *buffer, bool *b);

bool parse_uint64(buffer_t *buffer, uint64_t *n);

bool parse_int64(buffer_t *buffer, int64_t *n);

bool parse_scv_symbol(buffer_t *buffer, scv_symbol_t *symbol);

bool parse_scv_string(buffer_t *buffer, scv_string_t *string);

bool buffer_read32(buffer_t *buffer, uint32_t *n);

bool parse_sc_address(buffer_t *buffer, sc_address_t *sc_address);

bool read_scval_advance(buffer_t *buffer);
24 changes: 23 additions & 1 deletion libstellar/include/stellar/printer.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,26 @@ bool print_summary(const char *in,
uint8_t num_chars_l,
uint8_t num_chars_r);

bool print_time(uint64_t seconds, char *out, size_t out_len);
bool print_time(uint64_t seconds, char *out, size_t out_len);

bool print_int32(const uint8_t *value, char *out, size_t out_len, bool add_separator);

bool print_uint32(const uint8_t *value, char *out, size_t out_len, bool add_separator);

bool print_int64(const uint8_t *value, char *out, size_t out_len, bool add_separator);

bool print_uint64(const uint8_t *value, char *out, size_t out_len, bool add_separator);

bool print_int128(const uint8_t *value, char *out, size_t out_len, bool add_separator);

bool print_uint128(const uint8_t *value, char *out, size_t out_len, bool add_separator);

bool print_int256(const uint8_t *value, char *out, size_t out_len, bool add_separator);

bool print_uint256(const uint8_t *value, char *out, size_t out_len, bool add_separator);

bool print_scv_symbol(const scv_symbol_t *scv_symbol, char *out, size_t out_len);

bool print_scv_string(const scv_string_t *scv_string, char *out, size_t out_len);

bool add_separator_to_number(char *out, size_t out_len);
26 changes: 26 additions & 0 deletions libstellar/include/stellar/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#define DATA_NAME_MAX_SIZE 64
#define DATA_VALUE_MAX_SIZE 64
#define HOME_DOMAIN_MAX_SIZE 32
#define SCV_SYMBOL_MAX_SIZE 32

#define NETWORK_TYPE_PUBLIC 0
#define NETWORK_TYPE_TEST 1
Expand Down Expand Up @@ -512,6 +513,16 @@ typedef enum SCValType {
SCV_LEDGER_KEY_NONCE = 21
} sc_val_type_t;

typedef struct {
uint32_t size; // the max size of the symbol is SCV_SYMBOL_MAX_SIZE
const uint8_t *symbol;
} scv_symbol_t;

typedef struct {
uint32_t size; // dont include the null terminator
const uint8_t *string;
} scv_string_t;

typedef enum { SC_ADDRESS_TYPE_ACCOUNT = 0, SC_ADDRESS_TYPE_CONTRACT = 1 } sc_address_type_t;

typedef struct {
Expand All @@ -531,6 +542,7 @@ typedef struct {
const uint8_t *name;
} function;
size_t parameters_position;
uint8_t parameters_length;
} invoke_contract_args_t;

typedef enum {
Expand Down Expand Up @@ -558,6 +570,13 @@ typedef enum {
SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN = 1
} soroban_authorization_function_type_t;

typedef struct {
uint64_t nonce;
uint32_t signature_expiration_ledger;
soroban_authorization_function_type_t function_type;
invoke_contract_args_t invoke_contract_args;
} soroban_authorization_t;

// ************************* Soroban ************************* //

typedef struct {
Expand Down Expand Up @@ -649,6 +668,13 @@ typedef struct {
typedef struct {
transaction_details_t tx;
fee_bump_transaction_details_t fee_bump_tx;
} tx_details_t;

typedef struct {
union {
tx_details_t tx_details;
soroban_authorization_t soroban_authorization;
};
envelope_type_t type;
uint8_t network;
} envelope_t;
143 changes: 124 additions & 19 deletions libstellar/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
if (!(x)) return false; \
}

static bool read_scval_advance(buffer_t *buffer);
bool read_scval_advance(buffer_t *buffer);

static bool buffer_advance(buffer_t *buffer, size_t num_bytes) {
return buffer_seek_cur(buffer, num_bytes);
}

static bool buffer_read32(buffer_t *buffer, uint32_t *n) {
bool buffer_read32(buffer_t *buffer, uint32_t *n) {
return buffer_read_u32(buffer, n, BE);
}

Expand Down Expand Up @@ -46,6 +46,32 @@ static bool buffer_read_bytes(buffer_t *buffer, uint8_t *out, size_t size) {
return true;
}

static int64_t read_i64_be(const uint8_t *ptr, size_t offset) {
int64_t result = 0;
for (int i = 0; i < 8; i++) {
result = (result << 8) | ptr[offset + i];
}
return result;
}

bool parse_uint64(buffer_t *buffer, uint64_t *n) {
PARSER_CHECK(buffer_read64(buffer, n))
return true;
}

bool parse_bool(buffer_t *buffer, bool *b) {
return buffer_read_bool(buffer, b);
}

bool parse_int64(buffer_t *buffer, int64_t *n) {
if (!buffer_can_read(buffer, 8)) {
*n = 0;
return false;
}
*n = read_i64_be(buffer->ptr, buffer->offset);
return buffer_seek_cur(buffer, 8);
}

size_t num_bytes(size_t size) {
size_t remainder = size % 4;
if (remainder == 0) {
Expand Down Expand Up @@ -110,6 +136,24 @@ static bool parse_optional_type(buffer_t *buffer, xdr_type_reader reader, void *
}
}

bool parse_scv_symbol(buffer_t *buffer, scv_symbol_t *symbol) {
if (!buffer_read32(buffer, &symbol->size) || symbol->size > SCV_SYMBOL_MAX_SIZE) {
return false;
}
PARSER_CHECK(buffer_can_read(buffer, num_bytes(symbol->size)))
symbol->symbol = buffer->ptr + buffer->offset;
return true;
}

bool parse_scv_string(buffer_t *buffer, scv_string_t *string) {
if (!buffer_read32(buffer, &string->size)) {
return false;
}
PARSER_CHECK(buffer_can_read(buffer, num_bytes(string->size)))
string->string = buffer->ptr + buffer->offset;
return true;
}

static bool parse_signer_key(buffer_t *buffer, signer_key_t *key) {
uint32_t signer_type;

Expand Down Expand Up @@ -695,7 +739,7 @@ static bool parse_begin_sponsoring_future_reserves(buffer_t *buffer,
return true;
}

static bool parse_sc_address(buffer_t *buffer, sc_address_t *sc_address) {
bool parse_sc_address(buffer_t *buffer, sc_address_t *sc_address) {
uint32_t address_type;
PARSER_CHECK(buffer_read32(buffer, &address_type))
sc_address->type = address_type;
Expand Down Expand Up @@ -749,7 +793,7 @@ static bool read_contract_executable_advance(buffer_t *buffer) {
return true;
}

static bool read_scval_advance(buffer_t *buffer) {
bool read_scval_advance(buffer_t *buffer) {
uint32_t sc_type;
PARSER_CHECK(buffer_read32(buffer, &sc_type))

Expand Down Expand Up @@ -996,13 +1040,22 @@ static bool parse_invoke_contract_args(buffer_t *buffer, invoke_contract_args_t
args->function.name_size = name_size;

// args
uint32_t args_len;
PARSER_CHECK(buffer_read32(buffer, &args_len))

args->parameters_length = args_len;
args->parameters_position = buffer->offset;
// PRINTF("function_name.text_size=%d, function_name.text=%s\n",

// if (args_len > 10) {
// // TODO: We dont support more than 10 arguments
// return false;
// }

// PRINTF("function_name.text_size=%d, function_name.text=%s, args->parameters_length=%d\n",
// args->function.name_size,
// args->function.name);
// args->function.name,
// args->parameters_length);

uint32_t args_len;
PARSER_CHECK(buffer_read32(buffer, &args_len))
for (uint32_t i = 0; i < args_len; i++) {
PARSER_CHECK(read_scval_advance(buffer))
}
Expand Down Expand Up @@ -1175,8 +1228,7 @@ static bool parse_operation(buffer_t *buffer, operation_t *operation) {
case OPERATION_TYPE_LIQUIDITY_POOL_WITHDRAW:
return parse_liquidity_pool_withdraw(buffer, &operation->liquidity_pool_withdraw_op);
case OPERATION_INVOKE_HOST_FUNCTION: {
PARSER_CHECK(parse_invoke_host_function(buffer, &operation->invoke_host_function_op))
return true;
return parse_invoke_host_function(buffer, &operation->invoke_host_function_op);
}
case OPERATION_EXTEND_FOOTPRINT_TTL:
return parse_extend_footprint_ttl(buffer, &operation->extend_footprint_ttl_op);
Expand Down Expand Up @@ -1301,30 +1353,30 @@ bool parse_transaction_envelope(const uint8_t *data, size_t data_len, envelope_t
.offset = 0,
};

explicit_bzero(&envelope->tx, sizeof(transaction_details_t));
explicit_bzero(&envelope->fee_bump_tx, sizeof(fee_bump_transaction_details_t));
explicit_bzero(&envelope->tx_details, sizeof(tx_details_t));
uint32_t envelope_type;
PARSER_CHECK(parse_network(&buffer, &envelope->network))
PARSER_CHECK(buffer_read32(&buffer, &envelope_type))
envelope->type = envelope_type;
switch (envelope_type) {
case ENVELOPE_TYPE_TX:
PARSER_CHECK(parse_transaction_details(&buffer, &envelope->tx))
PARSER_CHECK(parse_transaction_details(&buffer, &envelope->tx_details.tx))
break;
case ENVELOPE_TYPE_TX_FEE_BUMP:
PARSER_CHECK(parse_fee_bump_transaction_details(&buffer, &envelope->fee_bump_tx))
PARSER_CHECK(
parse_fee_bump_transaction_details(&buffer, &envelope->tx_details.fee_bump_tx))
uint32_t inner_envelope_type;
PARSER_CHECK(buffer_read32(&buffer, &inner_envelope_type))
if (inner_envelope_type != ENVELOPE_TYPE_TX) {
return false;
}
PARSER_CHECK(parse_transaction_details(&buffer, &envelope->tx))
PARSER_CHECK(parse_transaction_details(&buffer, &envelope->tx_details.tx))
break;
default:
return false;
}

envelope->tx.operation_position = buffer.offset;
envelope->tx_details.tx.operation_position = buffer.offset;
return true;
}

Expand All @@ -1335,11 +1387,64 @@ bool parse_transaction_operation(const uint8_t *data,
buffer_t buffer = {
.ptr = data,
.size = data_len,
.offset = envelope->tx.operation_position,
.offset = envelope->tx_details.tx.operation_position,
};
for (uint8_t i = 0; i <= operation_index; i++) {
PARSER_CHECK(parse_operation(&buffer, &envelope->tx.op_details));
PARSER_CHECK(parse_operation(&buffer, &envelope->tx_details.tx.op_details));
}
envelope->tx_details.tx.operation_index = operation_index;
return true;
}

bool parse_soroban_authorization_envelope(const uint8_t *data,
size_t data_len,
envelope_t *envelope) {
// PRINTF("parse_transaction_envelope: offset=%d\n", buffer->offset);
buffer_t buffer = {
.ptr = data,
.size = data_len,
.offset = 0,
};

explicit_bzero(&envelope->soroban_authorization, sizeof(soroban_authorization_t));

uint32_t envelope_type;
PARSER_CHECK(buffer_read32(&buffer, &envelope_type))
if (envelope_type != ENVELOPE_TYPE_SOROBAN_AUTHORIZATION) {
return false;
}
envelope->type = envelope_type;

PARSER_CHECK(parse_network(&buffer, &envelope->network))
PARSER_CHECK(buffer_read64(&buffer, &envelope->soroban_authorization.nonce))
PARSER_CHECK(
buffer_read32(&buffer, &envelope->soroban_authorization.signature_expiration_ledger))

// function
uint32_t type;
PARSER_CHECK(buffer_read32(&buffer, &type))
envelope->soroban_authorization.function_type = type;
switch (type) {
case SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN: {
// contractFn
PARSER_CHECK(
parse_invoke_contract_args(&buffer,
&envelope->soroban_authorization.invoke_contract_args));
break;
}
case SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN:
// createContractHostFn
PARSER_CHECK(read_create_contract_args_advance(&buffer))
break;
default:
return false;
}

// subInvocations
uint32_t len;
PARSER_CHECK(buffer_read32(&buffer, &len))
for (uint32_t i = 0; i < len; i++) {
PARSER_CHECK(read_soroban_authorized_invocation_advance(&buffer))
}
envelope->tx.operation_index = operation_index;
return true;
}
Loading

0 comments on commit ae99370

Please sign in to comment.