Skip to content

Commit

Permalink
parser parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
abenso committed Nov 22, 2024
1 parent e17a549 commit dbcdd71
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 29 deletions.
1 change: 1 addition & 0 deletions app/rust/include/rslib.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ int32_t rs_bech32_encode(const uint8_t *hrp_ptr, size_t hrp_len, const uint8_t *

parser_error_t rs_compute_effect_hash(transaction_plan_t *plan, uint8_t *output, size_t output_len);

parser_error_t rs_parameter_hash(bytes_t *data, uint8_t *output, size_t output_len);
parser_error_t rs_spend_action_hash(spend_key_bytes_t *sk, spend_plan_t *plan, uint8_t *output, size_t output_len);
parser_error_t rs_output_action_hash(spend_key_bytes_t *sk, output_plan_t *plan, bytes_t *memo_key, uint8_t *output,
size_t output_len);
Expand Down
5 changes: 5 additions & 0 deletions app/rust/src/parser/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ use crate::parser::effect_hash::{create_personalized_state, EffectHash};

use super::bytes::BytesC;

#[repr(C)]
#[derive(Copy, Clone)]
#[cfg_attr(any(feature = "derive-debug", test), derive(Debug))]
pub struct ParametersHash(pub [u8; 64]);

#[repr(C)]
#[derive(Clone)]
#[cfg_attr(any(feature = "derive-debug", test), derive(Debug))]
Expand Down
49 changes: 31 additions & 18 deletions app/rust/src/parser/plans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ use crate::parser::{
use crate::keys::spend_key::SpendKeyBytes;
use crate::parser::effect_hash::EffectHash;
use crate::parser::bytes::BytesC;
use crate::parser::parameters::TransactionParametersC;
use crate::ParserError;
use crate::constants::EFFECT_HASH_LEN;
use crate::parser::parameters::ParametersHash;

pub mod output;
pub mod spend;
Expand All @@ -35,7 +35,7 @@ pub mod spend;
#[cfg_attr(any(feature = "derive-debug", test), derive(Debug))]
pub struct TransactionPlanC {
pub actions_hashes: ActionsHashC,
pub transaction_parameters: TransactionParametersC,
pub parameters_hash: ParametersHash,
pub memo: MemoPlanC,
pub detection_data: DetectionDataPlanC,
}
Expand All @@ -46,7 +46,7 @@ impl TransactionPlanC {
.personal(b"PenumbraEfHs")
.to_state();

state.update(self.transaction_parameters.effect_hash().as_array());
state.update(&self.parameters_hash.0);
state.update(self.memo.effect_hash()?.as_array());
state.update(self.detection_data.effect_hash()?.as_array());

Expand Down Expand Up @@ -87,6 +87,33 @@ pub unsafe extern "C" fn rs_compute_effect_hash(
ParserError::Ok as u32
}

#[no_mangle]
/// Use to compute an address and write it back into output
/// argument.
pub unsafe extern "C" fn rs_parameter_hash(
data: &BytesC,
output: *mut u8,
output_len: usize,
) -> u32 {
crate::zlog("rs_parameter_hash\x00");
let output = std::slice::from_raw_parts_mut(output, output_len);

if output.len() < 64 {
return ParserError::Ok as u32;
}

let effect_hash: EffectHash;
if let Ok(data_to_hash) = data.get_bytes() {
effect_hash = EffectHash::from_proto_effecting_data("/penumbra.core.transaction.v1.TransactionParameters", data_to_hash);

let body_hash_array = effect_hash.as_bytes();
let copy_len: usize = core::cmp::min(output.len(), body_hash_array.len());
output[..copy_len].copy_from_slice(&body_hash_array[..copy_len]);
}

ParserError::Ok as u32
}

#[no_mangle]
/// Use to compute an address and write it back into output
/// argument.
Expand Down Expand Up @@ -203,7 +230,6 @@ mod tests {
use crate::parser::memo::MemoPlanC;
use crate::parser::memo_plain_text::MemoPlaintextC;
use crate::parser::value::ValueC;
use crate::parser::parameters::TransactionParametersC;
use crate::parser::action::ActionHash;
#[test]
fn test_transaction_plan_hash() {
Expand All @@ -212,13 +238,6 @@ mod tests {
hashes: core::array::from_fn(|_| ActionHash([0u8; 64])),
};

// Create dummy TransactionParametersC
let transaction_parameters_bytes =
hex::decode("120d70656e756d6272612d746573741a020a00").unwrap();
let dummy_transaction_parameters = TransactionParametersC {
bytes: BytesC::from_slice(&transaction_parameters_bytes),
};

// Create dummy MemoPlanC
let memo_key_bytes =
hex::decode("18bd5cedd0eb952244a296c1e3fba4f417ebdcc1cfec04cb9441a394316a58bd")
Expand Down Expand Up @@ -268,17 +287,11 @@ mod tests {
// Create TransactionPlanC with dummy data
let transaction_plan = TransactionPlanC {
actions_hashes: dummy_action_hashes,
transaction_parameters: dummy_transaction_parameters,
parameters_hash: ParametersHash([0u8; 64]),
memo: dummy_memo_plan,
detection_data: dummy_detection_data,
};

let transaction_parameters_effect_hash =
transaction_plan.transaction_parameters.effect_hash();
let expected_hash = "e2b552c4c11e0bc5df75f22945c39d2c5acb6c38582716a1dd7d87e1cfa4043b9c32b350d927a9ae39f18b45b25f638947fa82e405a3c6ca7ea91248f9fa5ab7";
let computed_hash = hex::encode(transaction_parameters_effect_hash.as_array());
assert_eq!(computed_hash, expected_hash);


let memo_effect_hash = transaction_plan.memo.effect_hash();
let expected_hash = "0954149b3feec5d414a22d47ce4e69f895f52431db9fdf7adf0bb5325c2520540357b206b5a04ec8685aea0e69a93a679fcb5c220cff85ebecc3d65c6d82b4d1";
Expand Down
7 changes: 7 additions & 0 deletions app/src/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,20 @@ zxerr_t crypto_sign(parser_tx_t *tx_obj, uint8_t *signature, uint16_t signatureM
keys_t keys = {0};
zxerr_t error = zxerr_invalid_crypto_settings;


// compute parameters hash
CATCH_ZX_ERROR(compute_parameters_hash(&tx_obj->parameters_plan.data_bytes, &tx_obj->plan.parameters_hash));

// compute spend key
CATCH_ZX_ERROR(computeSpendKey(&keys));

// compute action hashes
for (uint16_t i = 0; i < tx_obj->plan.actions.qty; i++) {
CATCH_ZX_ERROR(compute_action_hash(&tx_obj->actions_plan[i], &keys.skb, &tx_obj->plan.memo.key,
&tx_obj->plan.actions.hashes[i]));
}

// compute effect hash
CATCH_ZX_ERROR(compute_effect_hash(&tx_obj->plan, tx_obj->effect_hash, sizeof(tx_obj->effect_hash)));

MEMCPY(signature, tx_obj->effect_hash, EFFECT_HASH_LEN);
Expand Down
20 changes: 19 additions & 1 deletion app/src/parser_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ parser_error_t _read(parser_context_t *c, parser_tx_t *v) {
request.actions.funcs.decode = &decode_action;
request.actions.arg = &v->actions_plan;

// parameters callbacks
fixed_size_field_t parameter_asset_id_arg;
variable_size_field_t parameter_chain_id_arg;
setup_decode_variable_field(&request.transaction_parameters.chain_id, &parameter_chain_id_arg, &v->parameters_plan.chain_id);
setup_decode_fixed_field(&request.transaction_parameters.fee.asset_id.inner, &parameter_asset_id_arg, &v->parameters_plan.fee.asset_id.inner, ASSET_ID_LEN);

// detection data callbacks
request.detection_data.clue_plans.funcs.decode = &decode_detection_data;
request.detection_data.clue_plans.arg = &v->plan.detection_data.clue_plans;
Expand All @@ -144,10 +150,22 @@ parser_error_t _read(parser_context_t *c, parser_tx_t *v) {
}

// get transaction parameters
extract_data_from_tag(&data, &v->plan.transaction_parameters.parameters,
extract_data_from_tag(&data, &v->parameters_plan.data_bytes,
penumbra_core_transaction_v1_TransactionPlan_transaction_parameters_tag);
v->plan.actions.qty = actions_qty;

// copy parameters
v->parameters_plan.expiry_height = request.transaction_parameters.expiry_height;
v->parameters_plan.has_fee = request.transaction_parameters.has_fee;
if (v->parameters_plan.has_fee) {
v->parameters_plan.fee.has_amount = request.transaction_parameters.fee.has_amount;
if (v->parameters_plan.fee.has_amount) {
v->parameters_plan.fee.amount.lo = request.transaction_parameters.fee.amount.lo;
v->parameters_plan.fee.amount.hi = request.transaction_parameters.fee.amount.hi;
}
v->parameters_plan.fee.has_asset_id = request.transaction_parameters.fee.has_asset_id;
}

return parser_ok;
}

Expand Down
12 changes: 11 additions & 1 deletion app/src/parser_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,17 @@ zxerr_t compute_effect_hash(transaction_plan_t *plan, uint8_t *effect_hash, uint
return zxerr_ok;
}

zxerr_t compute_action_hash(action_t *action, spend_key_bytes_t *sk_bytes, bytes_t *memo_key, action_hash_t *output) {
zxerr_t compute_parameters_hash(bytes_t *parameters_bytes, hash_t *output) {
if (parameters_bytes == NULL || output == NULL) return zxerr_unknown;

if (rs_parameter_hash(parameters_bytes, (uint8_t *)output, 64) != parser_ok) {
return zxerr_unknown;
}

return zxerr_ok;
}

zxerr_t compute_action_hash(action_t *action, spend_key_bytes_t *sk_bytes, bytes_t *memo_key, hash_t *output) {
if (action == NULL || output == NULL) return zxerr_unknown;

switch (action->action_type) {
Expand Down
3 changes: 2 additions & 1 deletion app/src/parser_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ extern "C" {
#include "zxerror.h"
#include "zxmacros.h"

zxerr_t compute_parameters_hash(bytes_t *parameters_bytes, hash_t *output);
zxerr_t compute_effect_hash(transaction_plan_t *plan, uint8_t *effect_hash, uint16_t effect_hash_len);
zxerr_t compute_action_hash(action_t *action, spend_key_bytes_t *sk_bytes, bytes_t *memo_key, action_hash_t *output);
zxerr_t compute_action_hash(action_t *action, spend_key_bytes_t *sk_bytes, bytes_t *memo_key, hash_t *output);

#ifdef __cplusplus
}
Expand Down
29 changes: 21 additions & 8 deletions app/src/parser_txdef.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ extern "C" {

#define ASSET_ID_LEN 32
#define RSEED_LEN 32
#define CHAIN_ID_LEN 32

typedef struct {
const uint8_t *ptr;
Expand Down Expand Up @@ -76,6 +77,13 @@ typedef struct {
uint64_t start_height;
} epoch_t;

typedef struct {
bool has_amount;
amount_t amount;
bool has_asset_id;
asset_id_t asset_id;
} fee_t;

typedef struct {
note_t note;
uint64_t position;
Expand Down Expand Up @@ -115,11 +123,6 @@ typedef struct {
bool has_from_epoch;
epoch_t from_epoch;
} undelegate_plan_t;

typedef struct {
bytes_t parameters;
} transaction_parameters_t;

typedef struct {
address_plan_t return_address;
bytes_t text;
Expand Down Expand Up @@ -151,22 +154,32 @@ typedef struct {
} action;
} action_t;

typedef uint8_t action_hash_t[64];
typedef uint8_t hash_t[64];
typedef struct {
uint8_t qty;
action_hash_t hashes[ACTIONS_QTY];
hash_t hashes[ACTIONS_QTY];
} actions_hash_t;

typedef struct {
uint64_t expiry_height;
bytes_t chain_id;
bool has_fee;
fee_t fee;
bytes_t data_bytes;
} parameters_t;


typedef struct {
actions_hash_t actions;
transaction_parameters_t transaction_parameters;
hash_t parameters_hash;
memo_plan_t memo;
detection_data_t detection_data;
} transaction_plan_t;

typedef struct {
transaction_plan_t plan;
action_t actions_plan[ACTIONS_QTY];
parameters_t parameters_plan;
uint8_t effect_hash[64];
} parser_tx_t;

Expand Down
6 changes: 6 additions & 0 deletions tests/parser_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,18 @@ TEST(SCALE, ReadBytes) {
err = parser_parse(&ctx, buffer, bufferLen, &tx_obj);
ASSERT_EQ(err, parser_ok) << parser_getErrorDescription(err);

// compute parameters hash
zxerr = compute_parameters_hash(&tx_obj.parameters_plan.data_bytes, &tx_obj.plan.parameters_hash);
ASSERT_EQ(zxerr, zxerr_ok);

// compute action hashes
for (uint16_t i = 0; i < tx_obj.plan.actions.qty; i++) {
zxerr = compute_action_hash(&tx_obj.actions_plan[i], &sk_bytes, &tx_obj.plan.memo.key,
&tx_obj.plan.actions.hashes[i]);
ASSERT_EQ(zxerr, zxerr_ok);
}

// compute effect hash
zxerr = compute_effect_hash(&tx_obj.plan, tx_obj.effect_hash, sizeof(tx_obj.effect_hash));
ASSERT_EQ(zxerr, zxerr_ok);

Expand Down
4 changes: 4 additions & 0 deletions tests/plan_effect_hash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ void check_testcase(const testcase_t &tc, bool expert_mode) {
err = parser_parse(&ctx, buffer, bufferLen, &tx_obj);
ASSERT_EQ(err, parser_ok) << parser_getErrorDescription(err);

// compute parameters hash
zxerr = compute_parameters_hash(&tx_obj.parameters_plan.data_bytes, &tx_obj.plan.parameters_hash);
ASSERT_EQ(zxerr, zxerr_ok);

for (uint16_t i = 0; i < tx_obj.plan.actions.qty; i++) {
zxerr = compute_action_hash(&tx_obj.actions_plan[i], &sk_bytes, &tx_obj.plan.memo.key,
&tx_obj.plan.actions.hashes[i]);
Expand Down

0 comments on commit dbcdd71

Please sign in to comment.