Skip to content

Commit

Permalink
add masptx parser
Browse files Browse the repository at this point in the history
  • Loading branch information
chcmedeiros committed Feb 8, 2024
1 parent e253638 commit bbbe662
Show file tree
Hide file tree
Showing 6 changed files with 310 additions and 52 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ file(GLOB_RECURSE LIB_SRC
${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_impl.c
${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_impl_common.c
${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_impl_txn.c
${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_impl_masp.c
${CMAKE_CURRENT_SOURCE_DIR}/app/src/crypto_helper.c
${CMAKE_CURRENT_SOURCE_DIR}/app/src/leb128.c
${CMAKE_CURRENT_SOURCE_DIR}/app/src/txn_validator.c
Expand Down
8 changes: 8 additions & 0 deletions app/src/parser_impl_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@ extern "C" {
#define CHANGE_VALIDATOR_METADATA_NORMAL_PARAMS 2
#define CHANGE_VALIDATOR_METADATA_EXPERT_PARAMS 7

#define DISCRIMINANT_DATA 0x00
#define DISCRIMINANT_EXTRA_DATA 0x01
#define DISCRIMINANT_CODE 0x02
#define DISCRIMINANT_SIGNATURE 0x03
#define DISCRIMINANT_CIPHERTEXT 0x04
#define DISCRIMINANT_MASP_TX 0x05
#define DISCRIMINANT_MASP_BUILDER 0x06

parser_error_t readByte(parser_context_t *ctx, uint8_t *byte);
parser_error_t readBytes(parser_context_t *ctx, const uint8_t **output, uint16_t outputLen);
parser_error_t readUint16(parser_context_t *ctx, uint16_t *value);
Expand Down
220 changes: 220 additions & 0 deletions app/src/parser_impl_masp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
/*******************************************************************************
* (c) 2018 - 2023 Zondax AG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
********************************************************************************/
#include "parser_impl_masp.h"

#include "parser_impl_common.h"
#include "parser_txdef.h"

#define ASSET_ID_LEN 32
#define ANCHOR_LEN 32
#define TRANSPARENT_ADDRESS_LEN 20
#define SHIELDED_OUTPUTS_LEN 756
#define INT_128_LEN 16
#define ZKPROFF_LEN 192
#define AUTH_SIG_LEN 64
#define SHIELDED_SPENDS_LEN 96
#define SHIELDED_CONVERTS_LEN 32

static parser_error_t parse_sapling_bundle(parser_context_t *ctx,
masp_sapling_bundle_t *bundle) {
if (ctx == NULL || bundle == NULL) {
return parser_unexpected_error;
}
uint8_t i = 0;

uint8_t has_shielded_spends = 0;
CHECK_ERROR(readByte(ctx, &has_shielded_spends))
if (has_shielded_spends != 0) {
bundle->n_shileded_spends = has_shielded_spends;
bundle->shielded_spends.len = SHIELDED_SPENDS_LEN;
for (i = 0; i < bundle->n_shileded_spends; i++) {
CHECK_ERROR(readBytes(ctx, bundle->shielded_spends.ptr,
bundle->shielded_spends.len))
}
}

uint8_t has_shielded_converts = 0;
CHECK_ERROR(readByte(ctx, &has_shielded_converts))
if (has_shielded_converts != 0) {
bundle->n_shielded_converts = has_shielded_converts;
bundle->shielded_converts.len = SHIELDED_CONVERTS_LEN;
for (i = 0; i < bundle->n_shielded_converts; i++) {
CHECK_ERROR(readBytes(ctx, bundle->shielded_converts.ptr,
bundle->shielded_converts.len))
}
}

uint8_t has_shielded_outputs = 0;
CHECK_ERROR(readByte(ctx, &has_shielded_outputs))
if (has_shielded_outputs != 0) {
bundle->n_shielded_outputs = has_shielded_outputs;
bundle->shielded_outputs.len = SHIELDED_OUTPUTS_LEN;
for (i = 0; i < bundle->n_shielded_outputs; i++) {
CHECK_ERROR(readBytes(ctx, bundle->shielded_outputs.ptr,
bundle->shielded_outputs.len))
}
}

if (has_shielded_converts != 0 && has_shielded_outputs != 0) {
uint8_t has_value = 0;
CHECK_ERROR(readByte(ctx, &has_value))
if (!has_value) {
return parser_unexpected_value;
}
bundle->value_asset_id.len = ASSET_ID_LEN;
CHECK_ERROR(
readBytes(ctx, bundle->value_asset_id.ptr, bundle->value_asset_id.len))

bundle->value_balance.len = INT_128_LEN;
CHECK_ERROR(
readBytes(ctx, &bundle->value_balance, bundle->value_balance.len))
}

if (has_shielded_spends != 0) {
bundle->anchor_shielded_spends.len = ANCHOR_LEN;
CHECK_ERROR(readBytes(ctx, bundle->anchor_shielded_spends.ptr,
bundle->anchor_shielded_spends.len))
}

if (has_shielded_converts != 0) {
bundle->anchor_shielded_converts.len = ANCHOR_LEN;
CHECK_ERROR(readBytes(ctx, bundle->anchor_shielded_converts.ptr,
bundle->anchor_shielded_converts.len))
}

if (has_shielded_spends != 0) {
bundle->zkproof_shielded_spends.len = ZKPROFF_LEN;
CHECK_ERROR(readBytes(ctx, bundle->zkproof_shielded_spends.ptr,
bundle->zkproof_shielded_spends.len))
bundle->auth_sig_shielded_spends.len = AUTH_SIG_LEN;
CHECK_ERROR(readBytes(ctx, bundle->auth_sig_shielded_spends.ptr,
bundle->auth_sig_shielded_spends.len))
}

if (has_shielded_converts != 0) {
bundle->zkproof_shielded_converts.len = ZKPROFF_LEN;
CHECK_ERROR(readBytes(ctx, bundle->zkproof_shielded_converts.ptr,
bundle->zkproof_shielded_converts.len))
}

if (has_shielded_outputs != 0) {
bundle->zkproof_shielded_spends.len = ZKPROFF_LEN;
CHECK_ERROR(readBytes(ctx, bundle->zkproof_shielded_spends.ptr,
bundle->zkproof_shielded_spends.len))
}

if (has_shielded_converts != 0 && has_shielded_outputs != 0 &&
has_shielded_spends != 0) {
bundle->authorization.len = AUTH_SIG_LEN;
CHECK_ERROR(
readBytes(ctx, bundle->authorization.ptr, bundle->authorization.len))
}

return parser_ok;
}

static parser_error_t parse_transparent_bundle(
parser_context_t *ctx, masp_transparent_bundle_t *bundle) {
if (ctx == NULL || bundle == NULL) {
return parser_unexpected_error;
}

uint8_t has_vin = 0;
CHECK_ERROR(readByte(ctx, &has_vin))

if (has_vin != 0) {
bundle->vin.asset_type_id.len = ASSET_ID_LEN;
CHECK_ERROR(readBytes(ctx, bundle->vin.asset_type_id.ptr, ASSET_ID_LEN))

// Nonce is not encoded in the bundle, skipped in borsh encoding

CHECK_ERROR(readUint64(ctx, &bundle->vin.value))

bundle->vin.transparent_address.len = TRANSPARENT_ADDRESS_LEN;
CHECK_ERROR(readBytes(ctx, bundle->vin.transparent_address.ptr,
TRANSPARENT_ADDRESS_LEN))
}

uint8_t has_vout = 0;
CHECK_ERROR(readByte(ctx, &has_vout))

if (has_vout != 0) {
bundle->vout.asset_type_id.len = ASSET_ID_LEN;
CHECK_ERROR(readBytes(ctx, bundle->vout.asset_type_id.ptr, ASSET_ID_LEN))

// Nonce is not encoded in the bundle, skipped in borsh encoding

CHECK_ERROR(readUint64(ctx, &bundle->vout.value))

bundle->vin.transparent_address.len = TRANSPARENT_ADDRESS_LEN;
CHECK_ERROR(readBytes(ctx, bundle->vout.transparent_address.ptr,
TRANSPARENT_ADDRESS_LEN))
}

return parser_ok;
}

parser_error_t readMaspTx(parser_context_t *ctx, masp_tx_section_t *maspTx) {
if (ctx == NULL || maspTx == NULL) {
return parser_unexpected_error;
}

uint8_t sectionMaspTx = 0;
CHECK_ERROR(readByte(ctx, &sectionMaspTx))
if (sectionMaspTx != DISCRIMINANT_MASP_TX) {
return parser_unexpected_value;
}

// Read version for now only MaspV5 that translates to 0x02
CHECK_ERROR(readUint32(ctx, &maspTx->data.tx_version))
if (maspTx->data.tx_version != MASPV5_TX_VERSION) {
return parser_unexpected_value;
}
CHECK_ERROR(readUint32(ctx, &maspTx->data.version_group_id))
if (maspTx->data.version_group_id != MASPV5_VERSION_GROUP_ID) {
return parser_unexpected_value;
}

// Read branch id, unique enum for now
CHECK_ERROR(readUint32(ctx, &maspTx->data.consensus_branch_id))
if (maspTx->data.consensus_branch_id != BRANCH_ID_IDENTIFIER) {
return parser_unexpected_value;
}

// Read lock time
CHECK_ERROR(readUint32(ctx, &maspTx->data.lock_time))

// Read expiry_height
CHECK_ERROR(readUint32(ctx, &maspTx->data.expiry_height))

CHECK_ERROR(readUint16(ctx, &maspTx->data.has_transparent_bundle))
if (maspTx->data.has_transparent_bundle != 0) {
ctx->offset -= 2;
parse_transparent_bundle(ctx, &maspTx->data.transparent_bundle);
}
uint8_t has_shielded_spends = 0;
uint8_t has_shielded_output = 0;
uint8_t has_shielded_converts = 0;
CHECK_ERROR(readByte(ctx, &has_shielded_spends))
CHECK_ERROR(readByte(ctx, &has_shielded_converts))
CHECK_ERROR(readByte(ctx, &has_shielded_output))
if (has_shielded_spends != 0 && has_shielded_converts != 0 &&
has_shielded_output != 0) {
ctx->offset -= 3;
parse_sapling_bundle(ctx, &maspTx->data.sapling_bundle);
}
return parser_ok;
}
34 changes: 34 additions & 0 deletions app/src/parser_impl_masp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*******************************************************************************
* (c) 2018 - 2022 Zondax AG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
********************************************************************************/
#pragma once
#include "parser_common.h"
#include <zxmacros.h>
#include "zxtypes.h"
#include "parser_txdef.h"

#ifdef __cplusplus
extern "C" {
#endif

#define MASPV5_TX_VERSION 0x02
#define MASPV5_VERSION_GROUP_ID 0x26A7270A
#define BRANCH_ID_IDENTIFIER 0xE9FF75A6

parser_error_t readMaspTx(parser_context_t *ctx, masp_tx_section_t *maspTx);

#ifdef __cplusplus
}
#endif
36 changes: 4 additions & 32 deletions app/src/parser_impl_txn.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
********************************************************************************/
#include "parser_impl_common.h"
#include "parser_txdef.h"
#include "parser_impl_masp.h"
#include "crypto_helper.h"
#include "leb128.h"
#include "bech32.h"
Expand All @@ -24,14 +25,6 @@
#include "stdbool.h"
#include <zxformat.h>

#define DISCRIMINANT_DATA 0x00
#define DISCRIMINANT_EXTRA_DATA 0x01
#define DISCRIMINANT_CODE 0x02
#define DISCRIMINANT_SIGNATURE 0x03
#define DISCRIMINANT_CIPHERTEXT 0x04
#define DISCRIMINANT_MASP_TX 0x05
#define DISCRIMINANT_MASP_BUILDER 0x06

// Update VP types
static const vp_types_t vp_user = { "vp_user.wasm", "User"};
static const vp_types_t vp_validator = { "vp_validator.wasm", "Validator"};
Expand Down Expand Up @@ -1084,26 +1077,6 @@ static parser_error_t readCodeSection(parser_context_t *ctx, section_t *code) {
return parser_ok;
}

#if(0)
static parser_error_t readCiphertext(parser_context_t *ctx, section_t *ciphertext) {
(void) ctx;
(void) ciphertext;
return parser_ok;
}


static parser_error_t readMaspTx(parser_context_t *ctx, section_t *maspTx) {
ctx->offset += 1171; // <- Transfer 2 // Transfer 1 -> 2403;//todo figure out correct number, fix this hack
(void) maspTx;
return parser_ok;
}

static parser_error_t readMaspBuilder(parser_context_t *ctx, section_t *maspBuilder) {
ctx->offset += 941; // <- Transfer 2 // Transfer 1 -> 3060; //todo figure out correct number, fix this hack
(void) maspBuilder;
return parser_ok;
}
#endif
parser_error_t readSections(parser_context_t *ctx, parser_tx_t *v) {
if (ctx == NULL || v == NULL) {
return parser_unexpected_value;
Expand Down Expand Up @@ -1151,19 +1124,18 @@ parser_error_t readSections(parser_context_t *ctx, parser_tx_t *v) {
signature->idx = i+1;
break;
}
#if(0)
case DISCRIMINANT_CIPHERTEXT:
CHECK_ERROR(readCiphertext(ctx, &v->transaction.sections.ciphertext))
//CHECK_ERROR(readCiphertext(ctx, &v->transaction.sections.ciphertext))
break;

case DISCRIMINANT_MASP_TX:
CHECK_ERROR(readMaspTx(ctx, &v->transaction.sections.maspTx))
break;

case DISCRIMINANT_MASP_BUILDER:
CHECK_ERROR(readMaspBuilder(ctx, &v->transaction.sections.maspBuilder))
//CHECK_ERROR(readMaspBuilder(ctx, &v->transaction.sections.maspBuilder))
break;
#endif

default:
return parser_unexpected_field;
}
Expand Down
Loading

0 comments on commit bbbe662

Please sign in to comment.