Skip to content

Commit

Permalink
Merge pull request #68 from trilitech/palmer@functori@document-the-co…
Browse files Browse the repository at this point in the history
…de-part-2

Document the code - Part 2
  • Loading branch information
ajinkyaraj-23 authored Mar 13, 2024
2 parents 54ddde1 + 876ce55 commit 877b9fd
Show file tree
Hide file tree
Showing 21 changed files with 1,095 additions and 401 deletions.
8 changes: 4 additions & 4 deletions .doxygen/Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ TIMESTAMP = NO
# normally produced when WARNINGS is set to YES.
# The default value is: NO.

EXTRACT_ALL = YES
EXTRACT_ALL = NO

# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation.
Expand Down Expand Up @@ -877,15 +877,15 @@ WARN_IF_INCOMPLETE_DOC = YES
# WARN_IF_INCOMPLETE_DOC
# The default value is: NO.

WARN_NO_PARAMDOC = NO
WARN_NO_PARAMDOC = YES

# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about
# undocumented enumeration values. If set to NO, doxygen will accept
# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled.
# The default value is: NO.

WARN_IF_UNDOC_ENUM_VAL = NO
WARN_IF_UNDOC_ENUM_VAL = YES

# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
Expand All @@ -901,7 +901,7 @@ WARN_IF_UNDOC_ENUM_VAL = NO
# Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT.
# The default value is: NO.

WARN_AS_ERROR = NO
WARN_AS_ERROR = YES

# The WARN_FORMAT tag determines the format of the warning messages that doxygen
# can produce. The string should contain the $file, $line, and $text tags, which
Expand Down
3 changes: 3 additions & 0 deletions src/apdu_setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ size_t handle_apdu_deauthorize(__attribute__((unused)) uint8_t instruction,
THROW(EXC_PARSE_ERROR);
}
UPDATE_NVRAM(ram, { memset(&ram->baking_key, 0, sizeof(ram->baking_key)); });
#ifdef HAVE_BAGL
update_baking_idle_screens();
#endif // HAVE_BAGL

return finalize_successful_send(0);
}
109 changes: 81 additions & 28 deletions src/baking_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ void authorize_baking(derivation_type_t const derivation_type,
});
}

/**
* @brief Checks if a baking info pass all checks
*
* See `doc/signing.md#checks`
*
* @param baking_info: baking info
* @return bool: return true if it has passed checks
*/
static bool is_level_authorized(parsed_baking_data_t const *const baking_info) {
check_null(baking_info);
if (!is_valid_level(baking_info->level)) {
Expand Down Expand Up @@ -104,6 +112,13 @@ static bool is_level_authorized(parsed_baking_data_t const *const baking_info) {
}
}

/**
* @brief Checks if a key pass the checks
*
* @param derivation_type: curve of the key
* @param bip32_path: bip32 path of the key
* @return bool: return true if it has passed checks
*/
bool is_path_authorized(derivation_type_t const derivation_type,
bip32_path_t const *const bip32_path) {
check_null(bip32_path);
Expand All @@ -124,43 +139,46 @@ void guard_baking_authorized(parsed_baking_data_t const *const baking_info,
}
}

/**
* @brief Raw representation of block
*
* All information of the block are not parsed here.
*
* Except the fitness placed just after fitness size, the rest
* of the block content is not important for our checks
*
* Fitness =
* - tag_size(4) + tag(1) +
* - level_size(4) + level(4) +
* - locked_round_size(4) + locked_round(0|4) +
* - predecessor_round_size(4) + predecessor_round(4) +
* - current_round_size(4) + current_round(4)
*
*/
struct block_wire {
uint8_t magic_byte;
uint32_t chain_id;
uint32_t level;
uint8_t proto;
uint8_t predecessor[32];
uint64_t timestamp;
uint8_t validation_pass;
uint8_t operation_hash[32];
uint32_t fitness_size;
uint8_t magic_byte; ///< magic bytes, should be 0x11
uint32_t chain_id; ///< chain id of the block
uint32_t level; ///< height of the block, from the genesis block
uint8_t proto; ///< protocol number
uint8_t predecessor[32]; ///< hash of the preceding block
uint64_t timestamp; ///< timestamp at which the block have been created
uint8_t validation_pass; ///< number of validation passes
uint8_t operation_hash[32]; ///< hash of the operations
uint32_t fitness_size; ///< size of the fitness
// ... beyond this we don't care
} __attribute__((packed));

struct consensus_op_wire {
uint8_t magic_byte;
uint32_t chain_id;
uint8_t branch[32];
uint8_t tag;
uint16_t slot;
uint32_t level;
uint32_t round;
uint8_t block_payload_hash[32];
} __attribute__((packed));

/**
* Fitness =
* - tag_size(4) + tag(1) +
* - level_size(4) + level(4) +
* - locked_round_size(4) + locked_round(0|4) +
* - predecessor_round_size(4) + predecessor_round(4) +
* - current_round_size(4) + current_round(4)
*/
#define MINIMUM_FITNESS_SIZE 33 // When 'locked_round' == none
#define MAXIMUM_FITNESS_SIZE 37 // When 'locked_round' != none

#define TENDERBAKE_PROTO_FITNESS_VERSION 2

/**
* @brief Get the protocol version from fitness
*
* @param fitness: fitness
* @return uint8_t: protocol version result
*/
uint8_t get_proto_version(void const *const fitness) {
// Each field is preceded by its size (uint32_t).
// That's why we need to look at `sizeof(uint32_t)` bytes after
Expand All @@ -171,6 +189,14 @@ uint8_t get_proto_version(void const *const fitness) {
return READ_UNALIGNED_BIG_ENDIAN(uint8_t, fitness + sizeof(uint32_t));
}

/**
* @brief Parse a block
*
* @param out: baking data output
* @param data: input
* @param length: input length
* @return bool: returns false if it is invalid
*/
bool parse_block(parsed_baking_data_t *const out, void const *const data, size_t const length) {
if (length < sizeof(struct block_wire) + MINIMUM_FITNESS_SIZE) {
return false;
Expand All @@ -196,6 +222,33 @@ bool parse_block(parsed_baking_data_t *const out, void const *const data, size_t
return true;
}

/**
* @brief Raw representation of a consensus operation
*
* - Pre-attestation , tag: 20
* - Attestation , tag: 21
* - Attestation + DAL, tag: 23
*
*/
struct consensus_op_wire {
uint8_t magic_byte; ///< magic bytes, should be 0x12, or 0x13
uint32_t chain_id; ///< chain id of the block
uint8_t branch[32]; ///< block branch
uint8_t tag; ///< operation tag
uint16_t slot; ///< first slot of the baker
uint32_t level; ///< level of the related block
uint32_t round; ///< round of the related block
uint8_t block_payload_hash[32]; ///< hash of the related block
} __attribute__((packed));

/**
* @brief Parse a consensus operation
*
* @param out: baking data output
* @param data: input
* @param length: input length
* @return bool: returns false if it is invalid
*/
bool parse_consensus_operation(parsed_baking_data_t *const out,
void const *const data,
size_t const length) {
Expand Down
39 changes: 35 additions & 4 deletions src/baking_auth.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,47 @@
#include <stdbool.h>
#include <stdint.h>

/**
* @brief Authorizes a key
*
* @param derivation_type: curve of the key
* @param bip32_path: bip32 path of the key
*/
void authorize_baking(derivation_type_t const derivation_type,
bip32_path_t const *const bip32_path);
void guard_baking_authorized(parsed_baking_data_t const *const baking_data,

/**
* @brief Guards baking info and key pass required checks
*
* @param baking_info: baking info to check
* @param key: key to check
*/
void guard_baking_authorized(parsed_baking_data_t const *const baking_info,
bip32_path_with_curve_t const *const key);
bool is_path_authorized(derivation_type_t const derivation_type,
bip32_path_t const *const bip32_path);

/**
* @brief Checks if a level is valid
*
* @param level: level
* @return bool: if the level is valid
*/
bool is_valid_level(level_t level);

/**
* @brief Stores baking info into the NVRAM
*
* @param in: baking info
*/
void write_high_water_mark(parsed_baking_data_t const *const in);

// Return false if it is invalid
/**
* @brief Parses a baking data
*
* @param out: baking data output
* @param data: input
* @param length: input length
* @return bool: returns false if it is invalid
*/
bool parse_baking_data(parsed_baking_data_t *const out,
void const *const data,
size_t const length);
17 changes: 13 additions & 4 deletions src/exception.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@
// Throw this to indicate prompting
#define ASYNC_EXCEPTION 0x2000

// Standard APDU error codes:
// https://www.eftlab.co.uk/index.php/site-map/knowledge-base/118-apdu-response-list

/**
* @brief Standard APDU error codes
*
* https://www.eftlab.co.uk/index.php/site-map/knowledge-base/118-apdu-response-list
*
*/
#define EXC_WRONG_PARAM 0x6B00
#define EXC_WRONG_LENGTH 0x6C00
#define EXC_INVALID_INS 0x6D00
Expand All @@ -41,7 +44,13 @@
#define EXC_CLASS 0x6E00
#define EXC_MEMORY_ERROR 0x9200

// Crashes can be harder to debug than exceptions and latency isn't a big concern
/**
* @brief Checks if a pointer is NULL
*
* Crashes can be harder to debug than exceptions and latency isn't a big concern
*
* @param ptr: pointer
*/
static inline void check_null(void volatile const *const ptr) {
if (ptr == NULL) {
THROW(EXC_MEMORY_ERROR);
Expand Down
Loading

0 comments on commit 877b9fd

Please sign in to comment.