// Copyright (c) 2012-2013 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "gtest/gtest.h" #include #include "common/base58.cpp" #include "currency_core/currency_format_utils.h" #include "serialization/binary_utils.h" #include "currency_core/currency_basic.h" using namespace tools; #define MAKE_STR(arr) std::string(arr, sizeof(arr) - 1) namespace { void do_test_uint_8be_to_64(uint64_t expected, const uint8_t* data, size_t size) { uint64_t val = base58::uint_8be_to_64(data, size); ASSERT_EQ(val, expected); } void do_test_uint_64_to_8be(uint64_t num, const std::string& expected_str) { std::string data(expected_str.size(), '\x0'); base58::uint_64_to_8be(num, data.size(), reinterpret_cast(&data[0])); ASSERT_EQ(data, expected_str); } void do_test_encode_block(const std::string& block, const std::string& expected) { ASSERT_TRUE(1 <= block.size() && block.size() <= base58::full_block_size); std::string enc(base58::encoded_block_sizes[block.size()], base58::alphabet[0]); base58::encode_block(block.data(), block.size(), &enc[0]); ASSERT_EQ(enc, expected); std::string dec(block.size(), '\0'); ASSERT_TRUE(base58::decode_block(enc.data(), enc.size(), &dec[0])); ASSERT_EQ(block, dec); } void do_test_decode_block_pos(const std::string& enc, const std::string& expected) { std::string data(base58::decoded_block_sizes::instance(enc.size()), '\0'); ASSERT_TRUE(base58::decode_block(enc.data(), enc.size(), &data[0])); ASSERT_EQ(data, expected); } void do_test_decode_block_neg(const std::string& enc) { std::string data(base58::full_block_size, '\0'); ASSERT_FALSE(base58::decode_block(enc.data(), enc.size(), &data[0])); } void do_test_encode(const std::string& data, const std::string& expected) { std::string enc = base58::encode(data); ASSERT_EQ(enc, expected); std::string dec; ASSERT_TRUE(base58::decode(enc, dec)); ASSERT_EQ(dec, data); } void do_test_decode_pos(const std::string& enc, const std::string& expected) { std::string dec; ASSERT_TRUE(base58::decode(enc, dec)); ASSERT_EQ(dec, expected); } void do_test_decode_neg(const std::string& enc) { std::string dec; ASSERT_FALSE(base58::decode(enc, dec)); } void do_test_encode_decode_addr(uint64_t tag, const std::string& data, const std::string& expected) { std::string addr = base58::encode_addr(tag, data); ASSERT_EQ(addr, expected); uint64_t dec_tag; std::string dec_data; ASSERT_TRUE(base58::decode_addr(addr, dec_tag, dec_data)); ASSERT_EQ(tag, dec_tag); ASSERT_EQ(data, dec_data); } } #define TEST_uint_8be_to_64(expected, str) \ TEST(base58_uint_8be_to_64, handles_bytes_##expected) \ { \ std::string data = str; \ do_test_uint_8be_to_64(expected, reinterpret_cast(data.data()), data.size()); \ } TEST_uint_8be_to_64(0x0000000000000001, "\x1"); TEST_uint_8be_to_64(0x0000000000000102, "\x1\x2"); TEST_uint_8be_to_64(0x0000000000010203, "\x1\x2\x3"); TEST_uint_8be_to_64(0x0000000001020304, "\x1\x2\x3\x4"); TEST_uint_8be_to_64(0x0000000102030405, "\x1\x2\x3\x4\x5"); TEST_uint_8be_to_64(0x0000010203040506, "\x1\x2\x3\x4\x5\x6"); TEST_uint_8be_to_64(0x0001020304050607, "\x1\x2\x3\x4\x5\x6\x7"); TEST_uint_8be_to_64(0x0102030405060708, "\x1\x2\x3\x4\x5\x6\x7\x8"); #define TEST_uint_64_to_8be(num, expected_str) \ TEST(base58_uint_64_to_8be, handles_bytes_##num) \ { \ do_test_uint_64_to_8be(num, expected_str); \ } TEST_uint_64_to_8be(0x0000000000000001, "\x1"); TEST_uint_64_to_8be(0x0000000000000102, "\x1\x2"); TEST_uint_64_to_8be(0x0000000000010203, "\x1\x2\x3"); TEST_uint_64_to_8be(0x0000000001020304, "\x1\x2\x3\x4"); TEST_uint_64_to_8be(0x0000000102030405, "\x1\x2\x3\x4\x5"); TEST_uint_64_to_8be(0x0000010203040506, "\x1\x2\x3\x4\x5\x6"); TEST_uint_64_to_8be(0x0001020304050607, "\x1\x2\x3\x4\x5\x6\x7"); TEST_uint_64_to_8be(0x0102030405060708, "\x1\x2\x3\x4\x5\x6\x7\x8"); TEST(reverse_alphabet, is_correct) { ASSERT_EQ(-1, base58::reverse_alphabet::instance(0)); ASSERT_EQ(-1, base58::reverse_alphabet::instance(std::numeric_limits::min())); ASSERT_EQ(-1, base58::reverse_alphabet::instance(std::numeric_limits::max())); ASSERT_EQ(-1, base58::reverse_alphabet::instance('1' - 1)); ASSERT_EQ(-1, base58::reverse_alphabet::instance('z' + 1)); ASSERT_EQ(-1, base58::reverse_alphabet::instance('0')); ASSERT_EQ(-1, base58::reverse_alphabet::instance('I')); ASSERT_EQ(-1, base58::reverse_alphabet::instance('O')); ASSERT_EQ(-1, base58::reverse_alphabet::instance('l')); ASSERT_EQ(0, base58::reverse_alphabet::instance('1')); ASSERT_EQ(8, base58::reverse_alphabet::instance('9')); ASSERT_EQ(base58::alphabet_size - 1, base58::reverse_alphabet::instance('z')); } #define TEST_encode_block(block, expected) \ TEST(base58_encode_block, handles_##expected) \ { \ do_test_encode_block(MAKE_STR(block), #expected); \ } TEST_encode_block("\x00", 11); TEST_encode_block("\x39", 1z); TEST_encode_block("\xFF", 5Q); TEST_encode_block("\x00\x00", 111); TEST_encode_block("\x00\x39", 11z); TEST_encode_block("\x01\x00", 15R); TEST_encode_block("\xFF\xFF", LUv); TEST_encode_block("\x00\x00\x00", 11111); TEST_encode_block("\x00\x00\x39", 1111z); TEST_encode_block("\x01\x00\x00", 11LUw); TEST_encode_block("\xFF\xFF\xFF", 2UzHL); TEST_encode_block("\x00\x00\x00\x39", 11111z); TEST_encode_block("\xFF\xFF\xFF\xFF", 7YXq9G); TEST_encode_block("\x00\x00\x00\x00\x39", 111111z); TEST_encode_block("\xFF\xFF\xFF\xFF\xFF", VtB5VXc); TEST_encode_block("\x00\x00\x00\x00\x00\x39", 11111111z); TEST_encode_block("\xFF\xFF\xFF\xFF\xFF\xFF", 3CUsUpv9t); TEST_encode_block("\x00\x00\x00\x00\x00\x00\x39", 111111111z); TEST_encode_block("\xFF\xFF\xFF\xFF\xFF\xFF\xFF", Ahg1opVcGW); TEST_encode_block("\x00\x00\x00\x00\x00\x00\x00\x39", 1111111111z); TEST_encode_block("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", jpXCZedGfVQ); TEST_encode_block("\x00\x00\x00\x00\x00\x00\x00\x00", 11111111111); TEST_encode_block("\x00\x00\x00\x00\x00\x00\x00\x01", 11111111112); TEST_encode_block("\x00\x00\x00\x00\x00\x00\x00\x08", 11111111119); TEST_encode_block("\x00\x00\x00\x00\x00\x00\x00\x09", 1111111111A); TEST_encode_block("\x00\x00\x00\x00\x00\x00\x00\x3A", 11111111121); TEST_encode_block("\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 1Ahg1opVcGW); TEST_encode_block("\x06\x15\x60\x13\x76\x28\x79\xF7", 22222222222); TEST_encode_block("\x05\xE0\x22\xBA\x37\x4B\x2A\x00", 1z111111111); #define TEST_decode_block_pos(enc, expected) \ TEST(base58_decode_block, handles_pos_##enc) \ { \ do_test_decode_block_pos(#enc, MAKE_STR(expected)); \ } #define TEST_decode_block_neg(enc) \ TEST(base58_decode_block, handles_neg_##enc) \ { \ do_test_decode_block_neg(#enc); \ } // 1-byte block TEST_decode_block_neg(1); TEST_decode_block_neg(z); // 2-bytes block TEST_decode_block_pos(11, "\x00"); TEST_decode_block_pos(5Q, "\xFF"); TEST_decode_block_neg(5R); TEST_decode_block_neg(zz); // 3-bytes block TEST_decode_block_pos(111, "\x00\x00"); TEST_decode_block_pos(LUv, "\xFF\xFF"); TEST_decode_block_neg(LUw); TEST_decode_block_neg(zzz); // 4-bytes block TEST_decode_block_neg(1111); TEST_decode_block_neg(zzzz); // 5-bytes block TEST_decode_block_pos(11111, "\x00\x00\x00"); TEST_decode_block_pos(2UzHL, "\xFF\xFF\xFF"); TEST_decode_block_neg(2UzHM); TEST_decode_block_neg(zzzzz); // 6-bytes block TEST_decode_block_pos(111111, "\x00\x00\x00\x00"); TEST_decode_block_pos(7YXq9G, "\xFF\xFF\xFF\xFF"); TEST_decode_block_neg(7YXq9H); TEST_decode_block_neg(zzzzzz); // 7-bytes block TEST_decode_block_pos(1111111, "\x00\x00\x00\x00\x00"); TEST_decode_block_pos(VtB5VXc, "\xFF\xFF\xFF\xFF\xFF"); TEST_decode_block_neg(VtB5VXd); TEST_decode_block_neg(zzzzzzz); // 8-bytes block TEST_decode_block_neg(11111111); TEST_decode_block_neg(zzzzzzzz); // 9-bytes block TEST_decode_block_pos(111111111, "\x00\x00\x00\x00\x00\x00"); TEST_decode_block_pos(3CUsUpv9t, "\xFF\xFF\xFF\xFF\xFF\xFF"); TEST_decode_block_neg(3CUsUpv9u); TEST_decode_block_neg(zzzzzzzzz); // 10-bytes block TEST_decode_block_pos(1111111111, "\x00\x00\x00\x00\x00\x00\x00"); TEST_decode_block_pos(Ahg1opVcGW, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF"); TEST_decode_block_neg(Ahg1opVcGX); TEST_decode_block_neg(zzzzzzzzzz); // 11-bytes block TEST_decode_block_pos(11111111111, "\x00\x00\x00\x00\x00\x00\x00\x00"); TEST_decode_block_pos(jpXCZedGfVQ, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"); TEST_decode_block_neg(jpXCZedGfVR); TEST_decode_block_neg(zzzzzzzzzzz); // Invalid symbols TEST_decode_block_neg(01111111111); TEST_decode_block_neg(11111111110); TEST_decode_block_neg(11111011111); TEST_decode_block_neg(I1111111111); TEST_decode_block_neg(O1111111111); TEST_decode_block_neg(l1111111111); TEST_decode_block_neg(_1111111111); #define TEST_encode(expected, data) \ TEST(base58_encode, handles_##expected) \ { \ do_test_encode(MAKE_STR(data), #expected); \ } TEST_encode(11, "\x00"); TEST_encode(111, "\x00\x00"); TEST_encode(11111, "\x00\x00\x00"); TEST_encode(111111, "\x00\x00\x00\x00"); TEST_encode(1111111, "\x00\x00\x00\x00\x00"); TEST_encode(111111111, "\x00\x00\x00\x00\x00\x00"); TEST_encode(1111111111, "\x00\x00\x00\x00\x00\x00\x00"); TEST_encode(11111111111, "\x00\x00\x00\x00\x00\x00\x00\x00"); TEST_encode(1111111111111, "\x00\x00\x00\x00\x00\x00\x00\x00\x00"); TEST_encode(11111111111111, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"); TEST_encode(1111111111111111, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"); TEST_encode(11111111111111111, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"); TEST_encode(111111111111111111, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"); TEST_encode(11111111111111111111, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"); TEST_encode(111111111111111111111, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"); TEST_encode(1111111111111111111111, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"); TEST_encode(22222222222VtB5VXc, "\x06\x15\x60\x13\x76\x28\x79\xF7\xFF\xFF\xFF\xFF\xFF"); #define TEST_decode_pos(enc, expected) \ TEST(base58_decode_pos, handles_pos_##enc) \ { \ do_test_decode_pos(#enc, MAKE_STR(expected)); \ } #define TEST_decode_neg(enc) \ TEST(base58_decode_neg, handles_neg_##enc) \ { \ do_test_decode_neg(#enc); \ } TEST_decode_pos(, ""); TEST_decode_pos(5Q, "\xFF"); TEST_decode_pos(LUv, "\xFF\xFF"); TEST_decode_pos(2UzHL, "\xFF\xFF\xFF"); TEST_decode_pos(7YXq9G, "\xFF\xFF\xFF\xFF"); TEST_decode_pos(VtB5VXc, "\xFF\xFF\xFF\xFF\xFF"); TEST_decode_pos(3CUsUpv9t, "\xFF\xFF\xFF\xFF\xFF\xFF"); TEST_decode_pos(Ahg1opVcGW, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF"); TEST_decode_pos(jpXCZedGfVQ, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"); TEST_decode_pos(jpXCZedGfVQ5Q, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"); TEST_decode_pos(jpXCZedGfVQLUv, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"); TEST_decode_pos(jpXCZedGfVQ2UzHL, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"); TEST_decode_pos(jpXCZedGfVQ7YXq9G, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"); TEST_decode_pos(jpXCZedGfVQVtB5VXc, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"); TEST_decode_pos(jpXCZedGfVQ3CUsUpv9t, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"); TEST_decode_pos(jpXCZedGfVQAhg1opVcGW, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"); TEST_decode_pos(jpXCZedGfVQjpXCZedGfVQ, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"); // Invalid length TEST_decode_neg(1); TEST_decode_neg(z); TEST_decode_neg(1111); TEST_decode_neg(zzzz); TEST_decode_neg(11111111); TEST_decode_neg(zzzzzzzz); TEST_decode_neg(123456789AB1); TEST_decode_neg(123456789ABz); TEST_decode_neg(123456789AB1111); TEST_decode_neg(123456789ABzzzz); TEST_decode_neg(123456789AB11111111); TEST_decode_neg(123456789ABzzzzzzzz); // Overflow TEST_decode_neg(5R); TEST_decode_neg(zz); TEST_decode_neg(LUw); TEST_decode_neg(zzz); TEST_decode_neg(2UzHM); TEST_decode_neg(zzzzz); TEST_decode_neg(7YXq9H); TEST_decode_neg(zzzzzz); TEST_decode_neg(VtB5VXd); TEST_decode_neg(zzzzzzz); TEST_decode_neg(3CUsUpv9u); TEST_decode_neg(zzzzzzzzz); TEST_decode_neg(Ahg1opVcGX); TEST_decode_neg(zzzzzzzzzz); TEST_decode_neg(jpXCZedGfVR); TEST_decode_neg(zzzzzzzzzzz); TEST_decode_neg(123456789AB5R); TEST_decode_neg(123456789ABzz); TEST_decode_neg(123456789ABLUw); TEST_decode_neg(123456789ABzzz); TEST_decode_neg(123456789AB2UzHM); TEST_decode_neg(123456789ABzzzzz); TEST_decode_neg(123456789AB7YXq9H); TEST_decode_neg(123456789ABzzzzzz); TEST_decode_neg(123456789ABVtB5VXd); TEST_decode_neg(123456789ABzzzzzzz); TEST_decode_neg(123456789AB3CUsUpv9u); TEST_decode_neg(123456789ABzzzzzzzzz); TEST_decode_neg(123456789ABAhg1opVcGX); TEST_decode_neg(123456789ABzzzzzzzzzz); TEST_decode_neg(123456789ABjpXCZedGfVR); TEST_decode_neg(123456789ABzzzzzzzzzzz); TEST_decode_neg(zzzzzzzzzzz11); // Invalid symbols TEST_decode_neg(10); TEST_decode_neg(11I); TEST_decode_neg(11O11); TEST_decode_neg(11l111); TEST_decode_neg(11_11111111); TEST_decode_neg(1101111111111); TEST_decode_neg(11I11111111111111); TEST_decode_neg(11O1111111111111111111); TEST_decode_neg(1111111111110); TEST_decode_neg(111111111111l1111); TEST_decode_neg(111111111111_111111111); #define TEST_encode_decode_addr(addr, tag, data) \ TEST(base58_encode_decode_addr, handles_##addr) \ { \ do_test_encode_decode_addr(UINT64_C(tag), MAKE_STR(data), #addr); \ } TEST_encode_decode_addr(21D35quxec71111111111111111111111111111111111111111111111111111111111111111111111111111116Q5tCH, 6, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"); TEST_encode_decode_addr(2Aui6ejTFscjpXCZedGfVQjpXCZedGfVQjpXCZedGfVQjpXCZedGfVQjpXCZedGfVQjpXCZedGfVQjpXCZedGfVQVqegMoV, 6, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"); TEST_encode_decode_addr(1119XrkPuSmLzdHXgVgrZKjepg5hZAxffLzdHXgVgrZKjepg5hZAxffLzdHXgVgrZKjepg5hZAxffLzdHXgVgrZKVphZRvn, 0, "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF" "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF"); TEST_encode_decode_addr(111111111111111111111111111111111111111111111111111111111111111111111111111111111111111115TXfiA, 0, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"); TEST_encode_decode_addr(PuT7GAdgbA83qvSEivPLYo11111111111111111111111111111111111111111111111111111111111111111111111111111169tWrH, 0x1122334455667788, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"); TEST_encode_decode_addr(PuT7GAdgbA841d7FXjswpJjpXCZedGfVQjpXCZedGfVQjpXCZedGfVQjpXCZedGfVQjpXCZedGfVQjpXCZedGfVQjpXCZedGfVQVq4LL1v, 0x1122334455667788, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"); TEST_encode_decode_addr(PuT7GAdgbA819VwdWVDP, 0x1122334455667788, "\x11"); TEST_encode_decode_addr(PuT7GAdgbA81efAfdCjPg, 0x1122334455667788, "\x22\x22"); TEST_encode_decode_addr(PuT7GAdgbA83sryEt3YC8Q, 0x1122334455667788, "\x33\x33\x33"); TEST_encode_decode_addr(PuT7GAdgbA83tWUuc54PFP3b, 0x1122334455667788, "\x44\x44\x44\x44"); TEST_encode_decode_addr(PuT7GAdgbA83u9zaKrtRKZ1J6, 0x1122334455667788, "\x55\x55\x55\x55\x55"); TEST_encode_decode_addr(PuT7GAdgbA83uoWF3eanGG1aRoG, 0x1122334455667788, "\x66\x66\x66\x66\x66\x66"); TEST_encode_decode_addr(PuT7GAdgbA83vT1umSHMYJ4oNVdu, 0x1122334455667788, "\x77\x77\x77\x77\x77\x77\x77"); TEST_encode_decode_addr(PuT7GAdgbA83w6XaVDyvpoGQBEWbB, 0x1122334455667788, "\x88\x88\x88\x88\x88\x88\x88\x88"); TEST_encode_decode_addr(PuT7GAdgbA83wk3FD1gW7J2KVGofA1r, 0x1122334455667788, "\x99\x99\x99\x99\x99\x99\x99\x99\x99"); TEST_encode_decode_addr(15p2yAV, 0, ""); TEST_encode_decode_addr(FNQ3D6A, 0x7F, ""); TEST_encode_decode_addr(26k9QWweu, 0x80, ""); TEST_encode_decode_addr(3BzAD7n3y, 0xFF, ""); TEST_encode_decode_addr(11efCaY6UjG7JrxuB, 0, "\x11\x22\x33\x44\x55\x66\x77"); TEST_encode_decode_addr(21rhHRT48LN4PriP9, 6, "\x11\x22\x33\x44\x55\x66\x77"); #define TEST_decode_addr_neg(addr, test_name) \ TEST(base58_decode_addr_neg, test_name) \ { \ uint64_t tag; \ std::string data; \ ASSERT_FALSE(base58::decode_addr(MAKE_STR(addr), tag, data)); \ } TEST_decode_addr_neg("zuT7GAdgbA819VwdWVDP", decode_fails_due_overflow); TEST_decode_addr_neg("0uT7GAdgbA819VwdWVDP", decode_fails_due_invalid_char_0); TEST_decode_addr_neg("IuT7GAdgbA819VwdWVDP", decode_fails_due_invalid_char_I); TEST_decode_addr_neg("OuT7GAdgbA819VwdWVDP", decode_fails_due_invalid_char_O); TEST_decode_addr_neg("luT7GAdgbA819VwdWVDP", decode_fails_due_invalid_char_l); TEST_decode_addr_neg("\0uT7GAdgbA819VwdWVDP", decode_fails_due_invalid_char_00); TEST_decode_addr_neg("PuT7GAdgbA819VwdWVD", decode_fails_due_invalid_lenght); TEST_decode_addr_neg("11efCaY6UjG7JrxuC", handles_invalid_checksum); TEST_decode_addr_neg("jerj2e4mESo", handles_non_correct_tag); // "jerj2e4mESo" == "\xFF\x00\xFF\xFF\x5A\xD9\xF1\x1C" TEST_decode_addr_neg("1", decode_fails_due_invalid_block_len_0); TEST_decode_addr_neg("1111", decode_fails_due_invalid_block_len_1); TEST_decode_addr_neg("11", decode_fails_due_address_too_short_0); TEST_decode_addr_neg("111", decode_fails_due_address_too_short_1); TEST_decode_addr_neg("11111", decode_fails_due_address_too_short_2); TEST_decode_addr_neg("111111", decode_fails_due_address_too_short_3); TEST_decode_addr_neg("999999", decode_fails_due_address_too_short_4); TEST_decode_addr_neg("ZZZZZZ", decode_fails_due_address_too_short_5); namespace { std::string test_serialized_keys = MAKE_STR( "\xf7\x24\xbc\x5c\x6c\xfb\xb9\xd9\x76\x02\xc3\x00\x42\x3a\x2f\x28" "\x64\x18\x74\x51\x3a\x03\x57\x78\xa0\xc1\x77\x8d\x83\x32\x01\xe9" "\x22\x09\x39\x68\x9e\xdf\x1a\xbd\x5b\xc1\xd0\x31\xf7\x3e\xcd\x6c" "\x99\x3a\xdd\x66\xd6\x80\x88\x70\x45\x6a\xfe\xb8\xe7\xee\xb6\x8d" "\x00"); std::string test_keys_addr_str = "ZxDqHy6WnyYY5yQcdApjMb8tVPik5BC3LFdaevfbGq7X1KY5vdsWmUi5UQgse2GBZFbMsb47TFqBmPpdFHDDwDxR2ZuZ6zX4W"; // correct str address depends on CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX value } TEST(get_account_address_as_str, works_correctly) { currency::account_public_address addr; ASSERT_TRUE(serialization::parse_binary(test_serialized_keys, addr)); std::string addr_str = currency::get_account_address_as_str(addr); ASSERT_EQ(addr_str, test_keys_addr_str); } TEST(get_account_address_from_str, handles_valid_address) { currency::account_public_address addr; ASSERT_TRUE(currency::get_account_address_from_str(addr, test_keys_addr_str)); std::string blob; ASSERT_TRUE(serialization::dump_binary(addr, blob)); ASSERT_EQ(blob, test_serialized_keys); } TEST(get_account_address_from_str, fails_on_invalid_address_format) { currency::account_public_address addr; std::string addr_str = test_keys_addr_str; addr_str[0] = '0'; ASSERT_FALSE(currency::get_account_address_from_str(addr, addr_str)); } TEST(get_account_address_from_str, fails_on_invalid_address_prefix) { std::string addr_str = base58::encode_addr(0, test_serialized_keys); currency::account_public_address addr; ASSERT_FALSE(currency::get_account_address_from_str(addr, addr_str)); } TEST(get_account_address_from_str, fails_on_invalid_address_content) { std::string addr_str = base58::encode_addr(CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX, test_serialized_keys.substr(1)); currency::account_public_address addr; ASSERT_FALSE(currency::get_account_address_from_str(addr, addr_str)); } TEST(get_account_address_from_str, fails_on_invalid_address_spend_key) { std::string serialized_keys_copy = test_serialized_keys; serialized_keys_copy[0] = '\0'; std::string addr_str = base58::encode_addr(CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX, serialized_keys_copy); currency::account_public_address addr; ASSERT_FALSE(currency::get_account_address_from_str(addr, addr_str)); } TEST(get_account_address_from_str, fails_on_invalid_address_view_key) { std::string serialized_keys_copy = test_serialized_keys; serialized_keys_copy[serialized_keys_copy.size() - 2] = '\x01'; std::string addr_str = base58::encode_addr(CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX, serialized_keys_copy); currency::account_public_address addr; ASSERT_FALSE(currency::get_account_address_from_str(addr, addr_str)); } // integrated addresses TEST(integ_address, payment_id_sizes) { size_t pid_size_max = BC_PAYMENT_ID_SERVICE_SIZE_MAX; for(size_t pid_size = 0; pid_size <= pid_size_max; ++pid_size) { std::string payment_id(pid_size, ' '); if (pid_size > 0) crypto::generate_random_bytes(pid_size, &payment_id.front()); currency::account_public_address addr = AUTO_VAL_INIT_T(currency::account_public_address); addr.spend_public_key = currency::keypair::generate().pub; addr.view_public_key = currency::keypair::generate().pub; std::string addr_str = currency::get_account_address_and_payment_id_as_str(addr, payment_id); currency::account_public_address addr2 = AUTO_VAL_INIT_T(currency::account_public_address); std::string integrated_payment_id; ASSERT_TRUE(currency::get_account_address_and_payment_id_from_str(addr2, integrated_payment_id, addr_str)); ASSERT_EQ(addr2, addr); ASSERT_EQ(integrated_payment_id, payment_id); } // test max size exceeding size_t pid_size = BC_PAYMENT_ID_SERVICE_SIZE_MAX + 1; std::string payment_id(pid_size, ' '); if (pid_size > 0) crypto::generate_random_bytes(pid_size, &payment_id.front()); currency::account_public_address addr = AUTO_VAL_INIT_T(currency::account_public_address); addr.spend_public_key = currency::keypair::generate().pub; addr.view_public_key = currency::keypair::generate().pub; // the following line is expected to handle oversized payment id well std::string addr_str = currency::get_account_address_and_payment_id_as_str(addr, payment_id); currency::account_public_address addr2 = AUTO_VAL_INIT_T(currency::account_public_address); std::string integrated_payment_id; ASSERT_FALSE(currency::get_account_address_and_payment_id_from_str(addr2, integrated_payment_id, addr_str)); } struct addr_entry_t { std::string address; std::string view_pub_key; std::string spend_pub_key; std::string payment_id_hex; uint8_t flags; }; addr_entry_t addr_entries[] = { { // classic normal address "ZxD5aoLDPTdcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp338Se7AxeH", // address "a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3", // view_pub_key "9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa", // spend_pub_key "", // payment_id_hex 0 // flags }, { // classic integrated address "iZ2Zi6RmTWwcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp3iTqEsjvJoco1aLSZXS6T", // address "a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3", // view_pub_key "9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa", // spend_pub_key "87440d0b9acc42f1", // payment_id_hex 0 // flags }, { // new format normal address with custom flags "ZxD5aoLDPTdcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp3APrDvRoL5C", // address "a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3", // view_pub_key "9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa", // spend_pub_key "", // payment_id_hex 0xfe // flags }, { // new format integrated address with custom flags "iZ4mBxubNfqcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp3iTrG7nU5rRCWmcozLaMoY95sAbo6", // address "a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3", // view_pub_key "9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa", // spend_pub_key "3ba0527bcfb1fa93630d28eed6", // payment_id 0xfe // flags }, { // normal auditable address "aZxb9Et6FhP9AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jLYcEJMEmqQFn", // address "a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3", // view_pub_key "9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa", // spend_pub_key "", // payment_id ACCOUNT_PUBLIC_ADDRESS_FLAG_AUDITABLE // flags }, { // auditable integrated address "aiZXDondHWu9AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jLYcEJM9xJH8EbjuRiMJgFmPRATsEV9", // address "a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3", // view_pub_key "9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa", // spend_pub_key "3ba0527bcfb1fa93630d28eed6", // payment_id ACCOUNT_PUBLIC_ADDRESS_FLAG_AUDITABLE // flags } }; void check_add_entry(const addr_entry_t& ae) { std::string payment_id, payment_id_hex; currency::account_public_address addr = AUTO_VAL_INIT(addr); ASSERT_TRUE(currency::get_account_address_and_payment_id_from_str(addr, payment_id, ae.address)); payment_id_hex = epee::string_tools::buff_to_hex_nodelimer(payment_id); ASSERT_EQ(ae.flags, addr.flags); ASSERT_EQ(ae.payment_id_hex, payment_id_hex); ASSERT_EQ(ae.view_pub_key, epee::string_tools::pod_to_hex(addr.view_public_key)); ASSERT_EQ(ae.spend_pub_key, epee::string_tools::pod_to_hex(addr.spend_public_key)); } TEST(auditable_addresses, basic) { /* currency::account_keys keys = AUTO_VAL_INIT(keys); epee::string_tools::parse_tpod_from_hex_string("248b019d145d485576ecb0367d92b5a12e8aa15084b59ef15014a7a22d1f3b0c", keys.spend_secret_key); dependent_key(keys.spend_secret_key, keys.view_secret_key); crypto::secret_key_to_public_key(keys.view_secret_key, keys.account_address.view_public_key); crypto::secret_key_to_public_key(keys.spend_secret_key, keys.account_address.spend_public_key); keys.account_address.flags = 0xfe; std::string payment_id; epee::string_tools::parse_hexstr_to_binbuff(std::string("3ba0527bcfb1fa93630d28eed6"), payment_id); std::cout << currency::get_account_address_as_str(keys.account_address) << " " << epee::string_tools::pod_to_hex(keys.account_address.view_public_key) << " " << epee::string_tools::pod_to_hex(keys.account_address.spend_public_key) << ENDL; std::cout << currency::get_account_address_and_payment_id_as_str(keys.account_address, payment_id) << " " << epee::string_tools::pod_to_hex(keys.account_address.view_public_key) << " " << epee::string_tools::pod_to_hex(keys.account_address.spend_public_key) << ENDL; */ for (size_t i = 0; i < sizeof addr_entries / sizeof addr_entries[0]; ++i) check_add_entry(addr_entries[i]); }