diff --git a/Makefile b/Makefile index d60f433..a838527 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ TARGET_BIN = multihash MAIN = src/main.c MAIN_O = $(MAIN:.c=.o) -SRCS = src/hashes.c src/errors.c +SRCS = src/hashes.c src/errors.c src/multihash.c OBJS = $(SRCS:.c=.o) src/%.o: src/%.c diff --git a/include/mh/errors.h b/include/mh/errors.h index 369e7b7..77abbdb 100644 --- a/include/mh/errors.h +++ b/include/mh/errors.h @@ -6,7 +6,7 @@ #define MH_E_UNKNOWN_CODE -1 #define MH_E_TOO_SHORT -2 #define MH_E_TOO_LONG -3 -#define MH_E_LEN_NOT_SUPPORTED -4 +#define MH_E_VARINT_NOT_SUPPORTED -4 #define MH_E_LAST -5 diff --git a/include/mh/hashes.h b/include/mh/hashes.h index 5d35cf5..787fb21 100644 --- a/include/mh/hashes.h +++ b/include/mh/hashes.h @@ -35,12 +35,3 @@ const char *mh_hash_name(int hash); // returns length in bytes or if returns is < 0 it is an error int mh_hash_default_length(int hash); - -int mh_hash_length(const unsigned char multihash[], int len, int *hash_length); - -int mh_hash_function(const unsigned char multihash[], int len, int *hash); - - - - - diff --git a/include/mh/multihash.h b/include/mh/multihash.h new file mode 100644 index 0000000..23c3448 --- /dev/null +++ b/include/mh/multihash.h @@ -0,0 +1,10 @@ +#ifndef MH_HULTIHASH_H +#define MH_HULTIHASH_H + +// returns hash code or error (which is < 0) +int mh_multihash_hash(const unsigned char multihash[], int len); + +// returns length of multihash or error (which is < 0) +int mh_multihash_length(const unsigned char multihash[], int len); + +#endif /* end of include guard */ diff --git a/src/errors.c b/src/errors.c index 702e04b..5b66188 100644 --- a/src/errors.c +++ b/src/errors.c @@ -7,12 +7,12 @@ const char *mh_error_string(int code) { case MH_E_UNKNOWN_CODE: return "unknown multihash code"; case MH_E_TOO_SHORT: - return "multihash too short. must be > 3 bytes"; + return "multihash too short. must be > 2 bytes"; case MH_E_TOO_LONG: return "multihash too long. must be < 129 bytes"; - case MH_E_LEN_NOT_SUPPORTED: - return "multihash does not yet support" - " digsets linger than 127 bytes"; + case MH_E_VARINT_NOT_SUPPORTED: + return "c-multihash does not yet support" + " varint encoding"; default: return "unknown error code"; } diff --git a/src/multihash.c b/src/multihash.c new file mode 100644 index 0000000..667040d --- /dev/null +++ b/src/multihash.c @@ -0,0 +1,39 @@ +#include "mh/multihash.h" + +#include "mh/hashes.h" +#include "mh/errors.h" + +#define VARINT_MASK (1 << 7) + +static int check_multihash(const unsigned char mh[], int len) { + if (len < 3) { + return MH_E_TOO_SHORT; + } else if (len >= 129) { + return MH_E_TOO_LONG; + } else if (mh[0] & VARINT_MASK) { + // In near future multihash format will be + // extended with varints, this is how we are protecting + // against it. + return MH_E_VARINT_NOT_SUPPORTED; + } else if (mh[1] & VARINT_MASK) { + return MH_E_VARINT_NOT_SUPPORTED; + } + return MH_E_NO_ERROR; +} + + +// returns hash code or error (which is < 0) +int mh_multihash_hash(const unsigned char mh[], int len) { + if (check_multihash(mh, len)) + return check_multihash(mh, len); + return (int) mh[0]; +} + + +// returns length of multihash or error (which is < 0) +int mh_multihash_length(const unsigned char mh[], int len) { + if (check_multihash(mh, len)) + return check_multihash(mh, len); + return (int) mh[1]; +} + diff --git a/tests/c/minunit.h b/tests/c/minunit.h index 7804497..83bf5cb 100644 --- a/tests/c/minunit.h +++ b/tests/c/minunit.h @@ -1,7 +1,8 @@ #include #define mu_assert(message, test) do { if (!(test)) return message; } while (0) -#define mu_run_test(test) do { char *message = test(); tests_run++; \ +#define mu_run_test(test) do { char *message; printf(" - run: %s\n", #test); \ + message = test(); tests_run++; \ if (message) return message; } while (0) int tests_run = 0; static char *mu_all_tests(void); diff --git a/tests/c/test_multihash_decoding.c b/tests/c/test_multihash_decoding.c new file mode 100644 index 0000000..8a3348a --- /dev/null +++ b/tests/c/test_multihash_decoding.c @@ -0,0 +1,42 @@ +#include +#include "minunit.h" +#include "mh/multihash.h" + +#include "mh/hashes.h" + +#include "examples.h" + +char error_buf[256]; + +static char *test_multihash_hash_decoding_works(void) { + mu_assert("sha1 multihash is detected as sha1", + mh_multihash_hash(sha1_example, sizeof(sha1_example)) + == MH_H_SHA1); + mu_assert("sha2 multihash is detected as sha2", + mh_multihash_hash(sha2_example, sizeof(sha2_example)) + == MH_H_SHA2_256); + mu_assert("sha3 multihash is detected as sha3", + mh_multihash_hash(sha3_example, sizeof(sha3_example)) + == MH_H_SHA3_512); + return NULL; +} + +static char *test_multihash_length_decoding_works(void) { + mu_assert("sha1 multihash has correct length", + mh_multihash_length(sha1_example, sizeof(sha1_example)) + == mh_hash_default_length(MH_H_SHA1)); + mu_assert("sha2 multihash has correct length", + mh_multihash_length(sha2_example, sizeof(sha2_example)) + == mh_hash_default_length(MH_H_SHA2_256)); + mu_assert("sha3-512 multihash has correct length", + mh_multihash_length(sha3_example, sizeof(sha3_example)) + == mh_hash_default_length(MH_H_SHA3_512)); + return NULL; +} + +static char *mu_all_tests(void) { + mu_run_test(test_multihash_hash_decoding_works); + mu_run_test(test_multihash_length_decoding_works); + return NULL; +} +