Skip to content

Commit

Permalink
parse spend plan and clean code
Browse files Browse the repository at this point in the history
  • Loading branch information
abenso committed Nov 8, 2024
1 parent 702f7c1 commit 4c1be97
Show file tree
Hide file tree
Showing 10 changed files with 126 additions and 225 deletions.
2 changes: 1 addition & 1 deletion app/src/c_api/rust.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ zxerr_t crypto_extractSpendingKeyBytes(uint8_t *key_bytes, uint32_t key_bytes_le

// Function to compute BLAKE2b hash with personalization
zxerr_t blake2b_hash_with_personalization(const uint8_t *input, size_t input_len, uint8_t *output, size_t output_len,
const uint8_t *label, size_t label_len) {
const uint8_t *label, size_t label_len) {
cx_blake2b_t hash_context;

// unsigned char *salt = NULL;
Expand Down
1 change: 0 additions & 1 deletion app/src/common/parser_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ extern "C" {
if (__err != parser_ok) return __err; \
}


// Convert bytes to uint32_t,
// assume data is in BE format
#define U32_BE(buffer, number) \
Expand Down
173 changes: 21 additions & 152 deletions app/src/parser_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,15 @@
#include "parser_impl.h"

#include "parser_interface.h"
#include "parser_pb_utils.h"
#include "pb_common.h"
#include "pb_decode.h"
#include "protobuf/penumbra/core/transaction/v1/transaction.pb.h"
#include "spend_plan.h"
#include "zxformat.h"

static bool decode_field(pb_istream_t *stream, const pb_field_t *field, void **arg);
static bool decode_action(pb_istream_t *stream, const pb_field_t *field, void **arg);
static bool decode_detection_data(pb_istream_t *stream, const pb_field_t *field, void **arg);
static void setup_decode_field(pb_callback_t *callback, decode_memo_field_arg_t *arg, Bytes_t *bytes, uint16_t expected_size,
bool check_size);
static parser_error_t extract_data_from_tag(Bytes_t *in, Bytes_t *out, uint32_t tag);

static uint16_t actions_qty = 0;
static uint16_t detection_data_qty = 0;
Expand Down Expand Up @@ -55,38 +53,9 @@ void print_string(const char *str) {
#endif
}

bool decode_field(pb_istream_t *stream, const pb_field_t *field, void **arg) {
if (stream->bytes_left == 0 || arg == NULL) return false;

decode_memo_field_arg_t *decode_arg = (decode_memo_field_arg_t *)*arg;
if (decode_arg == NULL || decode_arg->bytes == NULL) {
return false;
}

if (decode_arg->check_size && stream->bytes_left != decode_arg->expected_size) {
return false;
}

const uint8_t *first_byte = stream->state;
uint16_t data_size = stream->bytes_left;

decode_arg->bytes->ptr = first_byte;
decode_arg->bytes->len = data_size;

return true;
}

void setup_decode_field(pb_callback_t *callback, decode_memo_field_arg_t *arg, Bytes_t *bytes, uint16_t expected_size,
bool check_size) {
arg->bytes = bytes;
arg->expected_size = expected_size;
arg->check_size = check_size;
callback->funcs.decode = &decode_field;
callback->arg = arg;
}

bool decode_action(pb_istream_t *stream, const pb_field_t *field, void **arg) {
penumbra_core_transaction_v1_ActionPlan action = penumbra_core_transaction_v1_ActionPlan_init_default;
spend_plan_t spend_plan;

action_t *decode_arg = (action_t *)*arg;
if (decode_arg == NULL) {
Expand All @@ -99,15 +68,16 @@ bool decode_action(pb_istream_t *stream, const pb_field_t *field, void **arg) {

const uint8_t *first_byte = stream->state;
uint16_t data_size = stream->bytes_left;
decode_arg[actions_qty].action.ptr = first_byte + 2;
decode_arg[actions_qty].action.len = data_size - 2;
decode_arg[actions_qty].action.ptr = first_byte + 3;
decode_arg[actions_qty].action.len = data_size - 3;

if (!pb_decode(stream, penumbra_core_transaction_v1_ActionPlan_fields, &action)) {
return false;
}
decode_arg[actions_qty].action_type = action.which_action;
switch (action.which_action) {
case penumbra_core_transaction_v1_ActionPlan_spend_tag:
decode_spend_plan(&decode_arg[actions_qty].action, &spend_plan);
print_string("Spend action detected \n");
break;
case penumbra_core_transaction_v1_ActionPlan_output_tag:
Expand Down Expand Up @@ -145,14 +115,15 @@ bool decode_detection_data(pb_istream_t *stream, const pb_field_t *field, void *
}

penumbra_core_transaction_v1_CluePlan cluePlan = penumbra_core_transaction_v1_CluePlan_init_default;
decode_memo_field_arg_t rseed_arg, address_inner_arg, address_alt_bech32m_arg;
fixed_size_field_t rseed_arg, address_inner_arg;
variable_size_field_t address_alt_bech32m_arg;
clue_plan_t *clue_plan_arg = (clue_plan_t *)*arg;

setup_decode_field(&cluePlan.rseed, &rseed_arg, &clue_plan_arg[detection_data_qty].rseed, RSEED_SIZE, true);
setup_decode_field(&cluePlan.address.inner, &address_inner_arg, &clue_plan_arg[detection_data_qty].address.inner,
MEMO_ADDRESS_INNER_SIZE, true);
setup_decode_field(&cluePlan.address.alt_bech32m, &address_alt_bech32m_arg,
&clue_plan_arg[detection_data_qty].address.alt_bech32m, 0, false);
setup_decode_fixed_field(&cluePlan.rseed, &rseed_arg, &clue_plan_arg[detection_data_qty].rseed, RSEED_SIZE);
setup_decode_fixed_field(&cluePlan.address.inner, &address_inner_arg, &clue_plan_arg[detection_data_qty].address.inner,
MEMO_ADDRESS_INNER_SIZE);
setup_decode_variable_field(&cluePlan.address.alt_bech32m, &address_alt_bech32m_arg,
&clue_plan_arg[detection_data_qty].address.alt_bech32m);

if (!pb_decode(stream, penumbra_core_transaction_v1_CluePlan_fields, &cluePlan)) {
return false;
Expand All @@ -164,109 +135,6 @@ bool decode_detection_data(pb_istream_t *stream, const pb_field_t *field, void *
return true;
}

parser_error_t extract_data_from_tag(Bytes_t *in, Bytes_t *out, uint32_t tag) {
const uint8_t *start = NULL;
const uint8_t *end = NULL;
bool eof = false;

pb_istream_t scan_stream = pb_istream_from_buffer(in->ptr, in->len);
pb_wire_type_t wire_type;
uint32_t tag_internal;
while (pb_decode_tag(&scan_stream, &wire_type, &tag_internal, &eof) && !eof) {
if (tag_internal == tag) {
start = scan_stream.state;
if (!pb_skip_field(&scan_stream, wire_type)) {
return parser_unexpected_error;
}
end = scan_stream.state;
break;
} else {
if (!pb_skip_field(&scan_stream, wire_type)) {
return parser_unexpected_error;
}
}
}

if (!start || !end) {
return parser_unexpected_error;
}

out->ptr = start + 1;
out->len = end - start - 1;

return parser_ok;
}

// parser_error_t extract_data_array_from_tag(Bytes_t *in, Bytes_t out[], uint32_t tag) {
// const uint8_t *start = NULL;
// const uint8_t *end = NULL;
// bool eof = false;

// pb_istream_t scan_stream = pb_istream_from_buffer(in->ptr, in->len);
// pb_wire_type_t wire_type;
// uint32_t tag_internal;
// size_t out_index = 0;

// while (pb_decode_tag(&scan_stream, &wire_type, &tag_internal, &eof) && !eof) {
// if (tag_internal == tag) {
// start = scan_stream.state;
// if (!pb_skip_field(&scan_stream, wire_type)) {
// return parser_unexpected_error;
// }
// end = scan_stream.state;

// if (!start || !end) {
// return parser_unexpected_error;
// }

// out[out_index].ptr = start + 1;
// out[out_index].len = end - start - 1;
// out_index++;
// } else {
// if (!pb_skip_field(&scan_stream, wire_type)) {
// return parser_unexpected_error;
// }
// }
// }

// return parser_ok;
// }

// parser_error_t compute_detection_data(Bytes_t *detection_data, parser_tx_t *v) {
// uint16_t detection_data_bytes = DETECTION_DATA_SIZE;
// uint16_t clue_plans = detection_data->len / detection_data_bytes;

// if (clue_plans > 1) {
// if ((detection_data->ptr[0] + 1 == clue_plans) || (clue_plans * detection_data_bytes + 1 == detection_data->len))
// {
// for (uint16_t i = 0; i < clue_plans; i++) {
// v->plan.detection_data.clue_plans[i].ptr = detection_data->ptr + (i * detection_data_bytes + 1);
// v->plan.detection_data.clue_plans[i].len = DETECTION_DATA_SIZE;
// }
// } else {
// return parser_unexpected_error;
// }
// } else {
// v->plan.detection_data.clue_plans[0].ptr = detection_data->ptr;
// v->plan.detection_data.clue_plans[0].len = detection_data->len;
// }

// return parser_ok;
// }

// parser_error_t compute_actions(Bytes_t actions[], parser_tx_t *v) {
// for (uint16_t i = 0; i < ACTIONS_QTY; i++) {
// if (actions[i].len > 2) {
// v->plan.actions[i].action_type = actions[i].ptr[1] >> 3;
// // TODO: check if we have to parser each action
// v->plan.actions[i].action.ptr = actions[i].ptr + 2;
// v->plan.actions[i].action.len = actions[i].len - 2;
// }
// }

// return parser_ok;
// }

parser_error_t _read(parser_context_t *c, parser_tx_t *v) {
Bytes_t data;
data.ptr = c->buffer;
Expand All @@ -275,15 +143,16 @@ parser_error_t _read(parser_context_t *c, parser_tx_t *v) {
detection_data_qty = 0;

penumbra_core_transaction_v1_TransactionPlan request = penumbra_core_transaction_v1_TransactionPlan_init_default;
decode_memo_field_arg_t memo_key_arg, memo_text_arg, memo_return_address_inner_arg, memo_return_address_alt_bech32m_arg;
fixed_size_field_t memo_key_arg, memo_return_address_inner_arg;
variable_size_field_t memo_text_arg, memo_return_address_alt_bech32m_arg;

// memo callbacks
setup_decode_field(&request.memo.key, &memo_key_arg, &v->plan.memo.key, MEMO_KEY_SIZE, true);
setup_decode_field(&request.memo.plaintext.text, &memo_text_arg, &v->plan.memo.plaintext.text, 0, false);
setup_decode_field(&request.memo.plaintext.return_address.inner, &memo_return_address_inner_arg,
&v->plan.memo.plaintext.return_address.inner, MEMO_ADDRESS_INNER_SIZE, true);
setup_decode_field(&request.memo.plaintext.return_address.alt_bech32m, &memo_return_address_alt_bech32m_arg,
&v->plan.memo.plaintext.return_address.alt_bech32m, 0, false);
setup_decode_fixed_field(&request.memo.key, &memo_key_arg, &v->plan.memo.key, MEMO_KEY_SIZE);
setup_decode_variable_field(&request.memo.plaintext.text, &memo_text_arg, &v->plan.memo.plaintext.text);
setup_decode_fixed_field(&request.memo.plaintext.return_address.inner, &memo_return_address_inner_arg,
&v->plan.memo.plaintext.return_address.inner, MEMO_ADDRESS_INNER_SIZE);
setup_decode_variable_field(&request.memo.plaintext.return_address.alt_bech32m, &memo_return_address_alt_bech32m_arg,
&v->plan.memo.plaintext.return_address.alt_bech32m);

// actions callbacks
request.actions.funcs.decode = &decode_action;
Expand Down
6 changes: 0 additions & 6 deletions app/src/parser_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@
extern "C" {
#endif

typedef struct {
Bytes_t *bytes;
uint16_t expected_size;
bool check_size;
} decode_memo_field_arg_t;

parser_error_t _read(parser_context_t *c, parser_tx_t *v);

#ifdef __cplusplus
Expand Down
73 changes: 59 additions & 14 deletions app/src/parser_pb_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,41 +14,86 @@
* limitations under the License.
********************************************************************************/

#include "parser_impl.h"
#include "parser_pb_utils.h"

#include "parser_impl.h"
#include "parser_interface.h"
#include "zxformat.h"
#include "parser_pb_utils.h"


bool decode_fixed_field(pb_istream_t *stream, const pb_field_t *field, void **arg)
{
if (stream->bytes_left == 0 || arg == NULL)
return false;
bool decode_fixed_field(pb_istream_t *stream, const pb_field_t *field, void **arg) {
if (stream->bytes_left == 0 || arg == NULL) return false;

fixed_size_field_t *decode_arg = (fixed_size_field_t *)*arg;
if (decode_arg == NULL || decode_arg->bytes == NULL) {
return false;
}

if (decode_arg->check_size && stream->bytes_left != decode_arg->expected_size) {
if (stream->bytes_left != decode_arg->expected_size) {
return false;
}

const uint8_t *first_byte = stream->state;
uint16_t data_size = stream->bytes_left;
decode_arg->bytes->ptr = stream->state;
decode_arg->bytes->len = stream->bytes_left;

return true;
}

bool decode_variable_field(pb_istream_t *stream, const pb_field_t *field, void **arg) {
if (stream->bytes_left == 0 || arg == NULL) return false;

variable_size_field_t *decode_arg = (variable_size_field_t *)*arg;
if (decode_arg == NULL || decode_arg->bytes == NULL) {
return false;
}

decode_arg->bytes->ptr = first_byte;
decode_arg->bytes->len = data_size;
decode_arg->bytes->ptr = stream->state;
decode_arg->bytes->len = stream->bytes_left;

return true;
}

void setup_decode_fixed_field(pb_callback_t *callback, fixed_size_field_t *arg, Bytes_t *bytes, uint16_t expected_size, bool check_size) {
void setup_decode_fixed_field(pb_callback_t *callback, fixed_size_field_t *arg, Bytes_t *bytes, uint16_t expected_size) {
arg->bytes = bytes;
arg->expected_size = expected_size;
arg->check_size = check_size;
callback->funcs.decode = &decode_fixed_field;
callback->arg = arg;
}

void setup_decode_variable_field(pb_callback_t *callback, variable_size_field_t *arg, Bytes_t *bytes) {
arg->bytes = bytes;
callback->funcs.decode = &decode_variable_field;
callback->arg = arg;
}

parser_error_t extract_data_from_tag(Bytes_t *in, Bytes_t *out, uint32_t tag) {
const uint8_t *start = NULL;
const uint8_t *end = NULL;
bool eof = false;

pb_istream_t scan_stream = pb_istream_from_buffer(in->ptr, in->len);
pb_wire_type_t wire_type;
uint32_t tag_internal;
while (pb_decode_tag(&scan_stream, &wire_type, &tag_internal, &eof) && !eof) {
if (tag_internal == tag) {
start = scan_stream.state;
if (!pb_skip_field(&scan_stream, wire_type)) {
return parser_unexpected_error;
}
end = scan_stream.state;
break;
} else {
if (!pb_skip_field(&scan_stream, wire_type)) {
return parser_unexpected_error;
}
}
}

if (!start || !end) {
return parser_unexpected_error;
}

out->ptr = start + 1;
out->len = end - start - 1;

return parser_ok;
}
Loading

0 comments on commit 4c1be97

Please sign in to comment.