diff --git a/.gitignore b/.gitignore index fd92288..c5f3008 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ keyconv results.txt oclvanitygen++ vanitygen++ +run_tests \ No newline at end of file diff --git a/Makefile b/Makefile index d11fb1f..504974e 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,19 @@ -## If compiling on mac, comment out LIBS and CFLAGS below, and use the MacOS ones below +## CentOS/Redhat: +# yum install openssl-devel +# yum install libcurl-devel +# yum install check # Only need if you want to run tests + +## Ubuntu: +# apt install build-essential +# apt install libssl-dev +# apt install libpcre3-dev +# apt install libcurl4-openssl-dev +# apt install check # Only need if you want to run tests + LIBS=-lpcre -lcrypto -lm -lpthread CFLAGS=-ggdb -O3 -Wall # CFLAGS=-ggdb -O3 -Wall -I /usr/local/cuda-10.2/include/ -## If compiling on a mac make sure you install and use homebrew and run the following command `brew install pcre pcre++` -## Uncomment lines below and run `make all` -# LIBS= -lpcre -lcrypto -lm -lpthread -# INCPATHS=-I$(shell brew --prefix)/include -I$(shell brew --prefix openssl)/include -# LIBPATHS=-L$(shell brew --prefix)/lib -L$(shell brew --prefix openssl)/lib -# CFLAGS=-ggdb -O3 -Wall -Qunused-arguments $(INCPATHS) $(LIBPATHS) OBJS=vanitygen.o oclvanitygen.o oclvanityminer.o oclengine.o keyconv.o pattern.o util.o groestl.o sha3.o ed25519.o \ stellar.o base32.o crc16.o PROGS=vanitygen++ keyconv oclvanitygen++ oclvanityminer @@ -42,5 +47,13 @@ oclvanityminer: oclvanityminer.o oclengine.o pattern.o util.o groestl.o sha3.o keyconv: keyconv.o util.o groestl.o sha3.o $(CC) $^ -o $@ $(CFLAGS) $(LIBS) +run_tests.o: tests.h util_test.h + +run_tests: run_tests.o util.o groestl.o sha3.o + $(CC) $^ -o $@ $(CFLAGS) $(LIBS) $(OPENCL_LIBS) -lcheck + +test: run_tests + ./run_tests + clean: - rm -f $(OBJS) $(PROGS) $(TESTS) *.oclbin + rm -f $(OBJS) $(PROGS) $(TESTS) *.oclbin run_tests diff --git a/run_tests.c b/run_tests.c new file mode 100644 index 0000000..946f9b8 --- /dev/null +++ b/run_tests.c @@ -0,0 +1,26 @@ +#include "tests.h" +#include +#include + +int GRSFlag = 0; // avoid link error when test function in util.c + +// run suite +// +// See: +// https://libcheck.github.io/check/ +// http://developertesting.rocks/tools/check/ +int main(void) +{ + int number_failed; + Suite* suite = create_sample_suite(); + SRunner* runner = srunner_create(suite); + // srunner_add_suite(runner, ); + + srunner_run_all(runner, CK_VERBOSE); + number_failed = srunner_ntests_failed(runner); + srunner_free(runner); + if (number_failed == 0) { + printf("PASSED ALL TESTS\n"); + } + return number_failed; +} diff --git a/tests.h b/tests.h new file mode 100644 index 0000000..25d85f7 --- /dev/null +++ b/tests.h @@ -0,0 +1,53 @@ +#include "util.h" +#include "pattern.h" +#include + +#define FROM_HEX_MAXLEN 512 + +const uint8_t *from_hex(const char *str) { + static uint8_t buf[FROM_HEX_MAXLEN]; + size_t len = strlen(str) / 2; + if (len > FROM_HEX_MAXLEN) len = FROM_HEX_MAXLEN; + for (size_t i = 0; i < len; i++) { + uint8_t c = 0; + if (str[i * 2] >= '0' && str[i*2] <= '9') c += (str[i * 2] - '0') << 4; + if ((str[i * 2] & ~0x20) >= 'A' && (str[i*2] & ~0x20) <= 'F') c += (10 + (str[i * 2] & ~0x20) - 'A') << 4; + if (str[i * 2 + 1] >= '0' && str[i * 2 + 1] <= '9') c += (str[i * 2 + 1] - '0'); + if ((str[i * 2 + 1] & ~0x20) >= 'A' && (str[i * 2 + 1] & ~0x20) <= 'F') c += (10 + (str[i * 2 + 1] & ~0x20) - 'A'); + buf[i] = c; + } + return buf; +} + + +START_TEST(test_sample) +{ + ck_assert_int_eq(512, 512); + ck_assert_str_eq("Hello World", "Hello World"); +} +END_TEST + +#include "util_test.h" + + +Suite* create_sample_suite(void) +{ + Suite* suite = suite_create("Sample suite"); + TCase* tc; + + tc = tcase_create("sample test case"); + tcase_add_test(tc, test_sample); + suite_add_tcase(suite, tc); + + tc = tcase_create("util hex test"); + tcase_add_test(tc, test_hex_enc); + tcase_add_test(tc, test_hex_dec); + suite_add_tcase(suite, tc); + + tc = tcase_create("util eth test"); + tcase_add_test(tc, test_eth_pubkey2addr); + tcase_add_test(tc, test_eth_encode_checksum_addr); + suite_add_tcase(suite, tc); + + return suite; +} diff --git a/util.c b/util.c index d952e8c..5cb95be 100644 --- a/util.c +++ b/util.c @@ -1326,6 +1326,9 @@ count_processors(void) static const char hexdig[] = "0123456789abcdef"; +// An example: +// input: hex[4] = {0x31, 0x32, 0x61, 0x62} +// output: bin[2] = {0x12, 0xab} int hex_dec(void *bin, size_t *binszp, const char *hex, size_t hexsz) { diff --git a/util_test.h b/util_test.h new file mode 100644 index 0000000..31b89f5 --- /dev/null +++ b/util_test.h @@ -0,0 +1,124 @@ +START_TEST(test_hex_enc) +{ + struct { + const char* input; + const char* expect_output; + } tests[] = { + { "\x01", "\x30\x31" }, + { "\x11", "\x31\x31" }, + { "\xff", "\x66\x66" }, + { "\x12\xab", "\x31\x32\x61\x62" }, + }; + + size_t n = sizeof(tests) / sizeof(tests[0]); + + for (int i = 0; i < n; i++) { + char got[1024]; + size_t len = 1024; + + hex_enc(got, &len, tests[i].input, strlen(tests[i].input)); + + ck_assert_int_eq(len, strlen(tests[i].expect_output)); + ck_assert_mem_eq(got, tests[i].expect_output, len); + } +} +END_TEST + +START_TEST(test_hex_dec) +{ + struct { + const char* input; + const char* expect_output; + } tests[] = { + { "\x30\x31", "\x01" }, + { "\x31\x31", "\x11" }, + { "\x46\x46", "\xff" }, + { "\x66\x66", "\xff" }, + { "\x31\x32\x41\x42", "\x12\xab" }, + { "\x31\x32\x61\x62", "\x12\xab" }, + }; + + size_t n = sizeof(tests) / sizeof(tests[0]); + + for (int i = 0; i < n; i++) { + char got[1024]; + size_t len = 1024; + + hex_dec(got, &len, tests[i].input, strlen(tests[i].input)); + + ck_assert_int_eq(len, strlen(tests[i].expect_output)); + ck_assert_mem_eq(got, tests[i].expect_output, len); + } +} +END_TEST + +START_TEST(test_eth_pubkey2addr) +{ + struct { + const char* input_hex; + int addr_format; + const char* expect_output_hex; + } tests[] = { + { "0477eb4560b9535593f074704e9d0e593c4c09b4f8914971ac53766a4ddd0126e15fae8641a3c07d11a78b14dcd1f0f407781c8feac953c23efdfe71a82ccb9a1f", + VCF_PUBKEY, + "c660a638f696f8d22d8d593f19dcdbe1bb21716e" }, + { "0452b5bcf0ba1cdf9c4aaaa1463658f1e830b968f07fefe80d8e416758c20c727b83d30cdee31b85a8c92a6555fc00d6d2b0f572755f1880d011d9c5d56f4e9605", + VCF_PUBKEY, + "ef5a3f547f84d811998c505f0c5b7a8b74f5b79d" }, + { "0477eb4560b9535593f074704e9d0e593c4c09b4f8914971ac53766a4ddd0126e15fae8641a3c07d11a78b14dcd1f0f407781c8feac953c23efdfe71a82ccb9a1f", + VCF_CONTRACT, + "0e1bb5eb3ccfcacf6df3267c2a15705a7ba453b0" }, + { "0452b5bcf0ba1cdf9c4aaaa1463658f1e830b968f07fefe80d8e416758c20c727b83d30cdee31b85a8c92a6555fc00d6d2b0f572755f1880d011d9c5d56f4e9605", + VCF_CONTRACT, + "b42efaaf71a364905fd5fe95604dbb63bb2c2674" }, + }; + + size_t n = sizeof(tests) / sizeof(tests[0]); + + for (int i = 0; i < n; i++) { + size_t addr_len = 20; + char got[addr_len]; + + char input[65]; + memcpy(input, from_hex(tests[i].input_hex), sizeof(input)); + + char expect_output[addr_len]; + memcpy(expect_output, from_hex(tests[i].expect_output_hex), sizeof(expect_output)); + + eth_pubkey2addr((const unsigned char*)input, tests[i].addr_format, (unsigned char*)got); + + ck_assert_mem_eq(got, expect_output, addr_len); + } +} +END_TEST + +START_TEST(test_eth_encode_checksum_addr) +{ + struct { + const char* input_hex; + const char* expect_output; + } tests[] = { + /* All caps */ + { "52908400098527886e0f7030069857d2e4169ee7", "52908400098527886E0F7030069857D2E4169EE7" }, + /* All Lower */ + { "de709f2102306220921060314715629080e2fb77", "de709f2102306220921060314715629080e2fb77" }, + /* Normal */ + { "5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", "5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed" }, + }; + + size_t n = sizeof(tests) / sizeof(tests[0]); + + for (int i = 0; i < n; i++) { + size_t checksum_addr = 40; + char got[checksum_addr]; + + size_t input_len = 20; + char input[input_len]; + memcpy(input, from_hex(tests[i].input_hex), sizeof(input)); + + eth_encode_checksum_addr((void*)input, input_len, (char*)got, checksum_addr); + + ck_assert_mem_eq(got, tests[i].expect_output, checksum_addr); + } +} +END_TEST