diff --git a/cryptoTools b/cryptoTools index 1ffddc5..c09f5f5 160000 --- a/cryptoTools +++ b/cryptoTools @@ -1 +1 @@ -Subproject commit 1ffddc5215231d6ebda47b84c4b42782a7f4e790 +Subproject commit c09f5f59ba8718c7170bedf13f8d0d9655b3381e diff --git a/libOTe/Tools/CoeffCtx.h b/libOTe/Tools/CoeffCtx.h index a070d12..a73dec1 100644 --- a/libOTe/Tools/CoeffCtx.h +++ b/libOTe/Tools/CoeffCtx.h @@ -82,7 +82,12 @@ namespace osuCrypto { OC_FORCEINLINE void fromBlock(F& ret, const block& b) { static_assert(std::is_trivially_copyable::value, "memcpy is used so must be trivially_copyable."); - if constexpr (sizeof(F) <= sizeof(block)) + if constexpr (std::is_same::value) + { + // if F is a block, just return the block. + ret = b; + } + else if constexpr (sizeof(F) <= sizeof(block)) { // if small, just return the bytes of b memcpy(&ret, &b, sizeof(F)); diff --git a/libOTe/Tools/Pprf/PprfUtil.h b/libOTe/Tools/Pprf/PprfUtil.h index 4d294a1..a6fa45c 100644 --- a/libOTe/Tools/Pprf/PprfUtil.h +++ b/libOTe/Tools/Pprf/PprfUtil.h @@ -138,13 +138,13 @@ namespace osuCrypto // num of bytes they will take up. u64 numBytes = - depth * numTrees * sizeof(std::array) + // each internal level of the tree has two sums + depth * numTrees * sizeof(std::array) + // each internal level of the tree has two sums elementSize * numTrees * 2 + // we must program numTrees inactive F leaves elementSize * numTrees * 2 * programPuncturedPoint; // if we are programing the active lead, then we have numTrees more. // allocate the buffer and partition them. buff.resize(numBytes); - sums = span>((std::array*)buff.data(), depth * numTrees); + sums = span>((std::array*)buff.data(), depth * numTrees); leaf = span((u8*)(sums.data() + sums.size()), elementSize * numTrees * 2 + elementSize * numTrees * 2 * programPuncturedPoint @@ -188,76 +188,80 @@ namespace osuCrypto } - struct TreeAllocator + inline void allocateExpandTree( + u64 domainSize, + AlignedUnVector& alloc, + std::vector>>& levels, + bool reuseLevel = true) { - TreeAllocator() = default; - TreeAllocator(const TreeAllocator&) = delete; - TreeAllocator(TreeAllocator&&) = default; - - using ValueType = AlignedArray; - std::list> mTrees; - std::vector> mFreeTrees; - //std::mutex mMutex; - u64 mTreeSize = 0, mNumTrees = 0; + auto depth = log2ceil(domainSize); + levels.resize(depth + 1); - void reserve(u64 num, u64 size) + if (reuseLevel) { - //std::lock_guard lock(mMutex); - mTreeSize = size; - mNumTrees += num; - mTrees.clear(); - mFreeTrees.clear(); - mTrees.emplace_back(num * size); - auto iter = mTrees.back().data(); - for (u64 i = 0; i < num; ++i) + auto secondLast = roundUpTo((domainSize + 1) / 2,2); + auto size = roundUpTo((domainSize + secondLast),2); + + // we will allocate the last twoo levels of the tree. + // these levels will be used for the smaller levels as + // well. We will alternate between the two. + alloc.clear(); + alloc.resize(size * 8); + + std::array>, 2> buffs; + buffs[0] = { (AlignedArray*)alloc.data(), secondLast }; + buffs[1] = { (AlignedArray*)alloc.data() + secondLast , domainSize }; + + // give the last level the big buffer. + levels.back() = buffs[1].subspan(0, domainSize); + for (u64 i = levels.size() - 2, j = 0ull; i < levels.size(); --i, ++j) { - mFreeTrees.push_back(span(iter, size)); - assert((u64)mFreeTrees.back().data() % 32 == 0); - iter += size; + auto width = divCeil(domainSize, 1ull << (depth - i)); + assert( + levels[i + 1].size() == 2 * width || + levels[i + 1].size() == 2 * width - 1); + + if (width > 1) + width = roundUpTo(width, 2); + + // each level will be half the size of the next level. + // we alternate which buffer we use. + levels[i] = buffs[j % 2].subspan(0, width); } } - - span get() + else { - //std::lock_guard lock(mMutex); - if (mFreeTrees.size() == 0) + u64 totalSize = 0; + for (u64 i = 0; i < levels.size(); ++i) { - assert(mTreeSize); - mTrees.emplace_back(mTreeSize); - mFreeTrees.push_back(span(mTrees.back().data(), mTreeSize)); - assert((u64)mFreeTrees.back().data() % 32 == 0); - ++mNumTrees; + auto width = divCeil(domainSize, 1ull << (depth - i)); + totalSize += roundUpTo(width, 2); } - auto ret = mFreeTrees.back(); - mFreeTrees.pop_back(); - return ret; - } + alloc.clear(); + alloc.resize(totalSize * 8); + span> buff((AlignedArray*)alloc.data(), totalSize); - void clear() - { - mTrees = {}; - mFreeTrees = {}; - mTreeSize = 0; - mNumTrees = 0; - } - }; + levels.back() = buff.subspan(0, domainSize); + buff = buff.subspan(domainSize); + for (u64 i = levels.size() - 2, j = 0ull; i < levels.size(); --i, ++j) + { + // each level will be half the size of the next level. + auto width = divCeil(domainSize, 1ull << (depth - i)); + assert( + levels[i + 1].size() == 2 * width || + levels[i + 1].size() == 2 * width - 1); + if(width > 1) + width = roundUpTo(width, 2); - inline void allocateExpandTree( - TreeAllocator& alloc, - std::vector>>& levels) - { - span> tree = alloc.get(); - assert((u64)tree.data() % 32 == 0); - levels[0] = tree.subspan(0, 1); - auto rem = tree.subspan(2); - for (auto i = 1ull; i < levels.size(); ++i) - { - levels[i] = rem.subspan(0, levels[i - 1].size() * 2); - assert((u64)levels[i].data() % 32 == 0); - rem = rem.subspan(levels[i].size()); + levels[i] = buff.subspan(0, width); + buff = buff.subspan(levels[i].size()); + } } + + if (levels[0].size() != 1) + throw RTE_LOC; } diff --git a/libOTe/Tools/Pprf/RegularPprf.h b/libOTe/Tools/Pprf/RegularPprf.h index 9a6a1e0..4f7c286 100644 --- a/libOTe/Tools/Pprf/RegularPprf.h +++ b/libOTe/Tools/Pprf/RegularPprf.h @@ -27,15 +27,34 @@ namespace osuCrypto > class RegularPprfSender : public TimerAdapter { public: - u64 mDomain = 0, mDepth = 0, mPntCount = 0; + + // the number of leaves in a single tree. + u64 mDomain = 0; + + // the depth of each tree. + u64 mDepth = 0; + + // the number of trees, must be a multiple of 8. + u64 mPntCount = 0; + + // the values that should be programmed at the punctured points. std::vector mValue; + + // the base OTs that should be set. Matrix> mBaseOTs; + // if true, tree OT messages are eagerly sent in batches of 8. + // otherwise, the OT messages are sent in a single batch. + bool mEagerSend = true; + using VecF = typename CoeffCtx::template Vec; using VecG = typename CoeffCtx::template Vec; + // a function that can be used to output the result of the PPRF. std::function mOutputFn; + // an internal buffer that is used to expand the tree. + AlignedUnVector mTempBuffer; RegularPprfSender() = default; @@ -109,14 +128,28 @@ namespace osuCrypto buff = std::vector{}, encSums = span>{}, leafMsgs = span{}, - mTreeAlloc = pprf::TreeAllocator{} + encStepSize = u64{}, + leafStepSize = u64{}, + encOffset = u64{}, + leafOffset = u64{}, + min = u64{} ); - mTreeAlloc.reserve(numThreads, (1ull << mDepth) + 2); setTimePoint("SilentMultiPprfSender.reserve"); - levels.resize(mDepth); - pprf::allocateExpandTree(mTreeAlloc, levels); + pprf::allocateExpandTree(roundUpTo((mDomain + 1) / 2, 2), mTempBuffer, levels); + assert(levels.size() == mDepth); + + if (!mEagerSend) + { + // we need to allocate one large buffer that will store all OT messages. + pprf::allocateExpandBuffer( + mDepth - 1, mPntCount, programPuncturedPoint, buff, encSums, leafMsgs, ctx); + encStepSize = encSums.size() / mPntCount; + leafStepSize = leafMsgs.size() / mPntCount; + encOffset = 0; + leafOffset = 0; + } for (treeIndex = 0; treeIndex < mPntCount; treeIndex += 8) { @@ -136,14 +169,38 @@ namespace osuCrypto leafLevelPtr = &leafLevel; } - // allocate the send buffer and partition it. - pprf::allocateExpandBuffer( - mDepth - 1, std::min(8, mPntCount - treeIndex), programPuncturedPoint, buff, encSums, leafMsgs, ctx); + min = std::min(8, mPntCount - treeIndex); + if (mEagerSend) + { + // allocate a send buffer for the next 8 trees. + pprf::allocateExpandBuffer( + mDepth - 1, min, programPuncturedPoint, buff, encSums, leafMsgs, ctx); + encStepSize = encSums.size() / min; + leafStepSize = leafMsgs.size() / min; + encOffset = 0; + leafOffset = 0; + } // exapnd the tree - expandOne(seed, treeIndex, programPuncturedPoint, levels, *leafLevelPtr, leafIndex, encSums, leafMsgs, ctx); - - MC_AWAIT(chl.send(std::move(buff))); + expandOne( + seed, + treeIndex, + programPuncturedPoint, + levels, + *leafLevelPtr, + leafIndex, + encSums.subspan(encOffset, encStepSize * min), + leafMsgs.subspan(leafOffset, leafStepSize * min), + ctx); + + encOffset += encStepSize * min; + leafOffset += leafStepSize * min; + + if (mEagerSend) + { + // send the buffer for the current set of trees. + MC_AWAIT(chl.send(std::move(buff))); + } // if we aren't interleaved, we need to copy the // leaf layer to the output. @@ -152,9 +209,14 @@ namespace osuCrypto } + + if (!mEagerSend) + { + // send the buffer for all of the trees. + MC_AWAIT(chl.send(std::move(buff))); + } + mBaseOTs = {}; - //mTreeAlloc.del(tree); - mTreeAlloc.clear(); setTimePoint("SilentMultiPprfSender.de-alloc"); @@ -294,8 +356,8 @@ namespace osuCrypto // encrypt the sums and write them to the output. for (u64 j = 0; j < remTrees; ++j) { - (*encSumIter)[0] = sums[0][j] ^ mBaseOTs[treeIdx + j][mDepth - 1 - d][1]; - (*encSumIter)[1] = sums[1][j] ^ mBaseOTs[treeIdx + j][mDepth - 1 - d][0]; + (*encSumIter)[0] = sums[0][j] ^ mBaseOTs(treeIdx + j, mDepth - 1 - d)[1]; + (*encSumIter)[1] = sums[1][j] ^ mBaseOTs(treeIdx + j, mDepth - 1 - d)[0]; ++encSumIter; } } @@ -333,22 +395,29 @@ namespace osuCrypto { // The child that we will write in this iteration. - // Each parent is expanded into the left and right children - // using a different AES fixed-key. Therefore our OWF is: - // - // H(x) = (AES(k0, x) + x) || (AES(k1, x) + x); - // - // where each half defines one of the children. - gGgmAes.data()[keep].hashBlocks<8>(parent.data(), child.data()); - - ctx.fromBlock(*(outIter + 0), child.data()[0]); - ctx.fromBlock(*(outIter + 1), child.data()[1]); - ctx.fromBlock(*(outIter + 2), child.data()[2]); - ctx.fromBlock(*(outIter + 3), child.data()[3]); - ctx.fromBlock(*(outIter + 4), child.data()[4]); - ctx.fromBlock(*(outIter + 5), child.data()[5]); - ctx.fromBlock(*(outIter + 6), child.data()[6]); - ctx.fromBlock(*(outIter + 7), child.data()[7]); + if constexpr (std::is_same_v) + { + gGgmAes.data()[keep].hashBlocks<8>(parent.data(), outIter); + } + else + { + // Each parent is expanded into the left and right children + // using a different AES fixed-key. Therefore our OWF is: + // + // H(x) = (AES(k0, x) + x) || (AES(k1, x) + x); + // + // where each half defines one of the children. + gGgmAes.data()[keep].hashBlocks<8>(parent.data(), child.data()); + + ctx.fromBlock(*(outIter + 0), child.data()[0]); + ctx.fromBlock(*(outIter + 1), child.data()[1]); + ctx.fromBlock(*(outIter + 2), child.data()[2]); + ctx.fromBlock(*(outIter + 3), child.data()[3]); + ctx.fromBlock(*(outIter + 4), child.data()[4]); + ctx.fromBlock(*(outIter + 5), child.data()[5]); + ctx.fromBlock(*(outIter + 6), child.data()[6]); + ctx.fromBlock(*(outIter + 7), child.data()[7]); + } // leafSum += child auto& leafSum = leafSums[keep]; @@ -361,7 +430,7 @@ namespace osuCrypto ctx.plus(leafSum.data()[6], leafSum.data()[6], *(outIter + 6)); ctx.plus(leafSum.data()[7], leafSum.data()[7], *(outIter + 7)); - outIter+= 8; + outIter += 8; assert(outIter <= leafLevel.end()); } @@ -457,18 +526,35 @@ namespace osuCrypto class RegularPprfReceiver : public TimerAdapter { public: - u64 mDomain = 0, mDepth = 0, mPntCount = 0; + + // the number of leaves in a single tree. + u64 mDomain = 0; + + // the depth of each tree. + u64 mDepth = 0; + + // the number of trees, must be a multiple of 8. + u64 mPntCount = 0; + using VecF = typename CoeffCtx::template Vec; using VecG = typename CoeffCtx::template Vec; - //std::vector mPoints; - + // base ots that will be used to expand the tree. Matrix mBaseOTs; + // the choice bits, each row should be the bit decomposition of the active path. Matrix mBaseChoices; + // if true, tree OT messages are eagerly sent in batches of 8. + // otherwise, the OT messages are sent in a single batch. + bool mEagerSend = true; + + // a function that can be used to output the result of the PPRF. std::function mOutputFn; + // an internal buffer that is used to expand the tree. + AlignedUnVector mTempBuffer; + RegularPprfReceiver() = default; RegularPprfReceiver(const RegularPprfReceiver&) = delete; RegularPprfReceiver(RegularPprfReceiver&&) = delete; @@ -631,19 +717,36 @@ namespace osuCrypto buff = std::vector{}, encSums = span>{}, leafMsgs = span{}, - mTreeAlloc = pprf::TreeAllocator{}, - points = std::vector{} + points = std::vector{}, + encStepSize = u64{}, + leafStepSize = u64{}, + encOffset = u64{}, + leafOffset = u64{}, + min = u64{} ); setTimePoint("SilentMultiPprfReceiver.start"); points.resize(mPntCount); getPoints(points, PprfOutputFormat::ByLeafIndex); - mTreeAlloc.reserve(1, (1ull << mDepth) + 2); - setTimePoint("SilentMultiPprfSender.reserve"); + //setTimePoint("SilentMultiPprfSender.reserve"); + + pprf::allocateExpandTree(roundUpTo((mDomain + 1) / 2, 2), mTempBuffer, levels); + assert(levels.size() == mDepth); - levels.resize(mDepth); - pprf::allocateExpandTree(mTreeAlloc, levels); + + if (!mEagerSend) + { + // we need to allocate one large buffer that will store all OT messages. + pprf::allocateExpandBuffer( + mDepth - 1, mPntCount, programPuncturedPoint, buff, encSums, leafMsgs, ctx); + encStepSize = encSums.size() / mPntCount; + leafStepSize = leafMsgs.size() / mPntCount; + encOffset = 0; + leafOffset = 0; + + MC_AWAIT(chl.recv(buff)); + } for (treeIndex = 0; treeIndex < mPntCount; treeIndex += 8) { @@ -663,14 +766,34 @@ namespace osuCrypto leafLevelPtr = &leafLevel; } - // allocate the send buffer and partition it. - pprf::allocateExpandBuffer(mDepth - 1, std::min(8, mPntCount - treeIndex), - programPuncturedPoint, buff, encSums, leafMsgs, ctx); + min = std::min(8, mPntCount - treeIndex); + if (mEagerSend) + { - MC_AWAIT(chl.recv(buff)); + // allocate the send buffer and partition it. + pprf::allocateExpandBuffer(mDepth - 1, min, + programPuncturedPoint, buff, encSums, leafMsgs, ctx); + encStepSize = encSums.size() / min; + leafStepSize = leafMsgs.size() / min; + encOffset = 0; + leafOffset = 0; + MC_AWAIT(chl.recv(buff)); + } // exapnd the tree - expandOne(treeIndex, programPuncturedPoint, levels, *leafLevelPtr, leafIndex, encSums, leafMsgs, points, ctx); + expandOne( + treeIndex, + programPuncturedPoint, + levels, + *leafLevelPtr, + leafIndex, + encSums.subspan(encOffset, encStepSize * min), + leafMsgs.subspan(leafOffset, leafStepSize * min), + points, + ctx); + + encOffset += encStepSize * min; + leafOffset += leafStepSize * min; // if we aren't interleaved, we need to copy the // leaf layer to the output. @@ -681,8 +804,6 @@ namespace osuCrypto setTimePoint("SilentMultiPprfReceiver.join"); mBaseOTs = {}; - //mTreeAlloc.del(tree); - mTreeAlloc.clear(); setTimePoint("SilentMultiPprfReceiver.de-alloc"); @@ -776,9 +897,11 @@ namespace osuCrypto // The already constructed level. Only missing the // GGM tree node value along the active path. auto level0 = levels[d]; + assert(level0.size() == width || level0.size() == width + 1); // The next level that we want to construct. auto level1 = levels[d + 1]; + assert(level1.size() == width * 2); for (u64 parentIdx = 0, childIdx = 0; parentIdx < width; ++parentIdx, childIdx += 2) { @@ -869,7 +992,7 @@ namespace osuCrypto level1[siblingIdx][i] = (*theirSumsIter)[notAi] ^ mySums[notAi][i] ^ - mBaseOTs[i + treeIdx][mDepth - 1 - d]; + mBaseOTs(i + treeIdx, mDepth - 1 - d); ++theirSumsIter; @@ -914,23 +1037,29 @@ namespace osuCrypto for (u64 keep = 0; keep < 2; ++keep, ++childIdx) { - // Each parent is expanded into the left and right children - // using a different AES fixed-key. Therefore our OWF is: - // - // H(x) = (AES(k0, x) + x) || (AES(k1, x) + x); - // - // where each half defines one of the children. - gGgmAes.data()[keep].hashBlocks<8>(parent.data(), child.data()); - - ctx.fromBlock(*(outIter + 0), child.data()[0]); - ctx.fromBlock(*(outIter + 1), child.data()[1]); - ctx.fromBlock(*(outIter + 2), child.data()[2]); - ctx.fromBlock(*(outIter + 3), child.data()[3]); - ctx.fromBlock(*(outIter + 4), child.data()[4]); - ctx.fromBlock(*(outIter + 5), child.data()[5]); - ctx.fromBlock(*(outIter + 6), child.data()[6]); - ctx.fromBlock(*(outIter + 7), child.data()[7]); - + if constexpr (std::is_same_v) + { + gGgmAes.data()[keep].hashBlocks<8>(parent.data(), outIter); + } + else + { + // Each parent is expanded into the left and right children + // using a different AES fixed-key. Therefore our OWF is: + // + // H(x) = (AES(k0, x) + x) || (AES(k1, x) + x); + // + // where each half defines one of the children. + gGgmAes.data()[keep].hashBlocks<8>(parent.data(), child.data()); + + ctx.fromBlock(*(outIter + 0), child.data()[0]); + ctx.fromBlock(*(outIter + 1), child.data()[1]); + ctx.fromBlock(*(outIter + 2), child.data()[2]); + ctx.fromBlock(*(outIter + 3), child.data()[3]); + ctx.fromBlock(*(outIter + 4), child.data()[4]); + ctx.fromBlock(*(outIter + 5), child.data()[5]); + ctx.fromBlock(*(outIter + 6), child.data()[6]); + ctx.fromBlock(*(outIter + 7), child.data()[7]); + } auto& leafSum = leafSums[keep]; ctx.plus(leafSum.data()[0], leafSum.data()[0], *(outIter + 0)); ctx.plus(leafSum.data()[1], leafSum.data()[1], *(outIter + 1)); diff --git a/libOTe/Tools/TungstenCode/TungstenCode.h b/libOTe/Tools/TungstenCode/TungstenCode.h index 1e91d63..6682988 100644 --- a/libOTe/Tools/TungstenCode/TungstenCode.h +++ b/libOTe/Tools/TungstenCode/TungstenCode.h @@ -44,7 +44,7 @@ namespace osuCrypto { for (u64 i = 0; i < n; ++i) { auto j = prng.get() % (n - i) + i; - std::swap(mPerm[i], mPerm[j]); + std::swap(mPerm.data()[i], mPerm.data()[j]); } reset(); } @@ -155,16 +155,18 @@ namespace osuCrypto { template< typename F, typename CoeffCtx, - typename Iter + typename Iter, + typename VecF > - void dualEncode(Iter&& e, CoeffCtx ctx) + void dualEncode(Iter&& e, CoeffCtx ctx, VecF& temp) { if (mCodeSize == 0) throw RTE_LOC; - using VecF = typename CoeffCtx::template Vec; + //using VecF = typename CoeffCtx::template Vec; - VecF temp(mCodeSize - mMessageSize); + + ctx.resize(temp, mCodeSize - mMessageSize); if (temp.size() / ChunkSize != mPerm.mPerm.size()) throw RTE_LOC; @@ -200,6 +202,21 @@ namespace osuCrypto { ctx); } + + template< + typename F, + typename CoeffCtx, + typename Iter + > + void dualEncode(Iter&& e, CoeffCtx ctx) + { + if (mCodeSize == 0) + throw RTE_LOC; + using VecF = typename CoeffCtx::template Vec; + VecF temp; + dualEncode(std::forward(e), ctx, temp); + } + template< typename Table, typename F, @@ -299,94 +316,6 @@ namespace osuCrypto { break; } } - // - // - // template< - // typename Table, - // typename F, - // bool rangeCheck, - // typename OutputMap, - // typename CoeffCtx, - // typename Iter - // > - // void accumulateBlockGather( - // Iter x, - // u64 i, - // Iter dst, - // u64 size, - // OutputMap& output, - // CoeffCtx& ctx) - // { - // - // //static constexpr int chunkSize = OutputMap::chunkSize; - // static_assert(Table::data.size() % ChunkSize == 0); - // auto table = Table::data.data(); - // - // for (u64 j = 0; j < Table::data.size();) - // { - //#ifdef ENABLE_SSE - // if (rangeCheck == false || i + Table::data.size() * 2 < size) - // _mm_prefetch((char*)(x + i + Table::data.size() * 2), _MM_HINT_T0); - //#endif - // - // for (u64 k = 0; k < ChunkSize; ++k, ++j, ++i) - // { - // - // if constexpr (Table::data[0].size() == 4) - // { - // if constexpr (rangeCheck) - // { - // if (i == size) - // return; - // - // auto xi = x + i; - // auto xs = x + ((i + Table::max + 1) % size); - // ctx.plus(*xs, *xs, *xi); - // ctx.mulConst(*xs, *xs); - // - // for (u64 p = 0; p < Table::data[0].size(); ++p) - // { - // auto idx = (i + table[j].data()[p]) % size; - // if (idx != i) - // { - // auto xi = x + i; - // auto xp = x + idx; - // ctx.plus(*xp, *xp, *xi); - // } - // } - // } - // else - // { - // auto xi = x + i; - // - // auto xs = xi + Table::max + 1; - // auto x0 = xi + table[j].data()[0]; - // auto x1 = xi + table[j].data()[1]; - // auto x2 = xi + table[j].data()[2]; - // auto x3 = xi + table[j].data()[3]; - // - // ctx.plus(*xs, *xs, *xi); - // ctx.plus(*x0, *x0, *xi); - // ctx.plus(*x1, *x1, *xi); - // ctx.plus(*x2, *x2, *xi); - // ctx.plus(*x3, *x3, *xi); - // ctx.mulConst(*xs, *xs); - // - // } - // } - // else - // { - // throw RTE_LOC; - // } - // } - // - // output.template applyChunk(dst, x + (i - ChunkSize), ctx); - // - // if (rangeCheck && i >= size) - // break; - // } - // } - template(mA.begin(), {}); + encoder.dualEncode(mA.begin(), {}, mEncodeTemp); break; } default: @@ -735,7 +733,7 @@ namespace osuCrypto { experimental::TungstenCode encoder; encoder.config(roundUpTo(mRequestNumOts, 8), mNoiseVecSize); - encoder.dualEncode(mA.begin(), {}); + encoder.dualEncode(mA.begin(), {}, mEncodeTemp); encoder.dualEncode(mC.begin(), {}); break; } diff --git a/libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.h b/libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.h index a4c50a4..231a148 100644 --- a/libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.h +++ b/libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.h @@ -91,6 +91,9 @@ namespace osuCrypto // The flag which controls whether the malicious check is performed. SilentSecType mMalType = SilentSecType::SemiHonest; + // An temporary buffer used during LPN encoding. + AlignedUnVector mEncodeTemp; + // A flag that helps debug bool mDebug = false; diff --git a/libOTe/TwoChooseOne/Silent/SilentOtExtSender.cpp b/libOTe/TwoChooseOne/Silent/SilentOtExtSender.cpp index 4cceac7..7aacebc 100644 --- a/libOTe/TwoChooseOne/Silent/SilentOtExtSender.cpp +++ b/libOTe/TwoChooseOne/Silent/SilentOtExtSender.cpp @@ -192,6 +192,7 @@ namespace osuCrypto mNumPartitions = 0; mB = {}; + mEncodeTemp = {}; mDelta = block(0,0); @@ -485,7 +486,8 @@ namespace osuCrypto { experimental::TungstenCode encoder; encoder.config(oc::roundUpTo(mRequestNumOts, 8), mNoiseVecSize); - encoder.dualEncode(mB.begin(), {}); + + encoder.dualEncode(mB.begin(), {}, mEncodeTemp); break; } default: diff --git a/libOTe/TwoChooseOne/Silent/SilentOtExtSender.h b/libOTe/TwoChooseOne/Silent/SilentOtExtSender.h index 1a61d2d..39e38be 100644 --- a/libOTe/TwoChooseOne/Silent/SilentOtExtSender.h +++ b/libOTe/TwoChooseOne/Silent/SilentOtExtSender.h @@ -114,6 +114,9 @@ namespace osuCrypto // secret share of xa * delta as described in ferret. std::vector> mMalCheckOts; + // An temporary buffer used during LPN encoding. + AlignedUnVector mEncodeTemp; + // A flag that helps debug bool mDebug = false; diff --git a/libOTe_Tests/Pprf_Tests.cpp b/libOTe_Tests/Pprf_Tests.cpp index 68eaf4e..7b310d5 100644 --- a/libOTe_Tests/Pprf_Tests.cpp +++ b/libOTe_Tests/Pprf_Tests.cpp @@ -51,16 +51,16 @@ void Tools_Pprf_expandOne_test_impl(u64 domain, bool program) auto sSums = span>{}; auto sLast = span{}; - pprf::TreeAllocator mTreeAlloc; + //pprf::TreeAllocator mTreeAlloc; sLevels.resize(depth); rLevels.resize(depth); - mTreeAlloc.reserve(2, (1ull << depth) + 2); + //mTreeAlloc.reserve(2, (1ull << depth) + 2); + AlignedUnVector sTree, rTree; - - pprf::allocateExpandTree(mTreeAlloc, sLevels); - pprf::allocateExpandTree(mTreeAlloc, rLevels); + pprf::allocateExpandTree(domain, sTree, sLevels, false); + pprf::allocateExpandTree(domain, rTree, rLevels, false); using VecF = typename Ctx::template Vec; VecF sLeafLevel(8ull * domain); VecF rLeafLevel(8ull * domain); @@ -173,6 +173,7 @@ void Tools_Pprf_test_impl( u64 numPoints, bool program, PprfOutputFormat format, + bool eagerSend, bool verbose) { @@ -226,6 +227,8 @@ void Tools_Pprf_test_impl( std::vector points(numPoints); recver.getPoints(points, format); + sender.mEagerSend = eagerSend; + recver.mEagerSend = eagerSend; // a = b + points * delta auto p0 = sender.expand(sockets[0], delta, prng.get(), b, format, program, threads); @@ -388,10 +391,10 @@ void Tools_Pprf_inter_test(const CLP& cmd) { auto f = PprfOutputFormat::Interleaved; auto v = cmd.isSet("v"); - for (auto d : { 32,3242 }) for (auto n : { 8, 128 }) for (auto p : { true, false }) + for (auto d : { 32,3242 }) for (auto n : { 8, 128 }) for (auto p : { true, false }) for (auto e : { true, false }) { - Tools_Pprf_test_impl(d, n, p, f, v); - Tools_Pprf_test_impl(d, n, p, f, v); + Tools_Pprf_test_impl(d, n, p, f, e, v); + Tools_Pprf_test_impl(d, n, p, f, e, v); } } @@ -403,10 +406,10 @@ void Tools_Pprf_ByLeafIndex_test(const CLP& cmd) auto f = PprfOutputFormat::ByLeafIndex; auto v = cmd.isSet("v"); - for (auto d : { 32,3242 }) for (auto n : { 8, 128 }) for (auto p : { true/*, false */}) + for (auto d : { 32,3242 }) for (auto n : { 8, 128 }) for (auto p : { true/*, false */}) for (auto e : { true/*, false */}) { - Tools_Pprf_test_impl(d, n, p, f, v); - Tools_Pprf_test_impl(d, n, p, f, v); + Tools_Pprf_test_impl(d, n, p, f, e, v); + Tools_Pprf_test_impl(d, n, p, f, e, v); } #else throw UnitTestSkipped("ENABLE_SILENTOT not defined."); @@ -424,8 +427,8 @@ void Tools_Pprf_ByTreeIndex_test(const oc::CLP& cmd) auto v = cmd.isSet("v"); for (auto d : { 32,3242 }) for (auto n : { 8, 19}) for (auto p : { true/*, false*/ }) { - Tools_Pprf_test_impl(d, n, p, f, v); - Tools_Pprf_test_impl(d, n, p, f, v); + Tools_Pprf_test_impl(d, n, p, f, false, v); + Tools_Pprf_test_impl(d, n, p, f, false, v); } #else @@ -443,8 +446,8 @@ void Tools_Pprf_callback_test(const oc::CLP& cmd) auto v = cmd.isSet("v"); for (auto d : { 32,3242 }) for (auto n : { 8, 128 }) for (auto p : { true/*, false */}) { - Tools_Pprf_test_impl(d, n, p, f, v); - Tools_Pprf_test_impl(d, n, p, f, v); + Tools_Pprf_test_impl(d, n, p, f, false, v); + Tools_Pprf_test_impl(d, n, p, f, false, v); } #else throw UnitTestSkipped("ENABLE_SILENTOT not defined.");