From ea2a7d19c8a5335526b6fe9efec2cd51071f6893 Mon Sep 17 00:00:00 2001 From: Tal Davidi Date: Fri, 8 Apr 2022 15:49:05 -0700 Subject: [PATCH] Update ITupleGenerator Interface. Add const + switch composite tuple order (#162) Summary: Pull Request resolved: https://github.com/facebookresearch/fbpcf/pull/162 Couple of small changes in this diff. Separating out from next diff to ease review - Make composite tuple input map const - Switch order of composite tuple from `a = vec` and `b = bool` to `a = bool` and `b = vec`. This makes consuming the tuples in the Secret Share engine consistent with normal. (i.e the secrets to be revealed are `u + a` and `v[i] + b[i]` rather than `u + b` and `v[i] + a[i]`. - Add boolean function to indicate whether composite tuples are supported and won't throw exception Reviewed By: elliottlawrence Differential Revision: D35197215 fbshipit-source-id: 29de4c9180b9d0676ef713b623ac30f1e218b5a9 --- .../tuple_generator/DummyTupleGenerator.h | 13 ++++++-- .../engine/tuple_generator/ITupleGenerator.h | 28 ++++++++++------- .../engine/tuple_generator/TupleGenerator.cpp | 5 ++-- fbpcf/engine/tuple_generator/TupleGenerator.h | 8 +++-- .../TwoPartyTupleGenerator.cpp | 30 +++++++++---------- .../tuple_generator/TwoPartyTupleGenerator.h | 8 +++-- .../test/TupleGeneratorTest.cpp | 14 ++++----- 7 files changed, 64 insertions(+), 42 deletions(-) diff --git a/fbpcf/engine/tuple_generator/DummyTupleGenerator.h b/fbpcf/engine/tuple_generator/DummyTupleGenerator.h index 388d43e4..70aefc88 100644 --- a/fbpcf/engine/tuple_generator/DummyTupleGenerator.h +++ b/fbpcf/engine/tuple_generator/DummyTupleGenerator.h @@ -27,7 +27,7 @@ class DummyTupleGenerator final : public ITupleGenerator { * @inherit doc */ std::map> getCompositeTuple( - std::map& tupleSizes) override { + const std::map& tupleSizes) override { std::map> result; for (auto& countOfTuples : tupleSizes) { size_t tupleSize = countOfTuples.first; @@ -36,8 +36,8 @@ class DummyTupleGenerator final : public ITupleGenerator { result.emplace(tupleSize, std::vector(tupleCount)); for (int i = 0; i < tupleCount; i++) { result.at(tupleSize).at(i) = CompositeBooleanTuple( - std::vector(tupleSize, 0), 0, + std::vector(tupleSize, 0), std::vector(tupleSize, 0)); } } @@ -53,13 +53,20 @@ class DummyTupleGenerator final : public ITupleGenerator { std::map>> getNormalAndCompositeBooleanTuples( uint32_t tupleSizes, - std::map& compositeTupleSizes) override { + const std::map& compositeTupleSizes) override { auto boolResult = getBooleanTuple(tupleSizes); auto compositeBoolResult = getCompositeTuple(compositeTupleSizes); return std::make_pair( std::move(boolResult), std::move(compositeBoolResult)); } + /** + * @inherit doc + */ + bool supportsCompositeTupleGeneration() override { + return true; + } + std::pair getTrafficStatistics() const override { return {0, 0}; } diff --git a/fbpcf/engine/tuple_generator/ITupleGenerator.h b/fbpcf/engine/tuple_generator/ITupleGenerator.h index f0e2f2ef..d479d209 100644 --- a/fbpcf/engine/tuple_generator/ITupleGenerator.h +++ b/fbpcf/engine/tuple_generator/ITupleGenerator.h @@ -68,20 +68,20 @@ class ITupleGenerator { public: CompositeBooleanTuple() {} - CompositeBooleanTuple(std::vector a, bool b, std::vector c) - : a_{a}, c_{c}, b_{b} { - if (a.size() != c.size()) { + CompositeBooleanTuple(bool a, std::vector b, std::vector c) + : a_{a}, b_{b}, c_{c} { + if (b.size() != c.size()) { throw std::invalid_argument("Sizes of a and c must be equal"); } } - // get the vector of A bit shares - std::vector getA() { + // get the secret-share of shared bit A + bool getA() { return a_; } - // get the secret-share of shared bit B - bool getB() { + // get the vector of B bit shares + std::vector getB() { return b_; } @@ -91,8 +91,8 @@ class ITupleGenerator { } private: - std::vector a_, c_; - bool b_; + bool a_; + std::vector b_, c_; }; /** @@ -108,7 +108,7 @@ class ITupleGenerator { * @return A map of tuple sizes to vector of those tuples */ virtual std::map> - getCompositeTuple(std::map& tupleSizes) = 0; + getCompositeTuple(const std::map& tupleSizes) = 0; /** * Wrapper method for getBooleanTuple() and getCompositeTuple() which performs @@ -119,7 +119,13 @@ class ITupleGenerator { std::map>> getNormalAndCompositeBooleanTuples( uint32_t tupleSize, - std::map& compositeTupleSizes) = 0; + const std::map& compositeTupleSizes) = 0; + + /** + * Temporary method to indicate whether it's safe to call composite tuple + * generation methods + */ + virtual bool supportsCompositeTupleGeneration() = 0; /** * Get the total amount of traffic transmitted. diff --git a/fbpcf/engine/tuple_generator/TupleGenerator.cpp b/fbpcf/engine/tuple_generator/TupleGenerator.cpp index 25f0c82e..1e8ec20a 100644 --- a/fbpcf/engine/tuple_generator/TupleGenerator.cpp +++ b/fbpcf/engine/tuple_generator/TupleGenerator.cpp @@ -59,7 +59,8 @@ std::vector TupleGenerator::generateTuples( } std::map> -TupleGenerator::getCompositeTuple(std::map& tupleSizes) { +TupleGenerator::getCompositeTuple( + const std::map& tupleSizes) { throw std::runtime_error("Not implemented"); } @@ -68,7 +69,7 @@ std::pair< std::map>> TupleGenerator::getNormalAndCompositeBooleanTuples( uint32_t tupleSize, - std::map& tupleSizes) { + const std::map& tupleSizes) { throw std::runtime_error("Not implemented"); } diff --git a/fbpcf/engine/tuple_generator/TupleGenerator.h b/fbpcf/engine/tuple_generator/TupleGenerator.h index 62de758f..a2103192 100644 --- a/fbpcf/engine/tuple_generator/TupleGenerator.h +++ b/fbpcf/engine/tuple_generator/TupleGenerator.h @@ -43,7 +43,7 @@ class TupleGenerator final : public ITupleGenerator { * @inherit doc */ std::map> getCompositeTuple( - std::map& tupleSizes) override; + const std::map& tupleSizes) override; /** * @inherit doc @@ -53,7 +53,11 @@ class TupleGenerator final : public ITupleGenerator { std::map>> getNormalAndCompositeBooleanTuples( uint32_t tupleSize, - std::map& compositeTupleSizes) override; + const std::map& compositeTupleSizes) override; + + bool supportsCompositeTupleGeneration() override { + return false; + } std::pair getTrafficStatistics() const override; diff --git a/fbpcf/engine/tuple_generator/TwoPartyTupleGenerator.cpp b/fbpcf/engine/tuple_generator/TwoPartyTupleGenerator.cpp index a00e07ff..92d66e6a 100644 --- a/fbpcf/engine/tuple_generator/TwoPartyTupleGenerator.cpp +++ b/fbpcf/engine/tuple_generator/TwoPartyTupleGenerator.cpp @@ -54,7 +54,7 @@ TwoPartyTupleGenerator::getBooleanTuple(uint32_t size) { std::map> TwoPartyTupleGenerator::getCompositeTuple( - std::map& tupleSizes) { + const std::map& tupleSizes) { std::map> tuples; for (auto& tupleSizeToCount : tupleSizes) { size_t tupleSize = std::get<0>(tupleSizeToCount); @@ -81,7 +81,7 @@ std::pair< std::map>> TwoPartyTupleGenerator::getNormalAndCompositeBooleanTuples( uint32_t tupleSize, - std::map& tupleSizes) { + const std::map& tupleSizes) { auto normalTuples = getBooleanTuple(tupleSize); auto compositeTuples = getCompositeTuple(tupleSizes); return std::make_pair(std::move(normalTuples), std::move(compositeTuples)); @@ -218,25 +218,25 @@ TwoPartyTupleGenerator::expandRCOTResults( hashFromAes_.inPlaceHash(receiverMessages); for (size_t i = 0; i < sender0Messages.size(); i++) { - // a1 = H(k0) ^ H(k1) / a2 = H(l0) ^ H(l1) - __m128i a = _mm_xor_si128(sender0Messages.at(i), sender1Messages.at(i)); - // b1 = r / b2 = p - bool b = choiceBits.at(i); + // a1 = r / a2 = p + bool a = choiceBits.at(i); + // b1 = H(k0) ^ H(k1) / b2 = H(l0) ^ H(l1) + __m128i b = _mm_xor_si128(sender0Messages.at(i), sender1Messages.at(i)); // c1 = (H(k0) ^ H(k1)) & r ^ H(k0) + H(lr) // = H(kr) + H(lr) / // c2 = (H(l0) ^ H(l1)) & p ^ H(l0) + H(kp) // = H(lp) + H(kp) - __m128i c = b + __m128i c = a ? _mm_xor_si128( - _mm_xor_si128(a, sender0Messages.at(i)), + _mm_xor_si128(b, sender0Messages.at(i)), receiverMessages.at(i)) : _mm_xor_si128(sender0Messages.at(i), receiverMessages.at(i)); - std::vector aBits(requestedTupleSize); + std::vector bBits(requestedTupleSize); std::vector cBits(requestedTupleSize); - util::extractLnbToVector(a, aBits); + util::extractLnbToVector(b, bBits); util::extractLnbToVector(c, cBits); - result[i] = CompositeBooleanTuple(aBits, b, cBits); + result[i] = CompositeBooleanTuple(a, bBits, cBits); } } else { for (size_t i = 0; i < sender0Messages.size(); i++) { @@ -250,12 +250,12 @@ TwoPartyTupleGenerator::expandRCOTResults( // H(lr) / H(kp) util::AesPrg(receiverMessages.at(i)).getRandomBitsInPlace(receiverGen); - std::vector a(requestedTupleSize); - auto b = choiceBits.at(i); + auto a = choiceBits.at(i); + std::vector b(requestedTupleSize); std::vector c(requestedTupleSize); for (size_t j = 0; j < requestedTupleSize; j++) { - a[j] = sender0Gen[j] ^ sender1Gen[j]; - c[j] = (a[j] & b) ^ sender0Gen[j] ^ receiverGen[j]; + b[j] = sender0Gen[j] ^ sender1Gen[j]; + c[j] = (b[j] & a) ^ sender0Gen[j] ^ receiverGen[j]; } result[i] = CompositeBooleanTuple(a, b, c); } diff --git a/fbpcf/engine/tuple_generator/TwoPartyTupleGenerator.h b/fbpcf/engine/tuple_generator/TwoPartyTupleGenerator.h index 19a9fa6e..4ae89f9d 100644 --- a/fbpcf/engine/tuple_generator/TwoPartyTupleGenerator.h +++ b/fbpcf/engine/tuple_generator/TwoPartyTupleGenerator.h @@ -39,7 +39,7 @@ class TwoPartyTupleGenerator final : public ITupleGenerator { * @inherit doc */ std::map> getCompositeTuple( - std::map& tupleSizes) override; + const std::map& tupleSizes) override; /** * @inherit doc @@ -49,7 +49,11 @@ class TwoPartyTupleGenerator final : public ITupleGenerator { std::map>> getNormalAndCompositeBooleanTuples( uint32_t tupleSize, - std::map& compositeTupleSizes) override; + const std::map& compositeTupleSizes) override; + + bool supportsCompositeTupleGeneration() override { + return true; + } /** * @inherit doc diff --git a/fbpcf/engine/tuple_generator/test/TupleGeneratorTest.cpp b/fbpcf/engine/tuple_generator/test/TupleGeneratorTest.cpp index 3e0f04f6..7a5fca0f 100644 --- a/fbpcf/engine/tuple_generator/test/TupleGeneratorTest.cpp +++ b/fbpcf/engine/tuple_generator/test/TupleGeneratorTest.cpp @@ -65,25 +65,25 @@ void assertResults( } for (int i = 0; i < tupleCount; i++) { - std::vector a(compositeSize); - bool b = false; + bool a = false; + std::vector b(compositeSize); std::vector c(compositeSize); for (int j = 0; j < numberOfParty; j++) { - b ^= std::get<1>(results[j]).at(compositeSize)[i].getB(); - auto aShares = std::get<1>(results[j]).at(compositeSize)[i].getA(); + a ^= std::get<1>(results[j]).at(compositeSize)[i].getA(); + auto bShares = std::get<1>(results[j]).at(compositeSize)[i].getB(); auto cShares = std::get<1>(results[j]).at(compositeSize)[i].getC(); - ASSERT_EQ(aShares.size(), compositeSize); + ASSERT_EQ(bShares.size(), compositeSize); ASSERT_EQ(cShares.size(), compositeSize); for (int k = 0; k < compositeSize; k++) { - a.at(k) = a.at(k) ^ aShares[k]; + b.at(k) = b.at(k) ^ bShares[k]; c.at(k) = c.at(k) ^ cShares[k]; } } for (int k = 0; k < compositeSize; k++) { - ASSERT_EQ(c[k], a[k] & b); + ASSERT_EQ(c[k], a & b[k]); } } }