Skip to content

Commit

Permalink
Add trinary and input validators. (#13)
Browse files Browse the repository at this point in the history
* added trits/trytes validations.

* Added input validators.

* fixed code style and typo.

* Added test_is_address_with_checksum.
  • Loading branch information
Sam Chen authored Feb 3, 2020
1 parent 50aeee0 commit f0afbcb
Show file tree
Hide file tree
Showing 14 changed files with 471 additions and 1 deletion.
3 changes: 3 additions & 0 deletions common/model/transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ extern "C" {
#define NUM_TRITS_ATTACHMENT_TIMESTAMP_UPPER 27
#define NUM_TRITS_NONCE 81
#define NUM_TRITS_HASH 243
#define NUM_TRITS_CHECKSUM 27

#define NUM_TRYTES_SERIALIZED_TRANSACTION 2673
#define NUM_TRYTES_SIGNATURE 2187
Expand All @@ -54,6 +55,7 @@ extern "C" {
#define NUM_TRYTES_ATTACHMENT_TIMESTAMP_UPPER 9
#define NUM_TRYTES_NONCE 27
#define NUM_TRYTES_HASH 81
#define NUM_TRYTES_CHECKSUM 9

#define NUM_FLEX_TRITS_SERIALIZED_TRANSACTION FLEX_TRIT_SIZE_8019
#define NUM_FLEX_TRITS_SIGNATURE FLEX_TRIT_SIZE_6561
Expand All @@ -73,6 +75,7 @@ extern "C" {
#define NUM_FLEX_TRITS_ATTACHMENT_TIMESTAMP_UPPER FLEX_TRIT_SIZE_27
#define NUM_FLEX_TRITS_NONCE FLEX_TRIT_SIZE_81
#define NUM_FLEX_TRITS_HASH FLEX_TRIT_SIZE_243
#define NUM_FLEX_TRITS_CHECKSUM FLEX_TRIT_SIZE_27

// bundle essence = 486 trits
#define NUM_TRITS_ESSENCE \
Expand Down
2 changes: 2 additions & 0 deletions common/trinary/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ cc_library(

cc_library(
name = "trits",
srcs = ["trits.c"],
hdrs = ["trits.h"],
deps = [
"//common:stdint",
Expand All @@ -18,6 +19,7 @@ cc_library(

cc_library(
name = "tryte",
srcs = ["tryte.c"],
hdrs = ["tryte.h"],
deps = [
"//common:stdint",
Expand Down
22 changes: 21 additions & 1 deletion common/trinary/tests/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ cc_test(
)

cc_test(
name = "test_tryte",
name = "test_trit_tryte",
timeout = "short",
srcs = ["test_trit_tryte.c"],
deps = [
Expand Down Expand Up @@ -88,3 +88,23 @@ cc_test(
"@unity",
],
)

cc_test(
name = "test_trits",
timeout = "short",
srcs = ["test_trits.c"],
deps = [
"//common/trinary:trits",
"@unity",
],
)

cc_test(
name = "test_tryte",
timeout = "short",
srcs = ["test_tryte.c"],
deps = [
"//common/trinary:tryte",
"@unity",
],
)
57 changes: 57 additions & 0 deletions common/trinary/tests/test_trits.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2020 IOTA Stiftung
* https://github.com/iotaledger/iota_common
*
* Refer to the LICENSE file for licensing information
*/

#include <stdio.h>
#include <unity/unity.h>

#include "common/trinary/trits.h"

void test_is_trits(void) {
const trit_t tryte_LUT[27][3] = {
{0, 0, 0}, {1, 0, 0}, {-1, 1, 0}, {0, 1, 0}, {1, 1, 0}, {-1, -1, 1}, {0, -1, 1}, {1, -1, 1}, {-1, 0, 1},
{0, 0, 1}, {1, 0, 1}, {-1, 1, 1}, {0, 1, 1}, {1, 1, 1}, {-1, -1, -1}, {0, -1, -1}, {1, -1, -1}, {-1, 0, -1},
{0, 0, -1}, {1, 0, -1}, {-1, 1, -1}, {0, 1, -1}, {1, 1, -1}, {-1, -1, 0}, {0, -1, 0}, {1, -1, 0}, {-1, 0, 0}};

for (size_t i = 0; i < 27; i++) {
printf("tryte LUT checking %ld\n", i);
TEST_ASSERT(is_trits(tryte_LUT[i], 3) == true);
}

const trit_t ng_tryte[6][3] = {{2, 0, 0}, {1, 3, 0}, {-1, 1, 4}, {-2, 1, 0}, {1, -3, 0}, {-1, -1, -4}};
for (size_t i = 0; i < 6; i++) {
printf("ng_tryte checking %ld\n", i);
TEST_ASSERT(is_trits(ng_tryte[i], 3) == false);
}

const trit_t trytes_LUT[14][6] = {{0, 0, 0, 1, 0, 0}, {-1, 1, 0, 0, 1, 0}, {1, 1, 0, -1, -1, 1},
{0, -1, 1, 1, -1, 1}, {-1, 0, 1, 0, 0, 1}, {1, 0, 1, -1, 1, 1},
{0, 1, 1, 1, 1, 1}, {-1, -1, -1, 0, -1, -1}, {1, -1, -1, -1, 0, -1},
{0, 0, -1, 1, 0, -1}, {-1, 1, -1, 0, 1, -1}, {1, 1, -1, -1, -1, 0},
{0, -1, 0, 1, -1, 0}, {-1, 0, 0, 1, 1, 1}};
for (size_t i = 0; i < 14; i++) {
printf("trytes LUT checking %ld\n", i);
TEST_ASSERT(is_trits(trytes_LUT[i], 6) == true);
}

const trit_t ng_trytes[14][6] = {{2, 0, 0, 1, 0, 0}, {-1, 3, 0, 0, 1, 0}, {1, 1, 4, -1, -1, 1},
{0, -1, 1, 5, -1, 1}, {-1, 0, 1, 0, 6, 1}, {1, 0, 1, -1, 1, 7},
{-2, 1, 1, 1, 1, 1}, {-1, -3, -1, 0, -1, -1}, {1, -1, -4, -1, 0, -1},
{0, 0, -1, -5, 0, -1}, {-1, 1, -1, 0, -6, -1}, {1, 1, -1, -1, -1, -7},
{0, -1, 0, 1, -10, 0}, {-1, 10, 0, 1, 1, 1}};
for (size_t i = 0; i < 14; i++) {
printf("ng_trytes LUT checking %ld\n", i);
TEST_ASSERT(is_trits(ng_trytes[i], 6) == false);
}
}

int main(void) {
UNITY_BEGIN();

RUN_TEST(test_is_trits);

return UNITY_END();
}
34 changes: 34 additions & 0 deletions common/trinary/tests/test_tryte.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2020 IOTA Stiftung
* https://github.com/iotaledger/iota_common
*
* Refer to the LICENSE file for licensing information
*/

#include <stdio.h>
#include <unity/unity.h>

#include "common/trinary/tryte.h"

void test_is_trytes() {
tryte_t *hash0 = (tryte_t *)"XUERGHWTYRTFUYKFKXURKHMFEVLOIFTTCNTXOGLDPCZ9CJLKHROOPGNAQYFJEPGK9OKUQROUECBAVNXRX";
TEST_ASSERT(is_trytes(hash0, 81) == true);
// length is unmatched
TEST_ASSERT(is_trytes(hash0, 20) == false);

// hash with lowercases
tryte_t *hash1 = (tryte_t *)"XUERGHWTYRTFUYKFKXURKHMFEVLOIFTTCNTXOGLDPCZ9cjlkhroopgnaqyfjepgk9okuqrouecbavnxrx";
TEST_ASSERT(is_trytes(hash1, 81) == false);

// hash with invalid tryte
tryte_t *hash2 = (tryte_t *)"XUERGH3TYRTFUYKFKXURKHMF5VLOIFTTCNTXOGLDPCZ9CJLKHR0OPGNAQYFJEPGK9OKUQROUECBAVNXRX";
TEST_ASSERT(is_trytes(hash2, 81) == false);
}

int main(void) {
UNITY_BEGIN();

RUN_TEST(test_is_trytes);

return UNITY_END();
}
17 changes: 17 additions & 0 deletions common/trinary/trits.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright (c) 2020 IOTA Stiftung
* https://github.com/iotaledger/iota_common
*
* Refer to the LICENSE file for licensing information
*/

#include "common/trinary/trits.h"

bool is_trits(trit_t const *const trits, size_t len) {
for (size_t i = 0; i < len; i++) {
if (trits[i] < -1 || trits[i] > 1) {
return false;
}
}
return true;
}
19 changes: 19 additions & 0 deletions common/trinary/trits.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,27 @@
#ifndef __COMMON_TRINARY_TRIT_H_
#define __COMMON_TRINARY_TRIT_H_

#include <stdbool.h>

#include "common/stdint.h"

typedef int8_t trit_t;

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Checks if the given trits are valid.
*
* @param[in] trits A trits array.
* @param[in] len The length of trits array.
* @return boolean
*/
bool is_trits(trit_t const* const trits, size_t len);

#ifdef __cplusplus
}
#endif

#endif // __COMMON_TRINARY_TRIT_H_
25 changes: 25 additions & 0 deletions common/trinary/tryte.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (c) 2020 IOTA Stiftung
* https://github.com/iotaledger/iota_common
*
* Refer to the LICENSE file for licensing information
*/

#include <string.h>

#include "common/trinary/tryte.h"

bool is_trytes(tryte_t const *const trytes, size_t len) {
size_t trytes_cnt = strlen((char *)trytes);
if (trytes_cnt != len) {
// length does not match.
return false;
}

for (size_t i = 0; i < len; i++) {
if (trytes[i] != '9' && (trytes[i] < 'A' || trytes[i] > 'Z')) {
return false;
}
}
return true;
}
19 changes: 19 additions & 0 deletions common/trinary/tryte.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,29 @@
#ifndef __COMMON_TRINARY_TRYTE_H_
#define __COMMON_TRINARY_TRYTE_H_

#include <stdbool.h>

#include "common/stdint.h"

typedef int8_t tryte_t;

#define INDEX_OF_TRYTE(tryte) ((tryte) == '9' ? 0 : ((tryte) - 'A' + 1))

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Checks if given trytes are valid.
*
* @param[in] trytes A string of trytes.
* @param[in] len The length of the string.
* @return boolean
*/
bool is_trytes(tryte_t const *const trytes, size_t len);

#ifdef __cplusplus
}
#endif

#endif // __COMMON_TRINARY_TRYTE_H_
11 changes: 11 additions & 0 deletions utils/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,14 @@ cc_library(
hdrs = ["char_buffer.h"],
deps = ["//common:errors"],
)

cc_library(
name = "input_validators",
srcs = ["input_validators.c"],
hdrs = ["input_validators.h"],
deps = [
"//common/model:transaction",
"//common/trinary:trits",
"//common/trinary:tryte",
],
)
36 changes: 36 additions & 0 deletions utils/input_validators.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2020 IOTA Stiftung
* https://github.com/iotaledger/iota_common
*
* Refer to the LICENSE file for licensing information
*/

#include "utils/input_validators.h"
#include "common/model/transaction.h"

bool is_tryte_with_trailing_zero(tryte_t const tryte) {
if (tryte == '9' || (tryte >= 'A' && tryte <= 'D') || (tryte >= 'W' && tryte <= 'Z')) {
return true;
}
return false;
}

bool is_address(tryte_t const *const address) {
if (is_trytes(address, NUM_TRYTES_ADDRESS)) {
return is_tryte_with_trailing_zero(address[NUM_TRYTES_ADDRESS - 1]);
}
return false;
}

bool is_address_with_checksum(tryte_t const *const address) {
if (is_trytes(address, NUM_TRYTES_ADDRESS + NUM_TRYTES_CHECKSUM)) {
return is_tryte_with_trailing_zero(address[NUM_TRYTES_ADDRESS - 1]);
}
return false;
}

bool is_tag(tryte_t const *const tag) { return is_trytes(tag, NUM_TRYTES_TAG); }

bool is_seed(tryte_t const *const seed) { return is_trytes(seed, NUM_TRYTES_HASH); }

bool is_security_level(uint8_t level) { return (level >= 1 && level <= 3); }
78 changes: 78 additions & 0 deletions utils/input_validators.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright (c) 2020 IOTA Stiftung
* https://github.com/iotaledger/iota_common
*
* Refer to the LICENSE file for licensing information
*/

#ifndef __INPUT_VALIDATORS_H__
#define __INPUT_VALIDATORS_H__

#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

#include "common/trinary/trits.h"
#include "common/trinary/tryte.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Checks if a tryte with a trailing zero trit.
*
* @param[in] tryte A tryte
* @return boolean
*/
bool is_tryte_with_trailing_zero(tryte_t const tryte);

/**
* @brief Checks if the given address is valid.
*
* An address should be 81 trytes with a zero-trit at tail.
*
* @param[in] address A hash string.
* @return boolean
*/
bool is_address(tryte_t const* const address);

/**
* @brief Checks if address hash contains checksum
*
* It won't validate checksum, checks the hash length only.
*
* @param[in] address A hash string.
* @return boolean
*/
bool is_address_with_checksum(tryte_t const* const address);

/**
* @brief Checks if the given hash is a tag.
*
* @param[in] tag A hash string.
* @return boolean
*/
bool is_tag(tryte_t const* const tag);

/**
* @brief Checks if the given hash is a seed.
*
* @param[in] seed A hash string.
* @return boolean
*/
bool is_seed(tryte_t const* const seed);

/**
* @brief Checks if the given number is a security level.
*
* @param[in] level An integer.
* @return boolean
*/
bool is_security_level(uint8_t level);

#ifdef __cplusplus
}
#endif

#endif // __INPUT_VALIDATORS_H__
Loading

0 comments on commit f0afbcb

Please sign in to comment.