Skip to content

Commit

Permalink
Support displaying nested authorization & Add built-in XLM and USDC S…
Browse files Browse the repository at this point in the history
…oroban Token plugin (#14)
  • Loading branch information
overcat authored May 6, 2024
1 parent fb39552 commit 0e75242
Show file tree
Hide file tree
Showing 1,767 changed files with 2,104 additions and 220 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ elfs/
debug/
build/
tests_unit/build/
tests_unit/cmake-build-debug/
tests_unit/testcases/*.raw
tests_zemu/node_modules/
tests_zemu/snapshots-tmp/
Expand Down
1 change: 1 addition & 0 deletions .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"TARGET_NANOS",
"OS_IO_SEPROXYHAL",
"HAVE_BAGL",
"HAVE_NBGL",
"HAVE_SPRINTF",
"HAVE_IO_USB",
"HAVE_L4_USBLIB",
Expand Down
11 changes: 10 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,16 @@
"random": "c",
"array": "c",
"string": "c",
"string_view": "c"
"string_view": "c",
"optional": "c",
"ostream": "c",
"system_error": "c",
"functional": "c",
"tuple": "c",
"type_traits": "c",
"utility": "c",
"ratio": "c",
"ranges": "c"
},
"C_Cpp.clang_format_path": "/usr/bin/clang-format",
"editor.formatOnSave": true
Expand Down
4 changes: 3 additions & 1 deletion fuzz/fuzz_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
.display_sequence = true,
};

reset_formatter();
if (!reset_formatter(&fdata)) {
return 0;
}

bool data_exists = true;
bool is_op_header = false;
Expand Down
573 changes: 426 additions & 147 deletions libstellar/formatter.c

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion libstellar/include/stellar/formatter.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ typedef struct {
/**
* Reset the formatter state.
*/
void reset_formatter();
bool reset_formatter(formatter_data_t *fdata);

/**
* Get the next data to display.
Expand Down
4 changes: 4 additions & 0 deletions libstellar/include/stellar/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,7 @@ bool parse_sc_address(buffer_t *buffer, sc_address_t *sc_address);
* @return True if the reading was successful, false otherwise.
*/
bool read_scval_advance(buffer_t *buffer);

bool parse_auth_function(buffer_t *buffer,
soroban_authorization_function_type_t *type,
invoke_contract_args_t *args);
21 changes: 15 additions & 6 deletions libstellar/include/stellar/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
/* max amount is max int64 scaled down: "922337203685.4775807" */
#define AMOUNT_MAX_LENGTH 21

#define MAX_SUB_INVOCATIONS_SIZE 16

#define HASH_SIZE 32
#define LIQUIDITY_POOL_ID_SIZE 32
#define CLAIMABLE_BALANCE_ID_SIZE 32
Expand Down Expand Up @@ -550,10 +552,19 @@ typedef enum {
HOST_FUNCTION_TYPE_UPLOAD_CONTRACT_WASM = 2
} host_function_type_t;

typedef enum {
SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN = 0,
SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN = 1
} soroban_authorization_function_type_t;

typedef struct {
host_function_type_t host_function_type;
invoke_contract_args_t
invoke_contract_args; // exists if host_function_type == HOST_FUNCTION_TYPE_INVOKE_CONTRACT
soroban_authorization_function_type_t auth_function_type;
size_t sub_invocation_positions[MAX_SUB_INVOCATIONS_SIZE];
uint8_t sub_invocations_count;
uint8_t sub_invocation_index;
} invoke_host_function_op_t;

typedef struct {
Expand All @@ -564,16 +575,14 @@ typedef struct {
void *placeholder;
} restore_footprint_op_t;

typedef enum {
SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN = 0,
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;
soroban_authorization_function_type_t auth_function_type;
invoke_contract_args_t invoke_contract_args;
size_t sub_invocation_positions[MAX_SUB_INVOCATIONS_SIZE];
uint8_t sub_invocations_count;
uint8_t sub_invocation_index;
} soroban_authorization_t;

// ************************* Soroban ************************* //
Expand Down
122 changes: 93 additions & 29 deletions libstellar/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -984,7 +984,7 @@ static bool parse_restore_footprint(buffer_t *buffer, restore_footprint_op_t *op
return true;
}

static bool read_parse_soroban_credentials_advance(buffer_t *buffer) {
static bool read_parse_soroban_credentials_advance(buffer_t *buffer, uint32_t *credentials_type) {
uint32_t type;
PARSER_CHECK(buffer_read32(buffer, &type))
switch (type) {
Expand All @@ -1002,6 +1002,7 @@ static bool read_parse_soroban_credentials_advance(buffer_t *buffer) {
default:
return false;
}
*credentials_type = type;
return true;
}

Expand Down Expand Up @@ -1084,24 +1085,40 @@ static bool read_soroban_authorized_function_advance(buffer_t *buffer) {
return true;
}

static bool read_soroban_authorized_invocation_advance(buffer_t *buffer) {
static bool read_soroban_authorized_invocation_advance(buffer_t *buffer,
uint8_t *count,
size_t *positions) {
if (count != NULL && positions != NULL) {
if (*count >= MAX_SUB_INVOCATIONS_SIZE) {
return false;
}
positions[(*count)++] = buffer->offset;
}
// function
PARSER_CHECK(read_soroban_authorized_function_advance(buffer))

// 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))
PARSER_CHECK(read_soroban_authorized_invocation_advance(buffer, count, positions))
}
return true;
}

static bool read_soroban_authorization_entry_advance(buffer_t *buffer) {
PARSER_CHECK(read_parse_soroban_credentials_advance(buffer))
PARSER_CHECK(read_soroban_authorized_invocation_advance(buffer))
return true;
}
// static bool read_soroban_authorization_entry_advance(buffer_t *buffer,
// uint8_t *count,
// size_t *positions) {
// uint32_t credentials_type;
// PARSER_CHECK(read_parse_soroban_credentials_advance(buffer, &credentials_type))

// if (credentials_type == SOROBAN_CREDENTIALS_SOURCE_ACCOUNT) {
// PARSER_CHECK(read_soroban_authorized_invocation_advance(buffer, count, positions))
// } else {
// PARSER_CHECK(read_soroban_authorized_invocation_advance(buffer, NULL, NULL))
// }
// return true;
// }

static bool parse_invoke_host_function(buffer_t *buffer, invoke_host_function_op_t *op) {
// hostFunction
Expand All @@ -1128,10 +1145,39 @@ static bool parse_invoke_host_function(buffer_t *buffer, invoke_host_function_op

// auth<>
uint32_t auth_len;
uint8_t sub_invocations_count = 0;
PARSER_CHECK(buffer_read32(buffer, &auth_len))
for (uint32_t i = 0; i < auth_len; i++) {
PARSER_CHECK(read_soroban_authorization_entry_advance(buffer))
// PARSER_CHECK(read_soroban_authorization_entry_advance(buffer,
// &sub_invocations_count,
// op->sub_invocation_positions))
// PARSER_CHECK(read_soroban_authorized_invocation_advance(buffer, count, positions))
// 1. read credentials
uint32_t credentials_type;
PARSER_CHECK(read_parse_soroban_credentials_advance(buffer, &credentials_type))
// 2. read rootInvocation.function
PARSER_CHECK(read_soroban_authorized_function_advance(buffer))
// 3. read rootInvocation.subInvocations
// subInvocations
uint32_t len;
PARSER_CHECK(buffer_read32(buffer, &len))
for (uint32_t j = 0; j < len; j++) {
if (credentials_type == SOROBAN_CREDENTIALS_SOURCE_ACCOUNT) {
PARSER_CHECK(
read_soroban_authorized_invocation_advance(buffer,
&sub_invocations_count,
op->sub_invocation_positions))
} else {
PARSER_CHECK(read_soroban_authorized_invocation_advance(buffer, NULL, NULL))
}
}
}
op->sub_invocations_count = sub_invocations_count;

// PRINTF("sub_invocations_count=%d\n", sub_invocations_count);
// for (uint8_t i = 0; i < 16; i++) {
// PRINTF("sub_invocation_positions[%d]=%d\n", i, op->sub_invocation_positions[i]);
// }
return true;
}

Expand Down Expand Up @@ -1398,6 +1444,29 @@ bool parse_transaction_operation(const uint8_t *data,
return true;
}

bool parse_auth_function(buffer_t *buffer,
soroban_authorization_function_type_t *type,
invoke_contract_args_t *args) {
// function
uint32_t function_type;
PARSER_CHECK(buffer_read32(buffer, &function_type))
*type = function_type;
switch (function_type) {
case SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN: {
// contractFn
PARSER_CHECK(parse_invoke_contract_args(buffer, args))
break;
}
case SOROBAN_AUTHORIZED_FUNCTION_TYPE_CREATE_CONTRACT_HOST_FN:
// createContractHostFn
PARSER_CHECK(read_create_contract_args_advance(buffer))
break;
default:
return false;
}
return true;
}

bool parse_soroban_authorization_envelope(const uint8_t *data,
size_t data_len,
envelope_t *envelope) {
Expand All @@ -1423,30 +1492,25 @@ bool parse_soroban_authorization_envelope(const uint8_t *data,
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;
}

PARSER_CHECK(parse_auth_function(&buffer,
&envelope->soroban_authorization.auth_function_type,
&envelope->soroban_authorization.invoke_contract_args))
// subInvocations
uint32_t len;
uint8_t sub_invocations_count = 0;
PARSER_CHECK(buffer_read32(&buffer, &len))
for (uint32_t i = 0; i < len; i++) {
PARSER_CHECK(read_soroban_authorized_invocation_advance(&buffer))
PARSER_CHECK(read_soroban_authorized_invocation_advance(
&buffer,
&sub_invocations_count,
envelope->soroban_authorization.sub_invocation_positions));
}
envelope->soroban_authorization.sub_invocations_count = sub_invocations_count;
// PRINTF("sub_invocations_count=%d\n", sub_invocations_count);
// for (uint8_t i = 0; i < 16; i++) {
// PRINTF("sub_invocation_positions[%d]=%d\n",
// i,
// envelope->soroban_authorization.sub_invocation_positions[i]);
// }
return true;
}
2 changes: 1 addition & 1 deletion src/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
/*
* 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
#define DETAIL_CAPTION_MAX_LENGTH 21

/*
* DETAIL_VALUE_MAX_LENGTH value of 105 is chosen to fit the maximum length of 2**256 - 1 with
Expand Down
26 changes: 26 additions & 0 deletions src/plugin.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "plugin.h"
#include "globals.h"
#include "soroban_token.h"

#define MAX_APP_NAME_LENGTH 20

Expand All @@ -28,6 +29,11 @@ static const char *get_app_name(const uint8_t *contract_address) {
};

bool plugin_check_presence(const uint8_t *contract_address) {
// Build-in token plugin
if (token_plugin_check_presence(contract_address)) {
return true;
}

const char *app_name = get_app_name(contract_address);
if (app_name == NULL) {
return false;
Expand All @@ -54,6 +60,11 @@ bool plugin_check_presence(const uint8_t *contract_address) {
};

stellar_plugin_result_t plugin_init_contract(const uint8_t *contract_address) {
// Build-in token plugin
if (token_plugin_check_presence(contract_address)) {
return STELLAR_PLUGIN_RESULT_OK;
}

const char *app_name = get_app_name(contract_address);

stellar_plugin_shared_ro_t plugin_shared_ro = {
Expand All @@ -78,6 +89,11 @@ stellar_plugin_result_t plugin_init_contract(const uint8_t *contract_address) {

stellar_plugin_result_t plugin_query_data_pair_count(const uint8_t *contract_address,
uint8_t *data_pair_count) {
// Build-in token plugin
if (token_plugin_check_presence(contract_address)) {
return token_plugin_query_data_pair_count(contract_address, data_pair_count);
}

const char *app_name = get_app_name(contract_address);

stellar_plugin_shared_ro_t plugin_shared_ro = {
Expand Down Expand Up @@ -107,6 +123,16 @@ stellar_plugin_result_t plugin_query_data_pair(const uint8_t *contract_address,
uint8_t caption_len,
char *value,
uint8_t value_len) {
// Build-in token plugin
if (token_plugin_check_presence(contract_address)) {
return token_plugin_query_data_pair(contract_address,
data_pair_index,
caption,
caption_len,
value,
value_len);
}

const char *app_name = get_app_name(contract_address);

stellar_plugin_shared_ro_t plugin_shared_ro = {
Expand Down
Loading

0 comments on commit 0e75242

Please sign in to comment.