From 35a252989833d02d2e423f9d35ca43365ac20f72 Mon Sep 17 00:00:00 2001 From: Tal Davidi Date: Wed, 26 Oct 2022 16:31:08 -0700 Subject: [PATCH] Update function signatures of UDP InputProcessor Summary: Updates the signatures of `CompactionBasedInputProcessor` functions to slightly change the workflow of `getPlaintextData` logic, as well as adding the data structs that will be used for serialization / deserialization logic in `compactData` Rather than relying on the `getUnionMap` to shuffle the data in place, it will instead assume that the method for generation of `unionMap` is randomly secure. The high level algorithm is as follows: 1. Generate a random permutation of PID elements (i.e. `[1,3,4,0,2]` indicates the order of PID's in shuffled data) 2. Create the union map where -1 indicates dummy row, and `value > 0` indicates the index of that row in plaintext data after applying permutation to PID's (i.e. if PID `1` and `3` are dummy rows the map is `[1, -1, 2,-1,0]`). Not that the `maximumVal+1` (3) indicates the number of partner input rows. Each value appears once in the `unionMap` 3. In the prepare plaintext data step, it will generate a reverse unionMap without dummy rows. The plaintext data will be serialized by iterating through the reverse map in order and taking the input data at that location (i.e. `[4, 0, 2]`). {F785701567} Reviewed By: chennyc Differential Revision: D40687410 fbshipit-source-id: 82f622ce1cbe94eb5ec091196a19b471c10834d6 --- .../CompactionBasedInputProcessor.h | 57 +++++++++++++++---- .../CompactionBasedInputProcessor_impl.h | 50 ++++++++++------ 2 files changed, 79 insertions(+), 28 deletions(-) diff --git a/fbpcs/emp_games/lift/pcf2_calculator/input_processing/CompactionBasedInputProcessor.h b/fbpcs/emp_games/lift/pcf2_calculator/input_processing/CompactionBasedInputProcessor.h index 824a14bbb..46c271ff1 100644 --- a/fbpcs/emp_games/lift/pcf2_calculator/input_processing/CompactionBasedInputProcessor.h +++ b/fbpcs/emp_games/lift/pcf2_calculator/input_processing/CompactionBasedInputProcessor.h @@ -47,10 +47,14 @@ class CompactionBasedInputProcessor : public IInputProcessor { auto unionMap = shuffleAndGetUnionMap(); auto intersectionMap = getIntersectionMap(unionMap); - auto plaintextData = preparePlaintextData(); + auto plaintextData = preparePlaintextData(unionMap); - compactData(intersectionMap, plaintextData); - extractCompactedData(); + auto publisherPartnerJointMetadataShares = + compactData(intersectionMap, plaintextData); + + extractCompactedData( + std::get<0>(publisherPartnerJointMetadataShares), + std::get<1>(publisherPartnerJointMetadataShares)); } const LiftGameProcessedData& getLiftGameProcessedData() @@ -59,7 +63,36 @@ class CompactionBasedInputProcessor : public IInputProcessor { } private: - // shuffles the input data and returns the union map + struct PartnerRow { + bool anyValidPurchaseTimestamp; + uint32_t cohortGroupId; + }; + + struct PartnerConversionRow { + uint32_t purchaseTimestamp; + uint32_t thresholdTimestamp; + int32_t purchaseValue; + int64_t purchaseValueSquared; + }; + + struct PublisherRow { + bool breakdownId; + bool controlPopulation; + bool isValidOpportunityTimestamp; + bool testReach; + uint32_t opportunityTimestamp; + }; + + // Update the values if changing the structs above. This class handles it's + // own serialization / deserialization. using sizeof() will not work because a + // bool will take 1 byte in memory + const int PARTNER_ROW_SIZE_BYTES = 5; + const int PARTNER_CONVERSION_ROW_SIZE_BYTES = 20; + const int PUBLISHER_ROW_BYTES = 5; + + // unionMap[i] = j indicates PID i will point to index j in plaintext data + // note that j in [0,intersectionSize) rather than [0, unionSize) + // unionMap[i] = -1 indicates PID i is a dummy row std::vector shuffleAndGetUnionMap(); // runs adapter algorithm to get intsersection map @@ -67,18 +100,21 @@ class CompactionBasedInputProcessor : public IInputProcessor { // Serializes input data into rows of fixed width. Different implementations // for publisher and partner - std::vector> preparePlaintextData(); + std::vector> preparePlaintextData( + const std::vector& unionMap); /* Runs data processor algorithm to get intersected secret share data - * intersectionMap is the map of other player. Results are stored in - * publisherDataShares_ and partnerDataShares_ + * intersectionMap is the map of other player. First element is publisher + * metadata shares, second is partner metadata shares */ - void compactData( + std::pair compactData( const std::vector& intersectionMap, const std::vector>& plaintextData); // deserializes the compacted data into MPC structured values - void extractCompactedData(); + void extractCompactedData( + const SecString& publisherDataShares, + const SecString& partnerDataShares); int32_t myRole_; @@ -90,9 +126,6 @@ class CompactionBasedInputProcessor : public IInputProcessor { InputData inputData_; int32_t numConversionsPerUser_; - SecString publisherDataShares_; - SecString partnerDataShares_; - LiftGameProcessedData liftGameProcessedData_; }; diff --git a/fbpcs/emp_games/lift/pcf2_calculator/input_processing/CompactionBasedInputProcessor_impl.h b/fbpcs/emp_games/lift/pcf2_calculator/input_processing/CompactionBasedInputProcessor_impl.h index ff223ba6f..4cc37dc8f 100644 --- a/fbpcs/emp_games/lift/pcf2_calculator/input_processing/CompactionBasedInputProcessor_impl.h +++ b/fbpcs/emp_games/lift/pcf2_calculator/input_processing/CompactionBasedInputProcessor_impl.h @@ -34,43 +34,61 @@ CompactionBasedInputProcessor::getIntersectionMap( template std::vector> -CompactionBasedInputProcessor::preparePlaintextData() { +CompactionBasedInputProcessor::preparePlaintextData( + const std::vector& unionMap) { throw std::runtime_error("Not implemented"); } template -void CompactionBasedInputProcessor::compactData( +std::pair< + typename CompactionBasedInputProcessor::SecString, + typename CompactionBasedInputProcessor::SecString> +CompactionBasedInputProcessor::compactData( const std::vector& intersectionMap, const std::vector>& plaintextData) { - int32_t myDataWidth = plaintextData[0].size(); + int32_t myRows = plaintextData.size(); - auto publisherDataSize = common::shareIntFrom< + auto publisherRows = common::shareIntFrom< schedulerId, - sizeof(myDataWidth) * 8, + sizeof(myRows) * 8, common::PUBLISHER, - common::PARTNER>(myRole_, myDataWidth); + common::PARTNER>(myRole_, myRows); - auto partnerDataSize = common::shareIntFrom< + auto partnerRows = common::shareIntFrom< schedulerId, - sizeof(myDataWidth) * 8, + sizeof(myRows) * 8, common::PARTNER, - common::PUBLISHER>(myRole_, myDataWidth); + common::PUBLISHER>(myRole_, myRows); + SecString publisherDataShares; + SecString partnerDataShares; if (myRole_ == common::PUBLISHER) { - publisherDataShares_ = + publisherDataShares = dataProcessor_->processMyData(plaintextData, intersectionMap.size()); - partnerDataShares_ = dataProcessor_->processPeersData( - inputData_.getNumRows(), intersectionMap, partnerDataSize); + partnerDataShares = dataProcessor_->processPeersData( + partnerRows, + intersectionMap, + PARTNER_CONVERSION_ROW_SIZE_BYTES * numConversionsPerUser_ + + PARTNER_ROW_SIZE_BYTES); } else if (myRole_ == common::PARTNER) { - publisherDataShares_ = dataProcessor_->processPeersData( - inputData_.getNumRows(), intersectionMap, publisherDataSize); - partnerDataShares_ = + publisherDataShares = dataProcessor_->processPeersData( + publisherRows, intersectionMap, PUBLISHER_ROW_BYTES); + partnerDataShares = dataProcessor_->processMyData(plaintextData, intersectionMap.size()); } + + return std::make_pair< + typename CompactionBasedInputProcessor::SecString, + typename CompactionBasedInputProcessor::SecString>( + std::move(publisherDataShares), std::move(partnerDataShares)); } template -void CompactionBasedInputProcessor::extractCompactedData() { +void CompactionBasedInputProcessor::extractCompactedData( + const typename CompactionBasedInputProcessor::SecString& + publisherDataShares, + const typename CompactionBasedInputProcessor::SecString& + partnerDataShares) { throw std::runtime_error("Not implemented"); }