diff --git a/tests/test_frodoPIR.cpp b/tests/test_frodoPIR.cpp index f572a1c..71a551f 100644 --- a/tests/test_frodoPIR.cpp +++ b/tests/test_frodoPIR.cpp @@ -74,3 +74,89 @@ TEST(FrodoPIR, PrivateInformationRetrieval) test_private_information_retrieval<1ul << 16, 32, 10, 1774>(32); test_private_information_retrieval<1ul << 20, 32, 9, 1774>(32); } + +TEST(FrodoPIR, ClientQueryCacheStateTransition) +{ + constexpr size_t λ = 128; + constexpr size_t db_entry_count = 1ul << 16; + constexpr size_t db_entry_byte_len = 32; + constexpr size_t mat_element_bitlen = 10; + constexpr size_t lwe_dimension = 1774; + constexpr size_t parsed_db_column_count = frodoPIR_matrix::get_required_num_columns(db_entry_byte_len, mat_element_bitlen); + constexpr size_t db_byte_len = db_entry_count * db_entry_byte_len; + constexpr size_t pub_matM_byte_len = frodoPIR_matrix::matrix_t::get_byte_len(); + constexpr size_t query_byte_len = frodoPIR_vector::row_vector_t::get_byte_len(); + constexpr size_t response_byte_len = frodoPIR_vector::row_vector_t::get_byte_len(); + + std::array::digits> seed_μ{}; + std::vector db_bytes(db_byte_len, 0); + std::vector pub_matM_bytes(pub_matM_byte_len, 0); + std::vector query_bytes(query_byte_len, 0); + std::vector response_bytes(response_byte_len, 0); + std::vector db_row_bytes(db_entry_byte_len, 0); + + auto db_bytes_span = std::span(db_bytes); + auto pub_matM_bytes_span = std::span(pub_matM_bytes); + auto query_bytes_span = std::span(query_bytes); + auto response_bytes_span = std::span(response_bytes); + auto db_row_bytes_span = std::span(db_row_bytes); + + prng::prng_t prng{}; + + prng.read(seed_μ); + prng.read(db_bytes); + + auto [server, M] = frodoPIR_server::server_t<λ, db_entry_count, db_entry_byte_len, mat_element_bitlen, lwe_dimension>::setup(seed_μ, db_bytes_span); + + M.to_le_bytes(pub_matM_bytes_span); + auto client = frodoPIR_client::client_t<λ, db_entry_count, db_entry_byte_len, mat_element_bitlen, lwe_dimension>::setup(seed_μ, pub_matM_bytes_span); + + constexpr size_t db_first_row_index = 0; + constexpr size_t db_second_row_index = db_first_row_index + 1; + + // Before query for specific database row is prepared, attempt to use the query or decode response for the query. + EXPECT_FALSE(client.query(db_first_row_index, query_bytes_span)); + EXPECT_FALSE(client.query(db_second_row_index, query_bytes_span)); + EXPECT_FALSE(client.process_response(db_first_row_index, response_bytes_span, db_row_bytes_span)); + EXPECT_FALSE(client.process_response(db_second_row_index, response_bytes_span, db_row_bytes_span)); + + // Prepare query for a specific database row. + EXPECT_TRUE(client.prepare_query(db_first_row_index, prng)); + // Retry preparing query for the same database row. + EXPECT_FALSE(client.prepare_query(db_first_row_index, prng)); + + // Prepare query for a different database row. + EXPECT_TRUE(client.prepare_query(db_second_row_index, prng)); + // Retry preparing query for same database row. + EXPECT_FALSE(client.prepare_query(db_second_row_index, prng)); + + // Attempt processing response for specific database row even though query for that row is not yet sent. + EXPECT_FALSE(client.process_response(db_first_row_index, response_bytes_span, db_row_bytes_span)); + EXPECT_FALSE(client.process_response(db_second_row_index, response_bytes_span, db_row_bytes_span)); + + // Finalize query for specific database row. + EXPECT_TRUE(client.query(db_first_row_index, query_bytes_span)); + // Retry finalizing query for same database row. + EXPECT_FALSE(client.query(db_first_row_index, query_bytes_span)); + + // Finalize query for different database row. + EXPECT_TRUE(client.query(db_second_row_index, query_bytes_span)); + // Retry finalizing query for same database row. + EXPECT_FALSE(client.query(db_second_row_index, query_bytes_span)); + + // Ask server to respond for finalized query. + server.respond(query_bytes_span, response_bytes_span); + + // Process response obtained from server, decoding database row. + EXPECT_TRUE(client.process_response(db_first_row_index, response_bytes_span, db_row_bytes_span)); + // Retry processing response obtained from server, attempting to decode same database row. + EXPECT_FALSE(client.process_response(db_first_row_index, response_bytes_span, db_row_bytes_span)); + + // Process response obtained from server, decoding database row. + EXPECT_TRUE(client.process_response(db_second_row_index, response_bytes_span, db_row_bytes_span)); + // Retry processing response obtained from server, attempting to decode same database row. + EXPECT_FALSE(client.process_response(db_second_row_index, response_bytes_span, db_row_bytes_span)); + + constexpr size_t db_second_row_bytes_begin_at = db_second_row_index * db_entry_byte_len; + EXPECT_TRUE(std::ranges::equal(db_row_bytes_span, db_bytes_span.subspan(db_second_row_bytes_begin_at, db_entry_byte_len))); +}