diff options
Diffstat (limited to 'tests/unit_tests/crypto.cpp')
-rw-r--r-- | tests/unit_tests/crypto.cpp | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/tests/unit_tests/crypto.cpp b/tests/unit_tests/crypto.cpp index 7ac87ca7c..b550b35b0 100644 --- a/tests/unit_tests/crypto.cpp +++ b/tests/unit_tests/crypto.cpp @@ -33,6 +33,7 @@ #include <string> #include "cryptonote_basic/cryptonote_basic_impl.h" +#include "cryptonote_basic/merge_mining.h" namespace { @@ -99,3 +100,215 @@ TEST(Crypto, verify_32) } } } + +TEST(Crypto, tree_branch) +{ + crypto::hash inputs[6]; + crypto::hash branch[8]; + crypto::hash root, root2; + size_t depth; + uint32_t path, path2; + + auto hasher = [](const crypto::hash &h0, const crypto::hash &h1) -> crypto::hash + { + char buffer[64]; + memcpy(buffer, &h0, 32); + memcpy(buffer + 32, &h1, 32); + crypto::hash res; + cn_fast_hash(buffer, 64, res); + return res; + }; + + for (int n = 0; n < 6; ++n) + { + memset(&inputs[n], 0, 32); + inputs[n].data[0] = n + 1; + } + + // empty + ASSERT_FALSE(crypto::tree_branch((const char(*)[32])inputs, 0, crypto::null_hash.data, (char(*)[32])branch, &depth, &path)); + + // one, matching + ASSERT_TRUE(crypto::tree_branch((const char(*)[32])inputs, 1, inputs[0].data, (char(*)[32])branch, &depth, &path)); + ASSERT_EQ(depth, 0); + ASSERT_EQ(path, 0); + ASSERT_TRUE(crypto::tree_path(1, 0, &path2)); + ASSERT_EQ(path, path2); + crypto::tree_hash((const char(*)[32])inputs, 1, root.data); + ASSERT_EQ(root, inputs[0]); + ASSERT_TRUE(crypto::is_branch_in_tree(inputs[0].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[1].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(crypto::null_hash.data, root.data, (const char(*)[32])branch, depth, path)); + + // one, not found + ASSERT_FALSE(crypto::tree_branch((const char(*)[32])inputs, 1, inputs[1].data, (char(*)[32])branch, &depth, &path)); + + // two, index 0 + ASSERT_TRUE(crypto::tree_branch((const char(*)[32])inputs, 2, inputs[0].data, (char(*)[32])branch, &depth, &path)); + ASSERT_EQ(depth, 1); + ASSERT_EQ(path, 0); + ASSERT_TRUE(crypto::tree_path(2, 0, &path2)); + ASSERT_EQ(path, path2); + ASSERT_EQ(branch[0], inputs[1]); + crypto::tree_hash((const char(*)[32])inputs, 2, root.data); + ASSERT_EQ(root, hasher(inputs[0], inputs[1])); + ASSERT_TRUE(crypto::is_branch_in_tree(inputs[0].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[1].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[2].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(crypto::null_hash.data, root.data, (const char(*)[32])branch, depth, path)); + + // two, index 1 + ASSERT_TRUE(crypto::tree_branch((const char(*)[32])inputs, 2, inputs[1].data, (char(*)[32])branch, &depth, &path)); + ASSERT_EQ(depth, 1); + ASSERT_EQ(path, 1); + ASSERT_TRUE(crypto::tree_path(2, 1, &path2)); + ASSERT_EQ(path, path2); + ASSERT_EQ(branch[0], inputs[0]); + crypto::tree_hash((const char(*)[32])inputs, 2, root.data); + ASSERT_EQ(root, hasher(inputs[0], inputs[1])); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[0].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_TRUE(crypto::is_branch_in_tree(inputs[1].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[2].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(crypto::null_hash.data, root.data, (const char(*)[32])branch, depth, path)); + + // two, not found + ASSERT_FALSE(crypto::tree_branch((const char(*)[32])inputs, 2, inputs[2].data, (char(*)[32])branch, &depth, &path)); + + // a b c 0 + // x y + // z + + // three, index 0 + ASSERT_TRUE(crypto::tree_branch((const char(*)[32])inputs, 3, inputs[0].data, (char(*)[32])branch, &depth, &path)); + ASSERT_GE(depth, 1); + ASSERT_LE(depth, 2); + ASSERT_TRUE(crypto::tree_path(3, 0, &path2)); + ASSERT_EQ(path, path2); + crypto::tree_hash((const char(*)[32])inputs, 3, root.data); + ASSERT_EQ(root, hasher(inputs[0], hasher(inputs[1], inputs[2]))); + ASSERT_TRUE(crypto::is_branch_in_tree(inputs[0].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[1].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[2].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[3].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(crypto::null_hash.data, root.data, (const char(*)[32])branch, depth, path)); + + // three, index 1 + ASSERT_TRUE(crypto::tree_branch((const char(*)[32])inputs, 3, inputs[1].data, (char(*)[32])branch, &depth, &path)); + ASSERT_GE(depth, 1); + ASSERT_LE(depth, 2); + ASSERT_TRUE(crypto::tree_path(3, 1, &path2)); + ASSERT_EQ(path, path2); + crypto::tree_hash((const char(*)[32])inputs, 3, root.data); + ASSERT_EQ(root, hasher(inputs[0], hasher(inputs[1], inputs[2]))); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[0].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_TRUE(crypto::is_branch_in_tree(inputs[1].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[2].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[3].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(crypto::null_hash.data, root.data, (const char(*)[32])branch, depth, path)); + + // three, index 2 + ASSERT_TRUE(crypto::tree_branch((const char(*)[32])inputs, 3, inputs[2].data, (char(*)[32])branch, &depth, &path)); + ASSERT_GE(depth, 1); + ASSERT_LE(depth, 2); + ASSERT_TRUE(crypto::tree_path(3, 2, &path2)); + ASSERT_EQ(path, path2); + crypto::tree_hash((const char(*)[32])inputs, 3, root.data); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[0].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[1].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_TRUE(crypto::is_branch_in_tree(inputs[2].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[3].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(crypto::null_hash.data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_TRUE(crypto::tree_branch_hash(inputs[2].data, (const char(*)[32])branch, depth, path, root2.data)); + ASSERT_EQ(root, root2); + + // three, not found + ASSERT_FALSE(crypto::tree_branch((const char(*)[32])inputs, 3, inputs[3].data, (char(*)[32])branch, &depth, &path)); + + // a b c d e 0 0 0 + // x y + // z + // w + + // five, index 0 + ASSERT_TRUE(crypto::tree_branch((const char(*)[32])inputs, 5, inputs[0].data, (char(*)[32])branch, &depth, &path)); + ASSERT_GE(depth, 2); + ASSERT_LE(depth, 3); + ASSERT_TRUE(crypto::tree_path(5, 0, &path2)); + ASSERT_EQ(path, path2); + crypto::tree_hash((const char(*)[32])inputs, 5, root.data); + ASSERT_TRUE(crypto::is_branch_in_tree(inputs[0].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[1].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[2].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[3].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[4].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[5].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(crypto::null_hash.data, root.data, (const char(*)[32])branch, depth, path)); + + // five, index 1 + ASSERT_TRUE(crypto::tree_branch((const char(*)[32])inputs, 5, inputs[1].data, (char(*)[32])branch, &depth, &path)); + ASSERT_GE(depth, 2); + ASSERT_LE(depth, 3); + ASSERT_TRUE(crypto::tree_path(5, 1, &path2)); + ASSERT_EQ(path, path2); + crypto::tree_hash((const char(*)[32])inputs, 5, root.data); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[0].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_TRUE(crypto::is_branch_in_tree(inputs[1].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[2].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[3].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[4].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[5].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(crypto::null_hash.data, root.data, (const char(*)[32])branch, depth, path)); + + // five, index 2 + ASSERT_TRUE(crypto::tree_branch((const char(*)[32])inputs, 5, inputs[2].data, (char(*)[32])branch, &depth, &path)); + ASSERT_GE(depth, 2); + ASSERT_LE(depth, 3); + ASSERT_TRUE(crypto::tree_path(5, 2, &path2)); + ASSERT_EQ(path, path2); + crypto::tree_hash((const char(*)[32])inputs, 5, root.data); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[0].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[1].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_TRUE(crypto::is_branch_in_tree(inputs[2].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[3].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[4].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[5].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(crypto::null_hash.data, root.data, (const char(*)[32])branch, depth, path)); + + // five, index 4 + ASSERT_TRUE(crypto::tree_branch((const char(*)[32])inputs, 5, inputs[4].data, (char(*)[32])branch, &depth, &path)); + ASSERT_GE(depth, 2); + ASSERT_LE(depth, 3); + ASSERT_TRUE(crypto::tree_path(5, 4, &path2)); + ASSERT_EQ(path, path2); + crypto::tree_hash((const char(*)[32])inputs, 5, root.data); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[0].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[1].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[2].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[3].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_TRUE(crypto::is_branch_in_tree(inputs[4].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[5].data, root.data, (const char(*)[32])branch, depth, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(crypto::null_hash.data, root.data, (const char(*)[32])branch, depth, path)); + + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[4].data, root.data, (const char(*)[32])branch, depth - 1, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[4].data, root.data, (const char(*)[32])branch, depth + 1, path)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[4].data, root.data, (const char(*)[32])branch, depth, path ^ 1)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[4].data, root.data, (const char(*)[32])branch, depth, path ^ 2)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[4].data, root.data, (const char(*)[32])branch, depth, path ^ 3)); + ASSERT_FALSE(crypto::is_branch_in_tree(inputs[4].data, root.data, (const char(*)[32])(branch + 1), depth, path)); + + // five, not found + ASSERT_FALSE(crypto::tree_branch((const char(*)[32])inputs, 5, crypto::null_hash.data, (char(*)[32])branch, &depth, &path)); + + // depth encoding roundtrip + for (uint32_t n_chains = 1; n_chains <= 65; ++n_chains) + { + for (uint32_t nonce = 0; nonce < 1024; ++nonce) + { + const uint32_t depth = cryptonote::encode_mm_depth(n_chains, nonce); + uint32_t n_chains_2, nonce_2; + ASSERT_TRUE(cryptonote::decode_mm_depth(depth, n_chains_2, nonce_2)); + ASSERT_EQ(n_chains, n_chains_2); + ASSERT_EQ(nonce, nonce_2); + } + } +} |