From d1f5d008633ef213ac37ca88add5f247c7fc7ba7 Mon Sep 17 00:00:00 2001 From: Phi Date: Tue, 15 Aug 2023 15:41:26 +0000 Subject: [PATCH] Parallelizing the functions that add blinded histogram noise. (#1165) 1. Parallelizing the functions that add the blinded histogram noises. Most of the noises added are the blinded histogram noises, so parallelizing this step will help speed up the computation. 2. Updating the llv2 encryption test to make it consistent with the llv2 protocol. --- .../liquid_legions_v2_encryption_utility.cc | 59 +++++++++++-------- ...ly_liquid_legions_v2_encryption_utility.cc | 35 +++++++---- ...quid_legions_v2_encryption_utility_test.cc | 19 +++--- 3 files changed, 64 insertions(+), 49 deletions(-) diff --git a/src/main/cc/wfa/measurement/internal/duchy/protocol/liquid_legions_v2/liquid_legions_v2_encryption_utility.cc b/src/main/cc/wfa/measurement/internal/duchy/protocol/liquid_legions_v2/liquid_legions_v2_encryption_utility.cc index 62b7efc8c77..1b716fe6ee7 100644 --- a/src/main/cc/wfa/measurement/internal/duchy/protocol/liquid_legions_v2/liquid_legions_v2_encryption_utility.cc +++ b/src/main/cc/wfa/measurement/internal/duchy/protocol/liquid_legions_v2/liquid_legions_v2_encryption_utility.cc @@ -268,14 +268,15 @@ absl::StatusOr> GetSameKeyAggregatorMatrixBase( // Adds encrypted blinded-histogram-noise registers to the end of data. // returns the number of such noise registers added. absl::StatusOr AddBlindedHistogramNoise( - ProtocolCryptor& protocol_cryptor, int total_sketches_count, + MultithreadingHelper& helper, int total_sketches_count, const math::DistributedNoiser& distributed_noiser, size_t pos, std::string& data) { - ASSIGN_OR_RETURN( - std::string blinded_histogram_noise_key_ec, - protocol_cryptor.MapToCurve(kBlindedHistogramNoiseRegisterKey)); + ASSIGN_OR_RETURN(std::string blinded_histogram_noise_key_ec, + helper.GetProtocolCryptor().MapToCurve( + kBlindedHistogramNoiseRegisterKey)); int64_t noise_register_added = 0; + std::vector register_id_ecs; for (int k = 1; k <= total_sketches_count; ++k) { // The random number of distinct register_ids that should appear k times. @@ -286,33 +287,39 @@ absl::StatusOr AddBlindedHistogramNoise( // The prefix is to ensure the value is not in the regular id space. std::string register_id = absl::StrCat("blinded_histogram_noise", - protocol_cryptor.NextRandomBigNumAsString()); + helper.GetProtocolCryptor().NextRandomBigNumAsString()); ASSIGN_OR_RETURN(std::string register_id_ec, - protocol_cryptor.MapToCurve(register_id)); - // Add k registers with the same register_id but different keys and - // counts. + helper.GetProtocolCryptor().MapToCurve(register_id)); for (int j = 0; j < k; ++j) { - // Add register_id - RETURN_IF_ERROR(EncryptCompositeElGamalAndWriteToString( - protocol_cryptor, CompositeType::kFull, register_id_ec, pos, data)); - pos += kBytesPerCipherText; - // Add register key, which is the constant blinded_histogram_noise_key. - RETURN_IF_ERROR(EncryptCompositeElGamalAndWriteToString( - protocol_cryptor, CompositeType::kFull, - blinded_histogram_noise_key_ec, pos, data)); - pos += kBytesPerCipherText; - // Add register count, which can be arbitrary value. use the same value - // as key here. - RETURN_IF_ERROR(EncryptCompositeElGamalAndWriteToString( - protocol_cryptor, CompositeType::kFull, - blinded_histogram_noise_key_ec, pos, data)); - pos += kBytesPerCipherText; - - ++noise_register_added; + register_id_ecs.push_back(register_id_ec); } + noise_register_added += k; } } + absl::AnyInvocable f = + [&](ProtocolCryptor& cryptor, size_t index) -> absl::Status { + size_t current_pos = pos + kBytesPerCipherRegister * index; + // Add register_id + RETURN_IF_ERROR(EncryptCompositeElGamalAndWriteToString( + helper.GetProtocolCryptor(), CompositeType::kFull, + register_id_ecs[index], current_pos, data)); + current_pos += kBytesPerCipherText; + // Add register key, which is the constant blinded_histogram_noise_key. + RETURN_IF_ERROR(EncryptCompositeElGamalAndWriteToString( + helper.GetProtocolCryptor(), CompositeType::kFull, + blinded_histogram_noise_key_ec, current_pos, data)); + current_pos += kBytesPerCipherText; + // Add register count, which can be arbitrary value. use the same value + // as key here. + RETURN_IF_ERROR(EncryptCompositeElGamalAndWriteToString( + helper.GetProtocolCryptor(), CompositeType::kFull, + blinded_histogram_noise_key_ec, current_pos, data)); + current_pos += kBytesPerCipherText; + return absl::OkStatus(); + }; + RETURN_IF_ERROR(helper.Execute(noise_register_added, f)); + return noise_register_added; } @@ -817,7 +824,7 @@ absl::StatusOr CompleteSetupPhase( // 1. Add blinded histogram noise. ASSIGN_OR_RETURN( int64_t blinded_histogram_noise_count, - AddBlindedHistogramNoise(multithreading_helper->GetProtocolCryptor(), + AddBlindedHistogramNoise(*multithreading_helper, noise_parameters.total_sketches_count(), *blind_histogram_noiser, pos, *response_crv)); pos += kBytesPerCipherRegister * blinded_histogram_noise_count; diff --git a/src/main/cc/wfa/measurement/internal/duchy/protocol/liquid_legions_v2/reach_only_liquid_legions_v2_encryption_utility.cc b/src/main/cc/wfa/measurement/internal/duchy/protocol/liquid_legions_v2/reach_only_liquid_legions_v2_encryption_utility.cc index bb52b3b6be0..84114a8559c 100644 --- a/src/main/cc/wfa/measurement/internal/duchy/protocol/liquid_legions_v2/reach_only_liquid_legions_v2_encryption_utility.cc +++ b/src/main/cc/wfa/measurement/internal/duchy/protocol/liquid_legions_v2/reach_only_liquid_legions_v2_encryption_utility.cc @@ -155,12 +155,14 @@ int64_t CountUniqueElements(const std::vector& arr) { // Adds encrypted blinded-histogram-noise registers to the end of data. // returns the number of such noise registers added. absl::StatusOr AddReachOnlyBlindedHistogramNoise( - ProtocolCryptor& protocol_cryptor, int total_sketches_count, + MultithreadingHelper& helper, int total_sketches_count, const math::DistributedNoiser& distributed_noiser, size_t pos, std::string& data, int64_t& num_unique_noise_id) { int64_t noise_register_added = 0; num_unique_noise_id = 0; + std::vector register_id_ecs; + for (int k = 1; k <= total_sketches_count; ++k) { // The random number of distinct register_ids that should appear k times. ASSIGN_OR_RETURN(int64_t noise_register_count_for_bucket_k, @@ -172,21 +174,28 @@ absl::StatusOr AddReachOnlyBlindedHistogramNoise( // The prefix is to ensure the value is not in the regular id space. std::string register_id = absl::StrCat("blinded_histogram_noise", - protocol_cryptor.NextRandomBigNumAsString()); + helper.GetProtocolCryptor().NextRandomBigNumAsString()); ASSIGN_OR_RETURN(std::string register_id_ec, - protocol_cryptor.MapToCurve(register_id)); - // Add k registers with the same register_id. + helper.GetProtocolCryptor().MapToCurve(register_id)); for (int j = 0; j < k; ++j) { - // Add register_id - RETURN_IF_ERROR(EncryptCompositeElGamalAndWriteToString( - protocol_cryptor, CompositeType::kFull, register_id_ec, pos, data)); - pos += kBytesPerCipherText; - - ++noise_register_added; + register_id_ecs.push_back(register_id_ec); } + noise_register_added += k; } } + absl::AnyInvocable f = + [&](ProtocolCryptor& cryptor, size_t index) -> absl::Status { + size_t current_pos = pos + kBytesPerCipherText * index; + // Add register_id + RETURN_IF_ERROR(EncryptCompositeElGamalAndWriteToString( + helper.GetProtocolCryptor(), CompositeType::kFull, + register_id_ecs[index], current_pos, data)); + current_pos += kBytesPerCipherText; + return absl::OkStatus(); + }; + RETURN_IF_ERROR(helper.Execute(noise_register_added, f)); + return noise_register_added; } @@ -396,9 +405,9 @@ absl::StatusOr CompleteReachOnlySetupPhase( ASSIGN_OR_RETURN( int64_t blinded_histogram_noise_count, AddReachOnlyBlindedHistogramNoise( - multithreading_helper->GetProtocolCryptor(), - noise_parameters.total_sketches_count(), *blind_histogram_noiser, - pos, *response_crv, excessive_noise_count)); + *multithreading_helper, noise_parameters.total_sketches_count(), + *blind_histogram_noiser, pos, *response_crv, + excessive_noise_count)); pos += kBytesPerCipherText * blinded_histogram_noise_count; // 2. Add noise for publisher noise. Publisher noise count is at least 1. ASSIGN_OR_RETURN( diff --git a/src/test/cc/wfa/measurement/internal/duchy/protocol/liquid_legions_v2/liquid_legions_v2_encryption_utility_test.cc b/src/test/cc/wfa/measurement/internal/duchy/protocol/liquid_legions_v2/liquid_legions_v2_encryption_utility_test.cc index 909c98ef13f..53da7281b0c 100644 --- a/src/test/cc/wfa/measurement/internal/duchy/protocol/liquid_legions_v2/liquid_legions_v2_encryption_utility_test.cc +++ b/src/test/cc/wfa/measurement/internal/duchy/protocol/liquid_legions_v2/liquid_legions_v2_encryption_utility_test.cc @@ -329,9 +329,13 @@ class TestData { EXPECT_THAT(complete_setup_phase_response_2.combined_register_vector(), IsBlockSorted(kBytesPerEncryptedRegister)); - // Setup phase at Duchy 3. - // We assume all test data comes from duchy 1 in the test, so there is only - // noise from duchy 3 (if configured) + // Combine all CRVs. + std::string combine_data = absl::StrCat( + complete_setup_phase_response_1.combined_register_vector(), + complete_setup_phase_response_2.combined_register_vector()); + + // Setup phase at Duchy 3 (The aggregator). + // Duchy 1 and 2 send their modified combined_register_vectors to Duchy 3. CompleteSetupPhaseRequest complete_setup_phase_request_3; if (reach_noise_parameters != nullptr) { *complete_setup_phase_request_3.mutable_noise_parameters() = @@ -339,18 +343,13 @@ class TestData { } complete_setup_phase_request_3.set_noise_mechanism(noise_mechanism); complete_setup_phase_request_3.set_parallelism(kParallelism); + complete_setup_phase_request_3.set_combined_register_vector(combine_data); ASSIGN_OR_RETURN(CompleteSetupPhaseResponse complete_setup_phase_response_3, CompleteSetupPhase(complete_setup_phase_request_3)); EXPECT_THAT(complete_setup_phase_response_3.combined_register_vector(), IsBlockSorted(kBytesPerEncryptedRegister)); - // Combine all CRVs. - std::string combine_data = absl::StrCat( - complete_setup_phase_response_1.combined_register_vector(), - complete_setup_phase_response_2.combined_register_vector(), - complete_setup_phase_response_3.combined_register_vector()); - // Execution phase one at duchy 1 (non-aggregator). CompleteExecutionPhaseOneRequest complete_execution_phase_one_request_1; *complete_execution_phase_one_request_1.mutable_local_el_gamal_key_pair() = @@ -360,7 +359,7 @@ class TestData { complete_execution_phase_one_request_1.set_curve_id(kTestCurveId); complete_execution_phase_one_request_1.set_parallelism(kParallelism); complete_execution_phase_one_request_1.set_combined_register_vector( - combine_data); + complete_setup_phase_response_3.combined_register_vector()); ASSIGN_OR_RETURN( CompleteExecutionPhaseOneResponse complete_execution_phase_one_response_1,