From cd45d464355fab45af32fa457d59b295a5b16903 Mon Sep 17 00:00:00 2001 From: Yuval Shekel Date: Thu, 28 Nov 2024 15:10:26 +0200 Subject: [PATCH 01/12] Test Merkle-tree padding for all device --- icicle/tests/test_hash_api.cpp | 370 +++++++++++++++++---------------- 1 file changed, 188 insertions(+), 182 deletions(-) diff --git a/icicle/tests/test_hash_api.cpp b/icicle/tests/test_hash_api.cpp index d84cee3984..2affaa5683 100644 --- a/icicle/tests/test_hash_api.cpp +++ b/icicle/tests/test_hash_api.cpp @@ -445,7 +445,7 @@ void test_merkle_tree( // build tree START_TIMER(MerkleTree_build) ICICLE_CHECK(prover_tree.build(leaves4tree, nof_leaves * explict_leaf_size_in_bytes, config)); - END_TIMER(MerkleTree_build, "Merkle Tree build time", true) + // END_TIMER(MerkleTree_build, "Merkle Tree build time", true) ASSERT_TRUE(is_valid_tree(prover_tree, nof_leaves * explict_leaf_size_in_bytes, leaves, hashes, config)) << "Tree wasn't built correctly."; @@ -469,8 +469,8 @@ void test_merkle_tree( wrong_leaves_byte_ptr[wrong_byte_index] = new_worng_val; int wrong_leaf_idx = wrong_byte_index / leaf_size; - ICICLE_LOG_DEBUG << "Wrong input is modified at leaf " << wrong_leaf_idx << " (modified at byte " - << wrong_byte_index % leaf_size << ")"; + ICICLE_LOG_VERBOSE << "Wrong input is modified at leaf " << wrong_leaf_idx << " (modified at byte " + << wrong_byte_index % leaf_size << ")"; } T* wrong_device_leaves; @@ -484,8 +484,8 @@ void test_merkle_tree( for (int i = 0; i < nof_indices_modified; i++) { // int leaf_idx = (wrong_indices[i] % (nof_leaves * leaf_size)) / leaf_size; int leaf_idx = (wrong_indices[i] % (nof_leaves * leaf_size)) / leaf_size; - ICICLE_LOG_DEBUG << "Checking proof of index " << leaf_idx << " (Byte idx " - << (wrong_indices[i] % (nof_leaves * leaf_size)) << ")"; + ICICLE_LOG_VERBOSE << "Checking proof of index " << leaf_idx << " (Byte idx " + << (wrong_indices[i] % (nof_leaves * leaf_size)) << ")"; // get root and merkle-path for a leaf auto [root, root_size] = prover_tree.get_merkle_root(); @@ -561,200 +561,206 @@ TEST_F(HashApiTest, MerkleTreeBasic) TEST_F(HashApiTest, MerkleTreeZeroPadding) { - // TODO:add loop on devices (and change hash to one supported on gpu) - const int leaf_size = sizeof(uint32_t); - const int nof_leaves = 100; - uint32_t leaves[nof_leaves]; - randomize(leaves, nof_leaves); - ICICLE_CHECK(icicle_set_device(IcicleTestBase::reference_device())); + for (const auto& device : s_registered_devices) { + ICICLE_LOG_INFO << "MerkleTreeZeroPadding test on device=" << device; + ICICLE_CHECK(icicle_set_device(device)); - // define the merkle tree - auto layer0_hash = HashSumBackend::create(5 * leaf_size, 2 * leaf_size); // in 5 leaves, out 2 leaves 400B -> 160B - auto layer1_hash = HashSumBackend::create(4 * leaf_size, leaf_size); // in 4 leaves, out 1 leaf 160B -> 40B - auto layer2_hash = HashSumBackend::create(leaf_size, leaf_size); // in 1 leaf, out 1 leaf 40B -> 40B - auto layer3_hash = HashSumBackend::create(10 * leaf_size, leaf_size); // in 10 leaves, out 1 leaf 40B -> 4B + const int leaf_size = 256; + const int nof_leaves = 100; + std::byte leaves[nof_leaves * leaf_size]; + randomize(leaves, nof_leaves); - int total_nof_input_hashes = nof_leaves * leaf_size / layer0_hash.default_input_chunk_size(); - std::vector hashes = {layer0_hash, layer1_hash, layer2_hash, layer3_hash}; - int output_store_min_layer = 0; + // define the merkle tree + auto layer0_hash = Keccak256::create(leaf_size); + auto layer1_hash = Keccak256::create(2 * 32); + auto layer2_hash = Keccak256::create(5 * 32); + auto layer3_hash = Keccak256::create(10 * 32); - auto config = default_merkle_tree_config(); - // Test zero padding - config.padding_policy = PaddingPolicy::ZeroPadding; + int total_nof_input_hashes = nof_leaves * leaf_size / layer0_hash.default_input_chunk_size(); + std::vector hashes = {layer0_hash, layer1_hash, layer2_hash, layer3_hash}; + int output_store_min_layer = 0; - ICICLE_LOG_DEBUG << "Full tree"; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves, leaves); + auto config = default_merkle_tree_config(); + // Test zero padding + config.padding_policy = PaddingPolicy::ZeroPadding; + + ICICLE_LOG_VERBOSE << "Full tree"; + test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves, leaves); + + ICICLE_LOG_VERBOSE << "Last hash isn't full"; + test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves - 1, leaves); + + const unsigned nof_leaves_in_hash = layer0_hash.default_input_chunk_size() / leaf_size; + + ICICLE_LOG_VERBOSE << "19 hashes (Total hashes in layer 0 - 1) - full"; + test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves - nof_leaves_in_hash, leaves); + ICICLE_LOG_VERBOSE << "19 hashes (Total hashes in layer 0 - 1) - last hash not full"; + test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves - nof_leaves_in_hash - 1, leaves); + + ICICLE_LOG_VERBOSE << "16 hashes (Batch size) - full"; + test_merkle_tree(hashes, config, output_store_min_layer, 16 * nof_leaves_in_hash, leaves); + ICICLE_LOG_VERBOSE << "16 hashes (Batch size) - last hash not full"; + test_merkle_tree(hashes, config, output_store_min_layer, 16 * nof_leaves_in_hash - 1, leaves); + ICICLE_LOG_VERBOSE << "17 hashes (Batch size + 1) - full"; + test_merkle_tree(hashes, config, output_store_min_layer, 17 * nof_leaves_in_hash, leaves); + ICICLE_LOG_VERBOSE << "17 hashes (Batch size + 1) - last hash not full"; + test_merkle_tree(hashes, config, output_store_min_layer, 17 * nof_leaves_in_hash - 1, leaves); + + ICICLE_LOG_VERBOSE << "1 hash - full"; + test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves_in_hash, leaves); + ICICLE_LOG_VERBOSE << "1 leaf in tree"; + test_merkle_tree(hashes, config, output_store_min_layer, 1, leaves); + + ICICLE_LOG_VERBOSE << "A whole number of hashes is missing"; + int nof_hashes = ((rand() % (total_nof_input_hashes - 2)) + 1); + ICICLE_LOG_VERBOSE << "Number of used hashes: " << nof_hashes << " / " << total_nof_input_hashes; + test_merkle_tree(hashes, config, output_store_min_layer, nof_hashes * nof_leaves_in_hash, leaves); + + ICICLE_LOG_VERBOSE << "Random amount of leaves"; + int nof_partial_leaves = ((rand() % nof_leaves) + 1); + ICICLE_LOG_VERBOSE << "Random amount of leaves: " << nof_partial_leaves << " / " << nof_leaves; + test_merkle_tree(hashes, config, output_store_min_layer, nof_partial_leaves, leaves); + + ICICLE_LOG_VERBOSE << "Last leaf isn't fully occupied"; + auto byte_leaves = reinterpret_cast(leaves); + int byte_size; + do { + byte_size = rand() % (nof_leaves * leaf_size); + } while (byte_size % leaf_size == 0); + byte_size = 327; + ICICLE_LOG_VERBOSE << "Size of input in bytes: " << byte_size << "\t(" << float(byte_size) / leaf_size << " / " + << nof_leaves << " leaves)"; - ICICLE_LOG_DEBUG << "Last hash isn't full"; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves - 1, leaves); - - const unsigned nof_leaves_in_hash = layer0_hash.default_input_chunk_size() / leaf_size; - - ICICLE_LOG_DEBUG << "19 hashes (Total hashes in layer 0 - 1) - full"; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves - nof_leaves_in_hash, leaves); - ICICLE_LOG_DEBUG << "19 hashes (Total hashes in layer 0 - 1) - last hash not full"; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves - nof_leaves_in_hash - 1, leaves); - - ICICLE_LOG_DEBUG << "16 hashes (Batch size) - full"; - test_merkle_tree(hashes, config, output_store_min_layer, 16 * nof_leaves_in_hash, leaves); - ICICLE_LOG_DEBUG << "16 hashes (Batch size) - last hash not full"; - test_merkle_tree(hashes, config, output_store_min_layer, 16 * nof_leaves_in_hash - 1, leaves); - ICICLE_LOG_DEBUG << "17 hashes (Batch size + 1) - full"; - test_merkle_tree(hashes, config, output_store_min_layer, 17 * nof_leaves_in_hash, leaves); - ICICLE_LOG_DEBUG << "17 hashes (Batch size + 1) - last hash not full"; - test_merkle_tree(hashes, config, output_store_min_layer, 17 * nof_leaves_in_hash - 1, leaves); - - ICICLE_LOG_DEBUG << "1 hash - full"; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves_in_hash, leaves); - ICICLE_LOG_DEBUG << "1 leaf in tree"; - test_merkle_tree(hashes, config, output_store_min_layer, 1, leaves); - - ICICLE_LOG_DEBUG << "A whole number of hashes is missing"; - int nof_hashes = ((rand() % (total_nof_input_hashes - 2)) + 1); - ICICLE_LOG_DEBUG << "Number of used hashes: " << nof_hashes << " / " << total_nof_input_hashes; - test_merkle_tree(hashes, config, output_store_min_layer, nof_hashes * nof_leaves_in_hash, leaves); - - ICICLE_LOG_DEBUG << "Random amount of leaves"; - int nof_partial_leaves = ((rand() % nof_leaves) + 1); - ICICLE_LOG_DEBUG << "Random amount of leaves: " << nof_partial_leaves << " / " << nof_leaves; - test_merkle_tree(hashes, config, output_store_min_layer, nof_partial_leaves, leaves); - - ICICLE_LOG_DEBUG << "Last leaf isn't fully occupied"; - auto byte_leaves = reinterpret_cast(leaves); - int byte_size; - do { - byte_size = rand() % (nof_leaves * leaf_size); - } while (byte_size % leaf_size == 0); - byte_size = 327; - ICICLE_LOG_DEBUG << "Size of input in bytes: " << byte_size << "\t(" << float(byte_size) / leaf_size << " / " - << nof_leaves << " leaves)"; + auto prover_tree = MerkleTree::create(hashes, leaf_size, output_store_min_layer); + auto verifier_tree = MerkleTree::create(hashes, leaf_size, output_store_min_layer); - auto prover_tree = MerkleTree::create(hashes, leaf_size, output_store_min_layer); - auto verifier_tree = MerkleTree::create(hashes, leaf_size, output_store_min_layer); + // build tree + START_TIMER(MerkleTree_build) + ICICLE_CHECK(prover_tree.build(byte_leaves, byte_size, config)); + END_TIMER(MerkleTree_build, "Merkle Tree Build", true) - // build tree - START_TIMER(MerkleTree_build) - ICICLE_CHECK(prover_tree.build(byte_leaves, byte_size, config)); - END_TIMER(MerkleTree_build, "Merkle Tree CPU", true) - - ASSERT_TRUE(is_valid_tree(prover_tree, byte_size, byte_leaves, hashes, config)) << "Tree wasn't built correctly."; - - auto wrong_bytes = std::make_unique(byte_size); - memcpy(wrong_bytes.get(), byte_leaves, byte_size); - // Modify the last byte as the only difference of this test from the previous is proof for the partial index - wrong_bytes[byte_size - 1] = static_cast(rand()); - - int leaf_idx = byte_size / leaf_size; - ICICLE_LOG_DEBUG << "Checking proof of index " << leaf_idx << " (Byte idx " << leaf_idx * leaf_size << ")"; - - // get root and merkle-path for a leaf - auto [root, root_size] = prover_tree.get_merkle_root(); - MerkleProof merkle_proof{}; - ICICLE_CHECK(prover_tree.get_merkle_proof(byte_leaves, byte_size, leaf_idx, false, config, merkle_proof)); - - // Test valid proof - bool verification_valid = false; - ICICLE_CHECK(verifier_tree.verify(merkle_proof, verification_valid)); - ASSERT_TRUE(verification_valid) << "Proof of valid inputs at index " << leaf_idx - << " is invalid (And should be valid)."; - - // Test invalid proof (By modifying random data in the leaves) - verification_valid = true; - ICICLE_CHECK(prover_tree.get_merkle_proof(wrong_bytes.get(), byte_size, leaf_idx, false, config, merkle_proof)); - ICICLE_CHECK(verifier_tree.verify(merkle_proof, verification_valid)); - ASSERT_FALSE(verification_valid) << "Proof of invalid inputs at index " << leaf_idx - << " is valid (And should be invalid)."; - - // Same for pruned proof - verification_valid = false; - ICICLE_CHECK(prover_tree.get_merkle_proof(byte_leaves, byte_size, leaf_idx, true, config, merkle_proof)); - ICICLE_CHECK(verifier_tree.verify(merkle_proof, verification_valid)); - ASSERT_TRUE(verification_valid) << "Pruned proof of valid inputs at index " << leaf_idx - << " is invalid (And should be valid)."; - - // Test invalid proof (By modifying random data in the leaves) - verification_valid = true; - ICICLE_CHECK(prover_tree.get_merkle_proof(wrong_bytes.get(), byte_size, leaf_idx, true, config, merkle_proof)); - ICICLE_CHECK(verifier_tree.verify(merkle_proof, verification_valid)); - ASSERT_FALSE(verification_valid) << "Pruned proof of invalid inputs at index " << leaf_idx - << " is valid (And should be invalid)."; + ASSERT_TRUE(is_valid_tree(prover_tree, byte_size, byte_leaves, hashes, config)) << "Tree wasn't built correctly."; + + auto wrong_bytes = std::make_unique(byte_size); + memcpy(wrong_bytes.get(), byte_leaves, byte_size); + // Modify the last byte as the only difference of this test from the previous is proof for the partial index + wrong_bytes[byte_size - 1] = static_cast(rand()); + + int leaf_idx = byte_size / leaf_size; + ICICLE_LOG_VERBOSE << "Checking proof of index " << leaf_idx << " (Byte idx " << leaf_idx * leaf_size << ")"; + + // get root and merkle-path for a leaf + auto [root, root_size] = prover_tree.get_merkle_root(); + MerkleProof merkle_proof{}; + ICICLE_CHECK(prover_tree.get_merkle_proof(byte_leaves, byte_size, leaf_idx, false, config, merkle_proof)); + + // Test valid proof + bool verification_valid = false; + ICICLE_CHECK(verifier_tree.verify(merkle_proof, verification_valid)); + ASSERT_TRUE(verification_valid) << "Proof of valid inputs at index " << leaf_idx + << " is invalid (And should be valid)."; + + // Test invalid proof (By modifying random data in the leaves) + verification_valid = true; + ICICLE_CHECK(prover_tree.get_merkle_proof(wrong_bytes.get(), byte_size, leaf_idx, false, config, merkle_proof)); + ICICLE_CHECK(verifier_tree.verify(merkle_proof, verification_valid)); + ASSERT_FALSE(verification_valid) << "Proof of invalid inputs at index " << leaf_idx + << " is valid (And should be invalid)."; + + // Same for pruned proof + verification_valid = false; + ICICLE_CHECK(prover_tree.get_merkle_proof(byte_leaves, byte_size, leaf_idx, true, config, merkle_proof)); + ICICLE_CHECK(verifier_tree.verify(merkle_proof, verification_valid)); + ASSERT_TRUE(verification_valid) << "Pruned proof of valid inputs at index " << leaf_idx + << " is invalid (And should be valid)."; + + // Test invalid proof (By modifying random data in the leaves) + verification_valid = true; + ICICLE_CHECK(prover_tree.get_merkle_proof(wrong_bytes.get(), byte_size, leaf_idx, true, config, merkle_proof)); + ICICLE_CHECK(verifier_tree.verify(merkle_proof, verification_valid)); + ASSERT_FALSE(verification_valid) << "Pruned proof of invalid inputs at index " << leaf_idx + << " is valid (And should be invalid)."; + } } TEST_F(HashApiTest, MerkleTreeLastValuePadding) { - // TODO add loop on devices (and change hash to one supported on gpu) - const int leaf_size = sizeof(uint32_t); - const int nof_leaves = 100; - uint32_t leaves[nof_leaves]; - randomize(leaves, nof_leaves); - ICICLE_CHECK(icicle_set_device(IcicleTestBase::reference_device())); - - // define the merkle tree - auto layer0_hash = HashSumBackend::create(5 * leaf_size, 2 * leaf_size); // in 5 leaves, out 2 leaves 400B -> 160B - auto layer1_hash = HashSumBackend::create(4 * leaf_size, leaf_size); // in 4 leaves, out 1 leaf 160B -> 40B - auto layer2_hash = HashSumBackend::create(leaf_size, leaf_size); // in 1 leaf, out 1 leaf 40B -> 40B - auto layer3_hash = HashSumBackend::create(10 * leaf_size, leaf_size); // in 10 leaves, out 1 leaf 40B -> 4B + for (const auto& device : s_registered_devices) { + ICICLE_LOG_INFO << "MerkleTreeLastValuePadding test on device=" << device; + ICICLE_CHECK(icicle_set_device(device)); - int total_nof_input_hashes = nof_leaves * leaf_size / layer0_hash.default_input_chunk_size(); - std::vector hashes = {layer0_hash, layer1_hash, layer2_hash, layer3_hash}; - int output_store_min_layer = 0; + const int leaf_size = 320; + const int nof_leaves = 100; + std::byte leaves[nof_leaves * leaf_size]; + randomize(leaves, nof_leaves); - auto config = default_merkle_tree_config(); - // Test zero padding - config.padding_policy = PaddingPolicy::LastValue; + // define the merkle tree + auto layer0_hash = Keccak256::create(leaf_size); + auto layer1_hash = Keccak256::create(2 * 32); + auto layer2_hash = Keccak256::create(5 * 32); + auto layer3_hash = Keccak256::create(10 * 32); - ICICLE_LOG_DEBUG << "Full tree"; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves, leaves); + int total_nof_input_hashes = nof_leaves * leaf_size / layer0_hash.default_input_chunk_size(); + std::vector hashes = {layer0_hash, layer1_hash, layer2_hash, layer3_hash}; + int output_store_min_layer = 0; - ICICLE_LOG_DEBUG << "Last hash isn't full"; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves - 1, leaves); - - const unsigned nof_leaves_in_hash = layer0_hash.default_input_chunk_size() / leaf_size; - - ICICLE_LOG_DEBUG << "19 hashes (Total hashes in layer 0 - 1) - full"; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves - nof_leaves_in_hash, leaves); - ICICLE_LOG_DEBUG << "19 hashes (Total hashes in layer 0 - 1) - last hash not full"; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves - nof_leaves_in_hash - 1, leaves); - - ICICLE_LOG_DEBUG << "16 hashes (Batch size) - full"; - test_merkle_tree(hashes, config, output_store_min_layer, 16 * nof_leaves_in_hash, leaves); - ICICLE_LOG_DEBUG << "16 hashes (Batch size) - last hash not full"; - test_merkle_tree(hashes, config, output_store_min_layer, 16 * nof_leaves_in_hash - 1, leaves); - ICICLE_LOG_DEBUG << "17 hashes (Batch size + 1) - full"; - test_merkle_tree(hashes, config, output_store_min_layer, 17 * nof_leaves_in_hash, leaves); - ICICLE_LOG_DEBUG << "17 hashes (Batch size + 1) - last hash not full"; - test_merkle_tree(hashes, config, output_store_min_layer, 17 * nof_leaves_in_hash - 1, leaves); - - ICICLE_LOG_DEBUG << "1 hash - full"; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves_in_hash, leaves); - ICICLE_LOG_DEBUG << "1 leaf in tree"; - test_merkle_tree(hashes, config, output_store_min_layer, 1, leaves); - - ICICLE_LOG_DEBUG << "A whole number of hashes is missing"; - int nof_hashes = ((rand() % (total_nof_input_hashes - 2)) + 1); - ICICLE_LOG_DEBUG << "Number of used hashes: " << nof_hashes << " / " << total_nof_input_hashes; - test_merkle_tree(hashes, config, output_store_min_layer, nof_hashes * nof_leaves_in_hash, leaves); - - ICICLE_LOG_DEBUG << "Random amount of leaves"; - int nof_partial_leaves = ((rand() % nof_leaves) + 1); - ICICLE_LOG_DEBUG << "Random amount of leaves: " << nof_partial_leaves << " / " << nof_leaves; - test_merkle_tree(hashes, config, output_store_min_layer, nof_partial_leaves, leaves); - - ICICLE_LOG_DEBUG << "Last leaf isn't fully occupied - check that build should fail"; - auto byte_leaves = reinterpret_cast(leaves); - int byte_size; - do { - byte_size = rand() % (nof_leaves * leaf_size); - } while (byte_size % leaf_size == 0); - byte_size = 327; - ICICLE_LOG_DEBUG << "Size of input in bytes: " << byte_size << "\t(" << float(byte_size) / leaf_size << " / " - << nof_leaves << " leaves)"; + auto config = default_merkle_tree_config(); + // Test zero padding + config.padding_policy = PaddingPolicy::LastValue; + + ICICLE_LOG_VERBOSE << "Full tree"; + test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves, leaves); + + ICICLE_LOG_VERBOSE << "Last hash isn't full"; + test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves - 1, leaves); + + const unsigned nof_leaves_in_hash = layer0_hash.default_input_chunk_size() / leaf_size; + + ICICLE_LOG_VERBOSE << "19 hashes (Total hashes in layer 0 - 1) - full"; + test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves - nof_leaves_in_hash, leaves); + ICICLE_LOG_VERBOSE << "19 hashes (Total hashes in layer 0 - 1) - last hash not full"; + test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves - nof_leaves_in_hash - 1, leaves); + + ICICLE_LOG_VERBOSE << "16 hashes (Batch size) - full"; + test_merkle_tree(hashes, config, output_store_min_layer, 16 * nof_leaves_in_hash, leaves); + ICICLE_LOG_VERBOSE << "16 hashes (Batch size) - last hash not full"; + test_merkle_tree(hashes, config, output_store_min_layer, 16 * nof_leaves_in_hash - 1, leaves); + ICICLE_LOG_VERBOSE << "17 hashes (Batch size + 1) - full"; + test_merkle_tree(hashes, config, output_store_min_layer, 17 * nof_leaves_in_hash, leaves); + ICICLE_LOG_VERBOSE << "17 hashes (Batch size + 1) - last hash not full"; + test_merkle_tree(hashes, config, output_store_min_layer, 17 * nof_leaves_in_hash - 1, leaves); + + ICICLE_LOG_VERBOSE << "1 hash - full"; + test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves_in_hash, leaves); + ICICLE_LOG_VERBOSE << "1 leaf in tree"; + test_merkle_tree(hashes, config, output_store_min_layer, 1, leaves); + + ICICLE_LOG_VERBOSE << "A whole number of hashes is missing"; + int nof_hashes = ((rand() % (total_nof_input_hashes - 2)) + 1); + ICICLE_LOG_VERBOSE << "Number of used hashes: " << nof_hashes << " / " << total_nof_input_hashes; + test_merkle_tree(hashes, config, output_store_min_layer, nof_hashes * nof_leaves_in_hash, leaves); + + ICICLE_LOG_VERBOSE << "Random amount of leaves"; + int nof_partial_leaves = ((rand() % nof_leaves) + 1); + ICICLE_LOG_VERBOSE << "Random amount of leaves: " << nof_partial_leaves << " / " << nof_leaves; + test_merkle_tree(hashes, config, output_store_min_layer, nof_partial_leaves, leaves); + + ICICLE_LOG_VERBOSE << "Last leaf isn't fully occupied - check that build should fail"; + auto byte_leaves = reinterpret_cast(leaves); + int byte_size; + do { + byte_size = rand() % (nof_leaves * leaf_size); + } while (byte_size % leaf_size == 0); + byte_size = 327; + ICICLE_LOG_VERBOSE << "Size of input in bytes: " << byte_size << "\t(" << float(byte_size) / leaf_size << " / " + << nof_leaves << " leaves)"; - auto prover_tree = MerkleTree::create(hashes, leaf_size, output_store_min_layer); - auto verifier_tree = MerkleTree::create(hashes, leaf_size, output_store_min_layer); + auto prover_tree = MerkleTree::create(hashes, leaf_size, output_store_min_layer); + auto verifier_tree = MerkleTree::create(hashes, leaf_size, output_store_min_layer); - // build should fail when byte size isn't a whole amount of leaves and padding policy is LastValue - ASSERT_EQ(prover_tree.build(byte_leaves, byte_size, config), eIcicleError::INVALID_ARGUMENT); + // build should fail when byte size isn't a whole amount of leaves and padding policy is LastValue + ASSERT_EQ(prover_tree.build(byte_leaves, byte_size, config), eIcicleError::INVALID_ARGUMENT); + } } TEST_F(HashApiTest, MerkleTreeMixMediumSize) From 9de4831afbaf72cb4d36329bc9ac9f5df3b35c13 Mon Sep 17 00:00:00 2001 From: Yuval Shekel Date: Thu, 28 Nov 2024 17:04:41 +0200 Subject: [PATCH 02/12] refined merkle tree padding tests --- icicle/tests/test_hash_api.cpp | 186 +++++---------------------------- 1 file changed, 28 insertions(+), 158 deletions(-) diff --git a/icicle/tests/test_hash_api.cpp b/icicle/tests/test_hash_api.cpp index 2affaa5683..cf596f4454 100644 --- a/icicle/tests/test_hash_api.cpp +++ b/icicle/tests/test_hash_api.cpp @@ -561,14 +561,18 @@ TEST_F(HashApiTest, MerkleTreeBasic) TEST_F(HashApiTest, MerkleTreeZeroPadding) { + // TODO Koren: how is this testing correct padding? Any padding could work. Need to test against manually padded tree. for (const auto& device : s_registered_devices) { - ICICLE_LOG_INFO << "MerkleTreeZeroPadding test on device=" << device; + ICICLE_LOG_INFO << "MerkleTreeLastValuePadding test on device=" << device; ICICLE_CHECK(icicle_set_device(device)); - const int leaf_size = 256; - const int nof_leaves = 100; - std::byte leaves[nof_leaves * leaf_size]; - randomize(leaves, nof_leaves); + constexpr int leaf_size = 250; + constexpr int nof_leaves = 100; + const std::vector test_cases_nof_input_leaves = {1, 8, 32, + 70, 99, 100}; // those cases will be tested with padding + constexpr int input_size = nof_leaves * leaf_size; + std::byte leaves[input_size]; + randomize(leaves, input_size); // define the merkle tree auto layer0_hash = Keccak256::create(leaf_size); @@ -576,123 +580,35 @@ TEST_F(HashApiTest, MerkleTreeZeroPadding) auto layer2_hash = Keccak256::create(5 * 32); auto layer3_hash = Keccak256::create(10 * 32); - int total_nof_input_hashes = nof_leaves * leaf_size / layer0_hash.default_input_chunk_size(); std::vector hashes = {layer0_hash, layer1_hash, layer2_hash, layer3_hash}; int output_store_min_layer = 0; auto config = default_merkle_tree_config(); - // Test zero padding config.padding_policy = PaddingPolicy::ZeroPadding; - ICICLE_LOG_VERBOSE << "Full tree"; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves, leaves); - - ICICLE_LOG_VERBOSE << "Last hash isn't full"; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves - 1, leaves); - - const unsigned nof_leaves_in_hash = layer0_hash.default_input_chunk_size() / leaf_size; - - ICICLE_LOG_VERBOSE << "19 hashes (Total hashes in layer 0 - 1) - full"; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves - nof_leaves_in_hash, leaves); - ICICLE_LOG_VERBOSE << "19 hashes (Total hashes in layer 0 - 1) - last hash not full"; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves - nof_leaves_in_hash - 1, leaves); - - ICICLE_LOG_VERBOSE << "16 hashes (Batch size) - full"; - test_merkle_tree(hashes, config, output_store_min_layer, 16 * nof_leaves_in_hash, leaves); - ICICLE_LOG_VERBOSE << "16 hashes (Batch size) - last hash not full"; - test_merkle_tree(hashes, config, output_store_min_layer, 16 * nof_leaves_in_hash - 1, leaves); - ICICLE_LOG_VERBOSE << "17 hashes (Batch size + 1) - full"; - test_merkle_tree(hashes, config, output_store_min_layer, 17 * nof_leaves_in_hash, leaves); - ICICLE_LOG_VERBOSE << "17 hashes (Batch size + 1) - last hash not full"; - test_merkle_tree(hashes, config, output_store_min_layer, 17 * nof_leaves_in_hash - 1, leaves); - - ICICLE_LOG_VERBOSE << "1 hash - full"; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves_in_hash, leaves); - ICICLE_LOG_VERBOSE << "1 leaf in tree"; - test_merkle_tree(hashes, config, output_store_min_layer, 1, leaves); - - ICICLE_LOG_VERBOSE << "A whole number of hashes is missing"; - int nof_hashes = ((rand() % (total_nof_input_hashes - 2)) + 1); - ICICLE_LOG_VERBOSE << "Number of used hashes: " << nof_hashes << " / " << total_nof_input_hashes; - test_merkle_tree(hashes, config, output_store_min_layer, nof_hashes * nof_leaves_in_hash, leaves); - - ICICLE_LOG_VERBOSE << "Random amount of leaves"; - int nof_partial_leaves = ((rand() % nof_leaves) + 1); - ICICLE_LOG_VERBOSE << "Random amount of leaves: " << nof_partial_leaves << " / " << nof_leaves; - test_merkle_tree(hashes, config, output_store_min_layer, nof_partial_leaves, leaves); - - ICICLE_LOG_VERBOSE << "Last leaf isn't fully occupied"; - auto byte_leaves = reinterpret_cast(leaves); - int byte_size; - do { - byte_size = rand() % (nof_leaves * leaf_size); - } while (byte_size % leaf_size == 0); - byte_size = 327; - ICICLE_LOG_VERBOSE << "Size of input in bytes: " << byte_size << "\t(" << float(byte_size) / leaf_size << " / " - << nof_leaves << " leaves)"; - - auto prover_tree = MerkleTree::create(hashes, leaf_size, output_store_min_layer); - auto verifier_tree = MerkleTree::create(hashes, leaf_size, output_store_min_layer); - - // build tree - START_TIMER(MerkleTree_build) - ICICLE_CHECK(prover_tree.build(byte_leaves, byte_size, config)); - END_TIMER(MerkleTree_build, "Merkle Tree Build", true) - - ASSERT_TRUE(is_valid_tree(prover_tree, byte_size, byte_leaves, hashes, config)) << "Tree wasn't built correctly."; - - auto wrong_bytes = std::make_unique(byte_size); - memcpy(wrong_bytes.get(), byte_leaves, byte_size); - // Modify the last byte as the only difference of this test from the previous is proof for the partial index - wrong_bytes[byte_size - 1] = static_cast(rand()); - - int leaf_idx = byte_size / leaf_size; - ICICLE_LOG_VERBOSE << "Checking proof of index " << leaf_idx << " (Byte idx " << leaf_idx * leaf_size << ")"; - - // get root and merkle-path for a leaf - auto [root, root_size] = prover_tree.get_merkle_root(); - MerkleProof merkle_proof{}; - ICICLE_CHECK(prover_tree.get_merkle_proof(byte_leaves, byte_size, leaf_idx, false, config, merkle_proof)); - - // Test valid proof - bool verification_valid = false; - ICICLE_CHECK(verifier_tree.verify(merkle_proof, verification_valid)); - ASSERT_TRUE(verification_valid) << "Proof of valid inputs at index " << leaf_idx - << " is invalid (And should be valid)."; - - // Test invalid proof (By modifying random data in the leaves) - verification_valid = true; - ICICLE_CHECK(prover_tree.get_merkle_proof(wrong_bytes.get(), byte_size, leaf_idx, false, config, merkle_proof)); - ICICLE_CHECK(verifier_tree.verify(merkle_proof, verification_valid)); - ASSERT_FALSE(verification_valid) << "Proof of invalid inputs at index " << leaf_idx - << " is valid (And should be invalid)."; - - // Same for pruned proof - verification_valid = false; - ICICLE_CHECK(prover_tree.get_merkle_proof(byte_leaves, byte_size, leaf_idx, true, config, merkle_proof)); - ICICLE_CHECK(verifier_tree.verify(merkle_proof, verification_valid)); - ASSERT_TRUE(verification_valid) << "Pruned proof of valid inputs at index " << leaf_idx - << " is invalid (And should be valid)."; + // test various cases of missing leaves in input, requiring padding. + for (auto nof_leaves_iter : test_cases_nof_input_leaves) { + test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves_iter, leaves); + } - // Test invalid proof (By modifying random data in the leaves) - verification_valid = true; - ICICLE_CHECK(prover_tree.get_merkle_proof(wrong_bytes.get(), byte_size, leaf_idx, true, config, merkle_proof)); - ICICLE_CHECK(verifier_tree.verify(merkle_proof, verification_valid)); - ASSERT_FALSE(verification_valid) << "Pruned proof of invalid inputs at index " << leaf_idx - << " is valid (And should be invalid)."; + // Note that last leaf can be broken for zero pad. } } TEST_F(HashApiTest, MerkleTreeLastValuePadding) { + // TODO Koren: how is this testing correct padding? It passes even if zero padding it always applied for (const auto& device : s_registered_devices) { ICICLE_LOG_INFO << "MerkleTreeLastValuePadding test on device=" << device; ICICLE_CHECK(icicle_set_device(device)); - const int leaf_size = 320; - const int nof_leaves = 100; - std::byte leaves[nof_leaves * leaf_size]; - randomize(leaves, nof_leaves); + constexpr int leaf_size = 320; + constexpr int nof_leaves = 100; + const std::vector test_cases_nof_input_leaves = {1, 8, 32, + 70, 99, 100}; // those cases will be tested with padding + constexpr int input_size = nof_leaves * leaf_size; + std::byte leaves[input_size]; + randomize(leaves, input_size); // define the merkle tree auto layer0_hash = Keccak256::create(leaf_size); @@ -700,66 +616,20 @@ TEST_F(HashApiTest, MerkleTreeLastValuePadding) auto layer2_hash = Keccak256::create(5 * 32); auto layer3_hash = Keccak256::create(10 * 32); - int total_nof_input_hashes = nof_leaves * leaf_size / layer0_hash.default_input_chunk_size(); std::vector hashes = {layer0_hash, layer1_hash, layer2_hash, layer3_hash}; int output_store_min_layer = 0; auto config = default_merkle_tree_config(); - // Test zero padding config.padding_policy = PaddingPolicy::LastValue; - ICICLE_LOG_VERBOSE << "Full tree"; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves, leaves); - - ICICLE_LOG_VERBOSE << "Last hash isn't full"; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves - 1, leaves); - - const unsigned nof_leaves_in_hash = layer0_hash.default_input_chunk_size() / leaf_size; - - ICICLE_LOG_VERBOSE << "19 hashes (Total hashes in layer 0 - 1) - full"; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves - nof_leaves_in_hash, leaves); - ICICLE_LOG_VERBOSE << "19 hashes (Total hashes in layer 0 - 1) - last hash not full"; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves - nof_leaves_in_hash - 1, leaves); - - ICICLE_LOG_VERBOSE << "16 hashes (Batch size) - full"; - test_merkle_tree(hashes, config, output_store_min_layer, 16 * nof_leaves_in_hash, leaves); - ICICLE_LOG_VERBOSE << "16 hashes (Batch size) - last hash not full"; - test_merkle_tree(hashes, config, output_store_min_layer, 16 * nof_leaves_in_hash - 1, leaves); - ICICLE_LOG_VERBOSE << "17 hashes (Batch size + 1) - full"; - test_merkle_tree(hashes, config, output_store_min_layer, 17 * nof_leaves_in_hash, leaves); - ICICLE_LOG_VERBOSE << "17 hashes (Batch size + 1) - last hash not full"; - test_merkle_tree(hashes, config, output_store_min_layer, 17 * nof_leaves_in_hash - 1, leaves); - - ICICLE_LOG_VERBOSE << "1 hash - full"; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves_in_hash, leaves); - ICICLE_LOG_VERBOSE << "1 leaf in tree"; - test_merkle_tree(hashes, config, output_store_min_layer, 1, leaves); - - ICICLE_LOG_VERBOSE << "A whole number of hashes is missing"; - int nof_hashes = ((rand() % (total_nof_input_hashes - 2)) + 1); - ICICLE_LOG_VERBOSE << "Number of used hashes: " << nof_hashes << " / " << total_nof_input_hashes; - test_merkle_tree(hashes, config, output_store_min_layer, nof_hashes * nof_leaves_in_hash, leaves); - - ICICLE_LOG_VERBOSE << "Random amount of leaves"; - int nof_partial_leaves = ((rand() % nof_leaves) + 1); - ICICLE_LOG_VERBOSE << "Random amount of leaves: " << nof_partial_leaves << " / " << nof_leaves; - test_merkle_tree(hashes, config, output_store_min_layer, nof_partial_leaves, leaves); - - ICICLE_LOG_VERBOSE << "Last leaf isn't fully occupied - check that build should fail"; - auto byte_leaves = reinterpret_cast(leaves); - int byte_size; - do { - byte_size = rand() % (nof_leaves * leaf_size); - } while (byte_size % leaf_size == 0); - byte_size = 327; - ICICLE_LOG_VERBOSE << "Size of input in bytes: " << byte_size << "\t(" << float(byte_size) / leaf_size << " / " - << nof_leaves << " leaves)"; + // test various cases of missing leaves in input, requiring padding. + for (auto nof_leaves_iter : test_cases_nof_input_leaves) { + test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves_iter, leaves); + } + // Test that leaf_size divides input size for this kind of padding auto prover_tree = MerkleTree::create(hashes, leaf_size, output_store_min_layer); - auto verifier_tree = MerkleTree::create(hashes, leaf_size, output_store_min_layer); - - // build should fail when byte size isn't a whole amount of leaves and padding policy is LastValue - ASSERT_EQ(prover_tree.build(byte_leaves, byte_size, config), eIcicleError::INVALID_ARGUMENT); + ASSERT_EQ(prover_tree.build(leaves, (leaf_size - 1) * nof_leaves, config), eIcicleError::INVALID_ARGUMENT); } } From 4e6dbaf06ca7715101012167e2677d7db9e5fdc4 Mon Sep 17 00:00:00 2001 From: Koren-Brand Date: Sun, 1 Dec 2024 16:47:19 +0200 Subject: [PATCH 03/12] Adujsted test to check zero padding with partial leaves as input Signed-off-by: Koren-Brand --- icicle/tests/test_hash_api.cpp | 66 ++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/icicle/tests/test_hash_api.cpp b/icicle/tests/test_hash_api.cpp index cf596f4454..bab448308c 100644 --- a/icicle/tests/test_hash_api.cpp +++ b/icicle/tests/test_hash_api.cpp @@ -392,10 +392,12 @@ bool is_valid_tree( int nof_inputs, const T* inputs, const std::vector& hashes, - const MerkleTreeConfig& config) + const MerkleTreeConfig& config, + unsigned explicit_leaf_size = 1) { return is_valid_tree( - tree, nof_inputs * sizeof(T), sizeof(T), reinterpret_cast(inputs), hashes, config); + tree, nof_inputs * sizeof(T), sizeof(T) * explicit_leaf_size, reinterpret_cast(inputs), hashes, + config); } /** @@ -407,7 +409,9 @@ bool is_valid_tree( * @param nof_leaves - Size of the T leaves array. * @param leaves - Aforementioned leaves array. * @param explict_leaf_size_in_bytes - Optional. Size of each leaf element in case that leaves is given as a byte array. - * NOTE test will fail if this value isn't default (1) and T != std::byte + * @note Test will fail if this value isn't default (1) and T != std::byte + * @param partial_leaves_size - size of input leaves in bytes in case not a whole number of leaves is given + * @note Test will fail if this value is differe */ template void test_merkle_tree( @@ -416,7 +420,8 @@ void test_merkle_tree( const int output_store_min_layer, int nof_leaves, const T* leaves, - unsigned explict_leaf_size_in_bytes = 1) + unsigned explict_leaf_size_in_bytes = 1, + unsigned partial_leaves_size = 0) { ASSERT_TRUE((explict_leaf_size_in_bytes == 1 || std::is_same::value)) << "Explicit leaf size should only be given when the given leaves array is a bytes array."; @@ -432,7 +437,6 @@ void test_merkle_tree( const T* leaves4tree = config.is_leaves_on_device ? device_leaves : leaves; auto prover_tree = MerkleTree::create(hashes, leaf_size, output_store_min_layer); - auto prover_tree2 = MerkleTree::create(hashes, leaf_size, output_store_min_layer); auto verifier_tree = MerkleTree::create(hashes, leaf_size); // assert that incorrect size fails @@ -444,10 +448,14 @@ void test_merkle_tree( } // build tree START_TIMER(MerkleTree_build) - ICICLE_CHECK(prover_tree.build(leaves4tree, nof_leaves * explict_leaf_size_in_bytes, config)); + ICICLE_CHECK(prover_tree.build( leaves4tree, + partial_leaves_size? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, + config)); // END_TIMER(MerkleTree_build, "Merkle Tree build time", true) - - ASSERT_TRUE(is_valid_tree(prover_tree, nof_leaves * explict_leaf_size_in_bytes, leaves, hashes, config)) + + ASSERT_TRUE(is_valid_tree( prover_tree, + partial_leaves_size? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, + leaves, hashes, config, explict_leaf_size_in_bytes)) << "Tree wasn't built correctly."; // Create wrong input leaves by taking the original input and swapping some leaves by random values @@ -457,7 +465,7 @@ void test_merkle_tree( unsigned int wrong_indices[nof_indices_modified]; HashApiTest::randomize(wrong_indices, nof_indices_modified); for (int i = 0; i < nof_indices_modified; i++) { - int wrong_byte_index = wrong_indices[i] % (nof_leaves * leaf_size); + int wrong_byte_index = wrong_indices[i] % (partial_leaves_size? partial_leaves_size : nof_leaves * leaf_size); uint8_t* wrong_leaves_byte_ptr = reinterpret_cast(wrong_leaves.get()); @@ -483,15 +491,17 @@ void test_merkle_tree( // Test the paths at the random indices (Both that the original input is valid and the modified input isn't) for (int i = 0; i < nof_indices_modified; i++) { // int leaf_idx = (wrong_indices[i] % (nof_leaves * leaf_size)) / leaf_size; - int leaf_idx = (wrong_indices[i] % (nof_leaves * leaf_size)) / leaf_size; + int leaf_idx = (wrong_indices[i] % (partial_leaves_size? partial_leaves_size : nof_leaves * leaf_size)) / leaf_size; ICICLE_LOG_VERBOSE << "Checking proof of index " << leaf_idx << " (Byte idx " << (wrong_indices[i] % (nof_leaves * leaf_size)) << ")"; // get root and merkle-path for a leaf auto [root, root_size] = prover_tree.get_merkle_root(); MerkleProof merkle_proof{}; - ICICLE_CHECK(prover_tree.get_merkle_proof( - leaves, nof_leaves * explict_leaf_size_in_bytes, leaf_idx, false, config, merkle_proof)); + ICICLE_CHECK( + prover_tree.get_merkle_proof( leaves, + partial_leaves_size? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, + leaf_idx, false, config, merkle_proof)); // Test valid proof bool verification_valid = false; @@ -501,24 +511,30 @@ void test_merkle_tree( // Test invalid proof (By modifying random data in the leaves) verification_valid = true; - ICICLE_CHECK(prover_tree.get_merkle_proof( - wrong_leaves4tree, nof_leaves * explict_leaf_size_in_bytes, leaf_idx, false, config, merkle_proof)); + ICICLE_CHECK( + prover_tree.get_merkle_proof( wrong_leaves4tree, + partial_leaves_size? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, + leaf_idx, false, config, merkle_proof)); ICICLE_CHECK(verifier_tree.verify(merkle_proof, verification_valid)); ASSERT_FALSE(verification_valid) << "Proof of invalid inputs at index " << leaf_idx << " is valid (And should be invalid)."; // Same for pruned proof verification_valid = false; - ICICLE_CHECK(prover_tree.get_merkle_proof( - leaves, nof_leaves * explict_leaf_size_in_bytes, leaf_idx, true, config, merkle_proof)); + ICICLE_CHECK( + prover_tree.get_merkle_proof( leaves, + partial_leaves_size? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, + leaf_idx, true, config, merkle_proof)); ICICLE_CHECK(verifier_tree.verify(merkle_proof, verification_valid)); ASSERT_TRUE(verification_valid) << "Pruned proof of valid inputs at index " << leaf_idx << " is invalid (And should be valid)."; // Test invalid proof (By modifying random data in the leaves) verification_valid = true; - ICICLE_CHECK(prover_tree.get_merkle_proof( - wrong_leaves4tree, nof_leaves * explict_leaf_size_in_bytes, leaf_idx, true, config, merkle_proof)); + ICICLE_CHECK( + prover_tree.get_merkle_proof( wrong_leaves4tree, + partial_leaves_size? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, + leaf_idx, true, config, merkle_proof)); ICICLE_CHECK(verifier_tree.verify(merkle_proof, verification_valid)); ASSERT_FALSE(verification_valid) << "Pruned proof of invalid inputs at index " << leaf_idx << " is valid (And should be invalid)."; @@ -561,7 +577,6 @@ TEST_F(HashApiTest, MerkleTreeBasic) TEST_F(HashApiTest, MerkleTreeZeroPadding) { - // TODO Koren: how is this testing correct padding? Any padding could work. Need to test against manually padded tree. for (const auto& device : s_registered_devices) { ICICLE_LOG_INFO << "MerkleTreeLastValuePadding test on device=" << device; ICICLE_CHECK(icicle_set_device(device)); @@ -588,16 +603,21 @@ TEST_F(HashApiTest, MerkleTreeZeroPadding) // test various cases of missing leaves in input, requiring padding. for (auto nof_leaves_iter : test_cases_nof_input_leaves) { - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves_iter, leaves); + test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves_iter, leaves, leaf_size); } - // Note that last leaf can be broken for zero pad. + // Test tree with a fractional amount of leaves as input + const unsigned partial_leaf_bytes = (rand() % (leaf_size - 1)) + 1; + const unsigned nof_whole_leaves = rand() % nof_leaves; + const unsigned partial_leaves_size_in_bytes = nof_whole_leaves * leaf_size + partial_leaf_bytes; + ICICLE_LOG_VERBOSE << "Partial leaves byte size: " << partial_leaves_size_in_bytes; + test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves, leaves, leaf_size, + partial_leaves_size_in_bytes); } } TEST_F(HashApiTest, MerkleTreeLastValuePadding) { - // TODO Koren: how is this testing correct padding? It passes even if zero padding it always applied for (const auto& device : s_registered_devices) { ICICLE_LOG_INFO << "MerkleTreeLastValuePadding test on device=" << device; ICICLE_CHECK(icicle_set_device(device)); @@ -624,7 +644,7 @@ TEST_F(HashApiTest, MerkleTreeLastValuePadding) // test various cases of missing leaves in input, requiring padding. for (auto nof_leaves_iter : test_cases_nof_input_leaves) { - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves_iter, leaves); + test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves_iter, leaves, leaf_size); } // Test that leaf_size divides input size for this kind of padding From 32ad0ddf2b5d44e79383bd711bfa91e3b6636b75 Mon Sep 17 00:00:00 2001 From: Koren-Brand Date: Sun, 1 Dec 2024 16:56:52 +0200 Subject: [PATCH 04/12] Formatting Signed-off-by: Koren-Brand --- icicle/tests/test_hash_api.cpp | 54 ++++++++++++++++------------------ 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/icicle/tests/test_hash_api.cpp b/icicle/tests/test_hash_api.cpp index bab448308c..3ffbc03033 100644 --- a/icicle/tests/test_hash_api.cpp +++ b/icicle/tests/test_hash_api.cpp @@ -392,11 +392,11 @@ bool is_valid_tree( int nof_inputs, const T* inputs, const std::vector& hashes, - const MerkleTreeConfig& config, + const MerkleTreeConfig& config, unsigned explicit_leaf_size = 1) { return is_valid_tree( - tree, nof_inputs * sizeof(T), sizeof(T) * explicit_leaf_size, reinterpret_cast(inputs), hashes, + tree, nof_inputs * sizeof(T), sizeof(T) * explicit_leaf_size, reinterpret_cast(inputs), hashes, config); } @@ -448,14 +448,13 @@ void test_merkle_tree( } // build tree START_TIMER(MerkleTree_build) - ICICLE_CHECK(prover_tree.build( leaves4tree, - partial_leaves_size? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, - config)); + ICICLE_CHECK(prover_tree.build( + leaves4tree, partial_leaves_size ? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, config)); // END_TIMER(MerkleTree_build, "Merkle Tree build time", true) - - ASSERT_TRUE(is_valid_tree( prover_tree, - partial_leaves_size? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, - leaves, hashes, config, explict_leaf_size_in_bytes)) + + ASSERT_TRUE(is_valid_tree( + prover_tree, partial_leaves_size ? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, leaves, hashes, + config, explict_leaf_size_in_bytes)) << "Tree wasn't built correctly."; // Create wrong input leaves by taking the original input and swapping some leaves by random values @@ -465,7 +464,7 @@ void test_merkle_tree( unsigned int wrong_indices[nof_indices_modified]; HashApiTest::randomize(wrong_indices, nof_indices_modified); for (int i = 0; i < nof_indices_modified; i++) { - int wrong_byte_index = wrong_indices[i] % (partial_leaves_size? partial_leaves_size : nof_leaves * leaf_size); + int wrong_byte_index = wrong_indices[i] % (partial_leaves_size ? partial_leaves_size : nof_leaves * leaf_size); uint8_t* wrong_leaves_byte_ptr = reinterpret_cast(wrong_leaves.get()); @@ -491,17 +490,17 @@ void test_merkle_tree( // Test the paths at the random indices (Both that the original input is valid and the modified input isn't) for (int i = 0; i < nof_indices_modified; i++) { // int leaf_idx = (wrong_indices[i] % (nof_leaves * leaf_size)) / leaf_size; - int leaf_idx = (wrong_indices[i] % (partial_leaves_size? partial_leaves_size : nof_leaves * leaf_size)) / leaf_size; + int leaf_idx = + (wrong_indices[i] % (partial_leaves_size ? partial_leaves_size : nof_leaves * leaf_size)) / leaf_size; ICICLE_LOG_VERBOSE << "Checking proof of index " << leaf_idx << " (Byte idx " << (wrong_indices[i] % (nof_leaves * leaf_size)) << ")"; // get root and merkle-path for a leaf auto [root, root_size] = prover_tree.get_merkle_root(); MerkleProof merkle_proof{}; - ICICLE_CHECK( - prover_tree.get_merkle_proof( leaves, - partial_leaves_size? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, - leaf_idx, false, config, merkle_proof)); + ICICLE_CHECK(prover_tree.get_merkle_proof( + leaves, partial_leaves_size ? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, leaf_idx, false, + config, merkle_proof)); // Test valid proof bool verification_valid = false; @@ -511,30 +510,27 @@ void test_merkle_tree( // Test invalid proof (By modifying random data in the leaves) verification_valid = true; - ICICLE_CHECK( - prover_tree.get_merkle_proof( wrong_leaves4tree, - partial_leaves_size? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, - leaf_idx, false, config, merkle_proof)); + ICICLE_CHECK(prover_tree.get_merkle_proof( + wrong_leaves4tree, partial_leaves_size ? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, leaf_idx, + false, config, merkle_proof)); ICICLE_CHECK(verifier_tree.verify(merkle_proof, verification_valid)); ASSERT_FALSE(verification_valid) << "Proof of invalid inputs at index " << leaf_idx << " is valid (And should be invalid)."; // Same for pruned proof verification_valid = false; - ICICLE_CHECK( - prover_tree.get_merkle_proof( leaves, - partial_leaves_size? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, - leaf_idx, true, config, merkle_proof)); + ICICLE_CHECK(prover_tree.get_merkle_proof( + leaves, partial_leaves_size ? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, leaf_idx, true, + config, merkle_proof)); ICICLE_CHECK(verifier_tree.verify(merkle_proof, verification_valid)); ASSERT_TRUE(verification_valid) << "Pruned proof of valid inputs at index " << leaf_idx << " is invalid (And should be valid)."; // Test invalid proof (By modifying random data in the leaves) verification_valid = true; - ICICLE_CHECK( - prover_tree.get_merkle_proof( wrong_leaves4tree, - partial_leaves_size? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, - leaf_idx, true, config, merkle_proof)); + ICICLE_CHECK(prover_tree.get_merkle_proof( + wrong_leaves4tree, partial_leaves_size ? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, leaf_idx, + true, config, merkle_proof)); ICICLE_CHECK(verifier_tree.verify(merkle_proof, verification_valid)); ASSERT_FALSE(verification_valid) << "Pruned proof of invalid inputs at index " << leaf_idx << " is valid (And should be invalid)."; @@ -611,8 +607,8 @@ TEST_F(HashApiTest, MerkleTreeZeroPadding) const unsigned nof_whole_leaves = rand() % nof_leaves; const unsigned partial_leaves_size_in_bytes = nof_whole_leaves * leaf_size + partial_leaf_bytes; ICICLE_LOG_VERBOSE << "Partial leaves byte size: " << partial_leaves_size_in_bytes; - test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves, leaves, leaf_size, - partial_leaves_size_in_bytes); + test_merkle_tree( + hashes, config, output_store_min_layer, nof_leaves, leaves, leaf_size, partial_leaves_size_in_bytes); } } From f8b827f0ff602085b54a2ec777411058bd9983ed Mon Sep 17 00:00:00 2001 From: Koren-Brand Date: Sun, 1 Dec 2024 17:00:22 +0200 Subject: [PATCH 05/12] Added 16 ,17 cases for test (Chunk size for CPU as a test case) Signed-off-by: Koren-Brand --- icicle/tests/test_hash_api.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/icicle/tests/test_hash_api.cpp b/icicle/tests/test_hash_api.cpp index 3ffbc03033..70d0be2b30 100644 --- a/icicle/tests/test_hash_api.cpp +++ b/icicle/tests/test_hash_api.cpp @@ -579,7 +579,7 @@ TEST_F(HashApiTest, MerkleTreeZeroPadding) constexpr int leaf_size = 250; constexpr int nof_leaves = 100; - const std::vector test_cases_nof_input_leaves = {1, 8, 32, + const std::vector test_cases_nof_input_leaves = {1, 8, 16, 17, 32, 70, 99, 100}; // those cases will be tested with padding constexpr int input_size = nof_leaves * leaf_size; std::byte leaves[input_size]; @@ -620,7 +620,7 @@ TEST_F(HashApiTest, MerkleTreeLastValuePadding) constexpr int leaf_size = 320; constexpr int nof_leaves = 100; - const std::vector test_cases_nof_input_leaves = {1, 8, 32, + const std::vector test_cases_nof_input_leaves = {1, 8, 16, 17, 32, 70, 99, 100}; // those cases will be tested with padding constexpr int input_size = nof_leaves * leaf_size; std::byte leaves[input_size]; From abae8dd76ce1e0353d0e5b80cb9a8f188edb3760 Mon Sep 17 00:00:00 2001 From: Koren-Brand Date: Sun, 1 Dec 2024 17:30:31 +0200 Subject: [PATCH 06/12] Formatting Signed-off-by: Koren-Brand --- icicle/tests/test_hash_api.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/icicle/tests/test_hash_api.cpp b/icicle/tests/test_hash_api.cpp index 70d0be2b30..48c4402636 100644 --- a/icicle/tests/test_hash_api.cpp +++ b/icicle/tests/test_hash_api.cpp @@ -579,8 +579,8 @@ TEST_F(HashApiTest, MerkleTreeZeroPadding) constexpr int leaf_size = 250; constexpr int nof_leaves = 100; - const std::vector test_cases_nof_input_leaves = {1, 8, 16, 17, 32, - 70, 99, 100}; // those cases will be tested with padding + const std::vector test_cases_nof_input_leaves = {1, 8, 16, 17, + 32, 70, 99, 100}; // those cases will be tested with padding constexpr int input_size = nof_leaves * leaf_size; std::byte leaves[input_size]; randomize(leaves, input_size); @@ -620,8 +620,8 @@ TEST_F(HashApiTest, MerkleTreeLastValuePadding) constexpr int leaf_size = 320; constexpr int nof_leaves = 100; - const std::vector test_cases_nof_input_leaves = {1, 8, 16, 17, 32, - 70, 99, 100}; // those cases will be tested with padding + const std::vector test_cases_nof_input_leaves = {1, 8, 16, 17, + 32, 70, 99, 100}; // those cases will be tested with padding constexpr int input_size = nof_leaves * leaf_size; std::byte leaves[input_size]; randomize(leaves, input_size); From d018ac77dfa4ddafdc58ac00e8a274b2193cb876 Mon Sep 17 00:00:00 2001 From: Yuval Shekel Date: Tue, 3 Dec 2024 11:03:03 +0200 Subject: [PATCH 07/12] update docs: remove the note about padding not supported --- docs/docs/icicle/golang-bindings/merkle.md | 4 ---- docs/docs/icicle/primitives/merkle.md | 4 ---- docs/docs/icicle/rust-bindings/merkle.md | 4 ---- 3 files changed, 12 deletions(-) diff --git a/docs/docs/icicle/golang-bindings/merkle.md b/docs/docs/icicle/golang-bindings/merkle.md index 4e1cf90259..c5bff7c1dc 100644 --- a/docs/docs/icicle/golang-bindings/merkle.md +++ b/docs/docs/icicle/golang-bindings/merkle.md @@ -97,10 +97,6 @@ merkletree.BuildMerkleTree[byte](&mt, core.HostSliceFromElements(input), core.Ge ## Padding -:::note -Padding feature is not yet supported in **v3.1** and is planned for **v3.2**. -::: - When the input for **layer 0** is smaller than expected, ICICLE can apply **padding** to align the data. **Padding Schemes:** diff --git a/docs/docs/icicle/primitives/merkle.md b/docs/docs/icicle/primitives/merkle.md index 996a5ef96b..d3f3682b39 100644 --- a/docs/docs/icicle/primitives/merkle.md +++ b/docs/docs/icicle/primitives/merkle.md @@ -134,10 +134,6 @@ Any combination of hashers is valid including **Poseidon** that computes on fiel ## Padding -:::note -Padding feature is not yet supported in **v3.1** and is planned for **v3.2**. -::: - When the input for **layer 0** is smaller than expected, ICICLE can apply **padding** to align the data. **Padding Schemes:** diff --git a/docs/docs/icicle/rust-bindings/merkle.md b/docs/docs/icicle/rust-bindings/merkle.md index 40910a038b..ea241feefb 100644 --- a/docs/docs/icicle/rust-bindings/merkle.md +++ b/docs/docs/icicle/rust-bindings/merkle.md @@ -117,10 +117,6 @@ merkle_tree ## Padding -:::note -Padding feature is not yet supported in **v3.1** and is planned for **v3.2**. -::: - When the input for **layer 0** is smaller than expected, ICICLE can apply **padding** to align the data. **Padding Schemes:** From d18ff888f56c1bd3f77b3927a3d153e4dc4c9198 Mon Sep 17 00:00:00 2001 From: emirsoyturk Date: Wed, 4 Dec 2024 09:29:26 +0200 Subject: [PATCH 08/12] leaves on device test for padding --- icicle/tests/test_hash_api.cpp | 80 ++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/icicle/tests/test_hash_api.cpp b/icicle/tests/test_hash_api.cpp index 48c4402636..9314ce5203 100644 --- a/icicle/tests/test_hash_api.cpp +++ b/icicle/tests/test_hash_api.cpp @@ -612,6 +612,48 @@ TEST_F(HashApiTest, MerkleTreeZeroPadding) } } +TEST_F(HashApiTest, MerkleTreeZeroPaddingLeavesOnDevice) +{ + for (const auto& device : s_registered_devices) { + ICICLE_LOG_INFO << "MerkleTreeLastValuePadding test on device=" << device; + ICICLE_CHECK(icicle_set_device(device)); + + constexpr int leaf_size = 250; + constexpr int nof_leaves = 100; + const std::vector test_cases_nof_input_leaves = {1, 8, 16, 17, + 32, 70, 99, 100}; // those cases will be tested with padding + constexpr int input_size = nof_leaves * leaf_size; + std::byte leaves[input_size]; + randomize(leaves, input_size); + + // define the merkle tree + auto layer0_hash = Keccak256::create(leaf_size); + auto layer1_hash = Keccak256::create(2 * 32); + auto layer2_hash = Keccak256::create(5 * 32); + auto layer3_hash = Keccak256::create(10 * 32); + + std::vector hashes = {layer0_hash, layer1_hash, layer2_hash, layer3_hash}; + int output_store_min_layer = 0; + + auto config = default_merkle_tree_config(); + config.is_leaves_on_device = true; + config.padding_policy = PaddingPolicy::ZeroPadding; + + // test various cases of missing leaves in input, requiring padding. + for (auto nof_leaves_iter : test_cases_nof_input_leaves) { + test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves_iter, leaves, leaf_size); + } + + // Test tree with a fractional amount of leaves as input + const unsigned partial_leaf_bytes = (rand() % (leaf_size - 1)) + 1; + const unsigned nof_whole_leaves = rand() % nof_leaves; + const unsigned partial_leaves_size_in_bytes = nof_whole_leaves * leaf_size + partial_leaf_bytes; + ICICLE_LOG_VERBOSE << "Partial leaves byte size: " << partial_leaves_size_in_bytes; + test_merkle_tree( + hashes, config, output_store_min_layer, nof_leaves, leaves, leaf_size, partial_leaves_size_in_bytes); + } +} + TEST_F(HashApiTest, MerkleTreeLastValuePadding) { for (const auto& device : s_registered_devices) { @@ -649,6 +691,44 @@ TEST_F(HashApiTest, MerkleTreeLastValuePadding) } } +TEST_F(HashApiTest, MerkleTreeLastValuePaddingLeavesOnDevice) +{ + for (const auto& device : s_registered_devices) { + ICICLE_LOG_INFO << "MerkleTreeLastValuePadding test on device=" << device; + ICICLE_CHECK(icicle_set_device(device)); + + constexpr int leaf_size = 320; + constexpr int nof_leaves = 100; + const std::vector test_cases_nof_input_leaves = {1, 8, 16, 17, + 32, 70, 99, 100}; // those cases will be tested with padding + constexpr int input_size = nof_leaves * leaf_size; + std::byte leaves[input_size]; + randomize(leaves, input_size); + + // define the merkle tree + auto layer0_hash = Keccak256::create(leaf_size); + auto layer1_hash = Keccak256::create(2 * 32); + auto layer2_hash = Keccak256::create(5 * 32); + auto layer3_hash = Keccak256::create(10 * 32); + + std::vector hashes = {layer0_hash, layer1_hash, layer2_hash, layer3_hash}; + int output_store_min_layer = 0; + + auto config = default_merkle_tree_config(); + config.is_leaves_on_device = true; + config.padding_policy = PaddingPolicy::LastValue; + + // test various cases of missing leaves in input, requiring padding. + for (auto nof_leaves_iter : test_cases_nof_input_leaves) { + test_merkle_tree(hashes, config, output_store_min_layer, nof_leaves_iter, leaves, leaf_size); + } + + // Test that leaf_size divides input size for this kind of padding + auto prover_tree = MerkleTree::create(hashes, leaf_size, output_store_min_layer); + ASSERT_EQ(prover_tree.build(leaves, (leaf_size - 1) * nof_leaves, config), eIcicleError::INVALID_ARGUMENT); + } +} + TEST_F(HashApiTest, MerkleTreeMixMediumSize) { const uint32_t leaf_size = sizeof(uint32_t); From f122a76945f7940556f4f77fe8ace3adc46bd30e Mon Sep 17 00:00:00 2001 From: emirsoyturk Date: Thu, 5 Dec 2024 14:54:59 +0200 Subject: [PATCH 09/12] log --- icicle/tests/test_hash_api.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/icicle/tests/test_hash_api.cpp b/icicle/tests/test_hash_api.cpp index 9314ce5203..2563862b6f 100644 --- a/icicle/tests/test_hash_api.cpp +++ b/icicle/tests/test_hash_api.cpp @@ -411,7 +411,7 @@ bool is_valid_tree( * @param explict_leaf_size_in_bytes - Optional. Size of each leaf element in case that leaves is given as a byte array. * @note Test will fail if this value isn't default (1) and T != std::byte * @param partial_leaves_size - size of input leaves in bytes in case not a whole number of leaves is given - * @note Test will fail if this value is differe + * @note Test will fail if this value is set (not 0) and T != std::byte, or if it is larger than leaves size. */ template void test_merkle_tree( @@ -429,6 +429,8 @@ void test_merkle_tree( const unsigned leaf_size = explict_leaf_size_in_bytes > 1 ? explict_leaf_size_in_bytes : sizeof(T); const unsigned leaves_size = nof_leaves * leaf_size; + ASSERT_TRUE((partial_leaves_size == 0 || std::is_same::value) && (partial_leaves_size < leaves_size)); + T* device_leaves; if (config.is_leaves_on_device) { ICICLE_CHECK(icicle_malloc((void**)&device_leaves, leaves_size)); @@ -574,7 +576,7 @@ TEST_F(HashApiTest, MerkleTreeBasic) TEST_F(HashApiTest, MerkleTreeZeroPadding) { for (const auto& device : s_registered_devices) { - ICICLE_LOG_INFO << "MerkleTreeLastValuePadding test on device=" << device; + ICICLE_LOG_INFO << "MerkleTreeZeroPadding test on device=" << device; ICICLE_CHECK(icicle_set_device(device)); constexpr int leaf_size = 250; @@ -615,7 +617,7 @@ TEST_F(HashApiTest, MerkleTreeZeroPadding) TEST_F(HashApiTest, MerkleTreeZeroPaddingLeavesOnDevice) { for (const auto& device : s_registered_devices) { - ICICLE_LOG_INFO << "MerkleTreeLastValuePadding test on device=" << device; + ICICLE_LOG_INFO << "MerkleTreeZeroPaddingLeavesOnDevice test on device=" << device; ICICLE_CHECK(icicle_set_device(device)); constexpr int leaf_size = 250; @@ -694,7 +696,7 @@ TEST_F(HashApiTest, MerkleTreeLastValuePadding) TEST_F(HashApiTest, MerkleTreeLastValuePaddingLeavesOnDevice) { for (const auto& device : s_registered_devices) { - ICICLE_LOG_INFO << "MerkleTreeLastValuePadding test on device=" << device; + ICICLE_LOG_INFO << "MerkleTreeLastValuePaddingLeavesOnDevice test on device=" << device; ICICLE_CHECK(icicle_set_device(device)); constexpr int leaf_size = 320; From 3ad64ddfbcd11224a49cab8fed76b3aedf8294b6 Mon Sep 17 00:00:00 2001 From: emirsoyturk Date: Thu, 5 Dec 2024 18:56:29 +0200 Subject: [PATCH 10/12] temp test --- icicle/tests/test_hash_api.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/icicle/tests/test_hash_api.cpp b/icicle/tests/test_hash_api.cpp index 2563862b6f..f75d7f39cb 100644 --- a/icicle/tests/test_hash_api.cpp +++ b/icicle/tests/test_hash_api.cpp @@ -579,7 +579,7 @@ TEST_F(HashApiTest, MerkleTreeZeroPadding) ICICLE_LOG_INFO << "MerkleTreeZeroPadding test on device=" << device; ICICLE_CHECK(icicle_set_device(device)); - constexpr int leaf_size = 250; + constexpr int leaf_size = 320; // TODO: should be 250 after fix constexpr int nof_leaves = 100; const std::vector test_cases_nof_input_leaves = {1, 8, 16, 17, 32, 70, 99, 100}; // those cases will be tested with padding @@ -588,8 +588,8 @@ TEST_F(HashApiTest, MerkleTreeZeroPadding) randomize(leaves, input_size); // define the merkle tree - auto layer0_hash = Keccak256::create(leaf_size); - auto layer1_hash = Keccak256::create(2 * 32); + auto layer0_hash = Keccak256::create(leaf_size); // TODO: should be 2 * leaf_size after fix + auto layer1_hash = Keccak256::create(2 * 32); // TODO: should be 32 after fix auto layer2_hash = Keccak256::create(5 * 32); auto layer3_hash = Keccak256::create(10 * 32); @@ -620,7 +620,7 @@ TEST_F(HashApiTest, MerkleTreeZeroPaddingLeavesOnDevice) ICICLE_LOG_INFO << "MerkleTreeZeroPaddingLeavesOnDevice test on device=" << device; ICICLE_CHECK(icicle_set_device(device)); - constexpr int leaf_size = 250; + constexpr int leaf_size = 320; // TODO: should be 250 after fix constexpr int nof_leaves = 100; const std::vector test_cases_nof_input_leaves = {1, 8, 16, 17, 32, 70, 99, 100}; // those cases will be tested with padding @@ -629,8 +629,8 @@ TEST_F(HashApiTest, MerkleTreeZeroPaddingLeavesOnDevice) randomize(leaves, input_size); // define the merkle tree - auto layer0_hash = Keccak256::create(leaf_size); - auto layer1_hash = Keccak256::create(2 * 32); + auto layer0_hash = Keccak256::create(leaf_size); // TODO: should be 2 * leaf_size after fix + auto layer1_hash = Keccak256::create(2 * 32); // TODO: should be 32 after fix auto layer2_hash = Keccak256::create(5 * 32); auto layer3_hash = Keccak256::create(10 * 32); From b3b50ea63c9f4948c82e7c027ea2073348331df5 Mon Sep 17 00:00:00 2001 From: emirsoyturk Date: Thu, 5 Dec 2024 18:59:52 +0200 Subject: [PATCH 11/12] format --- icicle/tests/test_hash_api.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/icicle/tests/test_hash_api.cpp b/icicle/tests/test_hash_api.cpp index e11234d688..2fc4f903ce 100644 --- a/icicle/tests/test_hash_api.cpp +++ b/icicle/tests/test_hash_api.cpp @@ -584,8 +584,8 @@ TEST_F(HashApiTest, MerkleTreeZeroPadding) randomize(leaves, input_size); // define the merkle tree - auto layer0_hash = Keccak256::create(leaf_size); // TODO: should be 2 * leaf_size after fix - auto layer1_hash = Keccak256::create(2 * 32); // TODO: should be 32 after fix + auto layer0_hash = Keccak256::create(leaf_size); // TODO: should be 2 * leaf_size after fix + auto layer1_hash = Keccak256::create(2 * 32); // TODO: should be 32 after fix auto layer2_hash = Keccak256::create(5 * 32); auto layer3_hash = Keccak256::create(10 * 32); @@ -625,8 +625,8 @@ TEST_F(HashApiTest, MerkleTreeZeroPaddingLeavesOnDevice) randomize(leaves, input_size); // define the merkle tree - auto layer0_hash = Keccak256::create(leaf_size); // TODO: should be 2 * leaf_size after fix - auto layer1_hash = Keccak256::create(2 * 32); // TODO: should be 32 after fix + auto layer0_hash = Keccak256::create(leaf_size); // TODO: should be 2 * leaf_size after fix + auto layer1_hash = Keccak256::create(2 * 32); // TODO: should be 32 after fix auto layer2_hash = Keccak256::create(5 * 32); auto layer3_hash = Keccak256::create(10 * 32); From 8032f99af2aaadb5d62f0fbc0bf632293cdd9087 Mon Sep 17 00:00:00 2001 From: emirsoyturk Date: Thu, 5 Dec 2024 19:54:49 +0200 Subject: [PATCH 12/12] test changes --- icicle/tests/test_hash_api.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/icicle/tests/test_hash_api.cpp b/icicle/tests/test_hash_api.cpp index 2fc4f903ce..595a99e858 100644 --- a/icicle/tests/test_hash_api.cpp +++ b/icicle/tests/test_hash_api.cpp @@ -497,7 +497,7 @@ void test_merkle_tree( auto [root, root_size] = prover_tree.get_merkle_root(); MerkleProof merkle_proof{}; ICICLE_CHECK(prover_tree.get_merkle_proof( - leaves, partial_leaves_size ? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, leaf_idx, false, + leaves4tree, partial_leaves_size ? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, leaf_idx, false, config, merkle_proof)); // Test valid proof @@ -518,7 +518,7 @@ void test_merkle_tree( // Same for pruned proof verification_valid = false; ICICLE_CHECK(prover_tree.get_merkle_proof( - leaves, partial_leaves_size ? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, leaf_idx, true, + leaves4tree, partial_leaves_size ? partial_leaves_size : nof_leaves * explict_leaf_size_in_bytes, leaf_idx, true, config, merkle_proof)); ICICLE_CHECK(verifier_tree.verify(merkle_proof, verification_valid)); ASSERT_TRUE(verification_valid) << "Pruned proof of valid inputs at index " << leaf_idx @@ -575,7 +575,7 @@ TEST_F(HashApiTest, MerkleTreeZeroPadding) ICICLE_LOG_INFO << "MerkleTreeZeroPadding test on device=" << device; ICICLE_CHECK(icicle_set_device(device)); - constexpr int leaf_size = 320; // TODO: should be 250 after fix + constexpr int leaf_size = 250; constexpr int nof_leaves = 100; const std::vector test_cases_nof_input_leaves = {1, 8, 16, 17, 32, 70, 99, 100}; // those cases will be tested with padding @@ -584,10 +584,10 @@ TEST_F(HashApiTest, MerkleTreeZeroPadding) randomize(leaves, input_size); // define the merkle tree - auto layer0_hash = Keccak256::create(leaf_size); // TODO: should be 2 * leaf_size after fix - auto layer1_hash = Keccak256::create(2 * 32); // TODO: should be 32 after fix - auto layer2_hash = Keccak256::create(5 * 32); - auto layer3_hash = Keccak256::create(10 * 32); + auto layer0_hash = Blake2s::create(2 * leaf_size); + auto layer1_hash = Blake2s::create(32); + auto layer2_hash = Blake2s::create(5 * 32); + auto layer3_hash = Blake2s::create(10 * 32); std::vector hashes = {layer0_hash, layer1_hash, layer2_hash, layer3_hash}; int output_store_min_layer = 0;