diff --git a/CMakeLists.txt b/CMakeLists.txt index 87e0508..aba96a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ if (POLICY CMP0048) cmake_policy(SET CMP0048 NEW) endif (POLICY CMP0048) -project(libOTe VERSION 2.1.0) +project(libOTe VERSION 2.2.0) include(cmake/libOTePreamble.cmake) diff --git a/CMakePresets.json b/CMakePresets.json index 6fe2021..e0f1069 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -52,17 +52,22 @@ "ENABLE_PPRF": true, "ENABLE_SILENT_VOLE": true, "LIBOTE_STD_VER": "17", + "ENABLE_ALL_OT": true, + "ENABLE_KKRT": "ON", + "ENABLE_IKNP": "ON", + "ENABLE_MR": "ON", + "ENABLE_SIMPLESTOT": "ON", + "ENABLE_GMP": false, "ENABLE_RELIC": false, "ENABLE_SODIUM": true, - "ENABLE_BOOST": true, - "ENABLE_BITPOLYMUL": false, + "ENABLE_BOOST": false, + "ENABLE_BITPOLYMUL": true, "FETCH_AUTO": "ON", "ENABLE_CIRCUITS": true, "VERBOSE_FETCH": true, "ENABLE_SSE": true, "ENABLE_AVX": true, "ENABLE_ASAN": false, - "COPROTO_ENABLE_BOOST": true, "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}", "CMAKE_PREFIX_PATH": "${sourceDir}/../out/install/${presetName}" }, @@ -87,10 +92,11 @@ "cacheVariables": { "CMAKE_BUILD_TYPE": "RelWithDebInfo", "LIBOTE_STD_VER": "17", + "ENABLE_GMP": false, "ENABLE_ALL_OT": true, - "ENABLE_RELIC": true, - "ENABLE_SODIUM": false, - "ENABLE_BOOST": true, + "ENABLE_RELIC": false, + "ENABLE_SODIUM": true, + "ENABLE_BOOST": false, "ENABLE_OPENSSL": false, "FETCH_AUTO": true, "ENABLE_CIRCUITS": true, diff --git a/README.md b/README.md index fe220bd..8da6cc8 100644 --- a/README.md +++ b/README.md @@ -7,22 +7,24 @@ A fast and portable C++17 library for Oblivious Transfer extension (OTe). The primary design goal of this library to obtain *high performance* while being *easy to use*. Checkout [version 1.6](https://github.com/osu-crypto/libOTe/releases/tag/v1.6.0) for the previous version. -This library currently implements: -* The semi-honest 1-out-of-2 OT [[IKNP03]](https://www.iacr.org/archive/crypto2003/27290145/27290145.pdf). -* The semi-honest 1-out-of-2 Silent OT [[BCGIKRS19]](https://eprint.iacr.org/2019/1159.pdf). -* The semi-honest 1-out-of-2 Delta-OT [[IKNP03]](https://www.iacr.org/archive/crypto2003/27290145/27290145.pdf),[[BLNNOOSS15]](https://eprint.iacr.org/2015/472.pdf). -* The semi-honest 1-out-of-2 OT [[Roy22]](https://eprint.iacr.org/2022/192). -* The semi-honest 1-out-of-N OT [[KKRT16]](https://eprint.iacr.org/2016/799). -* The malicious secure 1-out-of-2 Silent+Expand Convolute [[RRT23]](https://eprint.iacr.org/2023/882). -* The malicious secure 1-out-of-2 OT [[KOS15]](https://eprint.iacr.org/2015/546). -* The malicious secure 1-out-of-2 Delta-OT [[KOS15]](https://eprint.iacr.org/2015/546),[[BLNNOOSS15]](https://eprint.iacr.org/2015/472.pdf). -* The malicious 1-out-of-2 OT [[Roy22]](https://eprint.iacr.org/2022/192). -* The malicious secure 1-out-of-N OT [[OOS16]](http://eprint.iacr.org/2016/933). -* The malicious secure 1-out-of-2 base OT [NP01]. -* The malicious secure 1-out-of-2 base OT [[CO15]](https://eprint.iacr.org/2015/267.pdf) (Faster Linux ASM version disabled by default). -* The malicious secure 1-out-of-2 base OT [[MR19]](https://eprint.iacr.org/2019/706.pdf) -* Several malicious secure batched 1-out-of-2 base OTs from [[MRR21]](https://eprint.iacr.org/2021/682) +Semi-honest OT extension: +* 1-out-of-2 Silent OT [[BCGIKRS19]](https://eprint.iacr.org/2019/1159.pdf),[[RRT23]](https://eprint.iacr.org/2023/882). +* 1-out-of-2 OT [[IKNP03]](https://www.iacr.org/archive/crypto2003/27290145/27290145.pdf). +* 1-out-of-2 Correlated-OT [[IKNP03]](https://www.iacr.org/archive/crypto2003/27290145/27290145.pdf),[[BLNNOOSS15]](https://eprint.iacr.org/2015/472.pdf). +* 1-out-of-2 OT [[Roy22]](https://eprint.iacr.org/2022/192). +* 1-out-of-N OT [[KKRT16]](https://eprint.iacr.org/2016/799). + +Malicious OT extension: +* 1-out-of-2 Silent OT [[BCGIKRS19]](https://eprint.iacr.org/2019/1159.pdf),[[RRT23]](https://eprint.iacr.org/2023/882). +* 1-out-of-2 OT [[KOS15]](https://eprint.iacr.org/2015/546). +* 1-out-of-2 Correlated-OT [[KOS15]](https://eprint.iacr.org/2015/546). +* 1-out-of-2 OT [[Roy22]](https://eprint.iacr.org/2022/192). +* 1-out-of-2 base OT, several protocols. + +Vole: +* Generic subfield noisy VOLE (semi-honest) [[BCGIKRS19]](https://eprint.iacr.org/2019/1159.pdf) +* Generic subfield silent VOLE (malicious/semi-honest) [[BCGIKRS19]](https://eprint.iacr.org/2019/1159.pdf),[[RRT23]](https://eprint.iacr.org/2023/882). ## Introduction @@ -73,10 +75,10 @@ LibOTe can be built with various only the selected protocols enabled. `-D ENABLE * `ENABLE_KOS` the Keller et al [[KOS15]](https://eprint.iacr.org/2015/546) malicious protocol. * `ENABLE_DELTA_KOS` the Burra et al [[BLNNOOSS15]](https://eprint.iacr.org/2015/472.pdf),[[KOS15]](https://eprint.iacr.org/2015/546) malicious Delta-OT protocol. * `ENABLE_SOFTSPOKEN_OT` the Roy [Roy22](https://eprint.iacr.org/2022/192) semi-honest/malicious protocol. - * `ENABLE_SILENTOT` the Couteau et al [RRT23],[[BCGIKRS19]](https://eprint.iacr.org/2019/1159.pdf) semi-honest/malicious protocol. + * `ENABLE_SILENTOT` the [[BCGIKRS19]](https://eprint.iacr.org/2019/1159.pdf),[[RRT23]](https://eprint.iacr.org/2023/882) semi-honest/malicious protocol. **Vole:** - * `ENABLE_SILENT_VOLE` the Couteau et al [CRR21] semi-honest/malicious protocol. + * `ENABLE_SILENT_VOLE` the [[BCGIKRS19]](https://eprint.iacr.org/2019/1159.pdf),[[RRT23]](https://eprint.iacr.org/2023/882) semi-honest/malicious protocol. Addition options can be set for cryptoTools. See the cmake output. diff --git a/frontend/CMakeLists.txt b/frontend/CMakeLists.txt index 57d5257..01e9716 100644 --- a/frontend/CMakeLists.txt +++ b/frontend/CMakeLists.txt @@ -15,6 +15,8 @@ target_link_libraries(frontend_libOTe libOTe_Tests tests_cryptoTools) if(MSVC) target_compile_options(frontend_libOTe PRIVATE $<$:/std:c++${LIBOTE_STD_VER}>) + + target_compile_options(frontend_libOTe PRIVATE "/bigobj") else() target_compile_options(frontend_libOTe PRIVATE $<$:-std=c++${LIBOTE_STD_VER}>) endif() \ No newline at end of file diff --git a/frontend/ExampleMessagePassing.h b/frontend/ExampleMessagePassing.h index 71f2bb6..142a239 100644 --- a/frontend/ExampleMessagePassing.h +++ b/frontend/ExampleMessagePassing.h @@ -4,205 +4,209 @@ #include "libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.h" #include "libOTe/TwoChooseOne/Silent/SilentOtExtSender.h" -// This example demonstates how one can get and manually send the protocol messages -// that are generated. This communicate method is one possible way of doing this. -// It takes a protocol that has been started and coproto buffering socket as input. -// It alternates between "sending" and "receiving" protocol messages. Instead of -// sending the messages on a socket, this program writes them to a file and the other -// party reads that file to get the message. In a real program the communication could -// handled in any way the user decides. -auto communicate( - macoro::eager_task<>& protocol, - bool sender, - coproto::BufferingSocket& sock, - bool verbose) +namespace osuCrypto { - int s = 0, r = 0; - std::string me = sender ? "sender" : "recver"; - std::string them = !sender ? "sender" : "recver"; - - // write any outgoing data to a file me_i.bin where i in the message index. - auto write = [&]() + // This example demonstates how one can get and manually send the protocol messages + // that are generated. This communicate method is one possible way of doing this. + // It takes a protocol that has been started and coproto buffering socket as input. + // It alternates between "sending" and "receiving" protocol messages. Instead of + // sending the messages on a socket, this program writes them to a file and the other + // party reads that file to get the message. In a real program the communication could + // handled in any way the user decides. + auto communicate( + macoro::eager_task<>& protocol, + bool sender, + coproto::BufferingSocket& sock, + bool verbose) { - // the the outbound messages that the protocol has generated. - // This will consist of all the outbound messages that can be - // generated without receiving the next inbound message. - auto b = sock.getOutbound(); - // If we do have outbound messages, then lets write them to a file. - if (b && b->size()) - { - std::ofstream message; - auto temp = me + ".tmp"; - auto file = me + "_" + std::to_string(s) + ".bin"; - message.open(temp, std::ios::binary | std::ios::trunc); - message.write((char*)b->data(), b->size()); - message.close(); + int s = 0, r = 0; + std::string me = sender ? "sender" : "recver"; + std::string them = !sender ? "sender" : "recver"; - if (verbose) + // write any outgoing data to a file me_i.bin where i in the message index. + auto write = [&]() { - // optional for debug purposes. - oc::RandomOracle hash(16); - hash.Update(b->data(), b->size()); - oc::block h; hash.Final(h); - - std::cout << me << " write " << std::to_string(s) << " " << h << "\n"; + // the the outbound messages that the protocol has generated. + // This will consist of all the outbound messages that can be + // generated without receiving the next inbound message. + auto b = sock.getOutbound(); + + // If we do have outbound messages, then lets write them to a file. + if (b && b->size()) + { + std::ofstream message; + auto temp = me + ".tmp"; + auto file = me + "_" + std::to_string(s) + ".bin"; + message.open(temp, std::ios::binary | std::ios::trunc); + message.write((char*)b->data(), b->size()); + message.close(); + + if (verbose) + { + // optional for debug purposes. + RandomOracle hash(16); + hash.Update(b->data(), b->size()); + block h; hash.Final(h); + + std::cout << me << " write " << std::to_string(s) << " " << h << "\n"; + } + + if (rename(temp.c_str(), file.c_str()) != 0) + std::cout << me << " file renamed failed\n"; + else if (verbose) + std::cout << me << " file renamed successfully\n"; + + ++s; + } + + }; + + // write incoming data from a file them_i.bin where i in the message index. + auto read = [&]() { + + std::ifstream message; + auto file = them + "_" + std::to_string(r) + ".bin"; + while (message.is_open() == false) + { + message.open(file, std::ios::binary); + if ((message.is_open() == false)) + std::this_thread::sleep_for(std::chrono::milliseconds(100)); } - if (rename(temp.c_str(), file.c_str()) != 0) - std::cout << me << " file renamed failed\n"; - else if (verbose) - std::cout << me << " file renamed successfully\n"; - - ++s; - } + auto fsize = message.tellg(); + message.seekg(0, std::ios::end); + fsize = message.tellg() - fsize; + message.seekg(0, std::ios::beg); + std::vector buff(fsize); + message.read((char*)buff.data(), fsize); + message.close(); + std::remove(file.c_str()); - }; + if (verbose) + { + RandomOracle hash(16); + hash.Update(buff.data(), buff.size()); + block h; hash.Final(h); - // write incoming data from a file them_i.bin where i in the message index. - auto read = [&]() { + std::cout << me << " read " << std::to_string(r) << " " << h << "\n"; + } + ++r; - std::ifstream message; - auto file = them + "_" + std::to_string(r) + ".bin"; - while (message.is_open() == false) - { - message.open(file, std::ios::binary); - if ((message.is_open() == false)) - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - } + // This gives this socket the message which forwards it to the protocol and + // run the protocol forward, possibly generating more outbound protocol + // messages. + sock.processInbound(buff); + }; - auto fsize = message.tellg(); - message.seekg(0, std::ios::end); - fsize = message.tellg() - fsize; - message.seekg(0, std::ios::beg); - std::vector buff(fsize); - message.read((char*)buff.data(), fsize); - message.close(); - std::remove(file.c_str()); + // The sender we generate the first message. + if (!sender) + write(); - if (verbose) + // While the protocol is not done we alternate between reading and writing messages. + while (protocol.is_ready() == false) { - oc::RandomOracle hash(16); - hash.Update(buff.data(), buff.size()); - oc::block h; hash.Final(h); - - std::cout << me << " read " << std::to_string(r) << " " << h << "\n"; + read(); + write(); } - ++r; - - // This gives this socket the message which forwards it to the protocol and - // run the protocol forward, possibly generating more outbound protocol - // messages. - sock.processInbound(buff); - }; - - // The sender we generate the first message. - if (!sender) - write(); - - // While the protocol is not done we alternate between reading and writing messages. - while (protocol.is_ready() == false) - { - read(); - write(); } -} -void messagePassingExampleRun(oc::CLP& cmd) -{ + void messagePassingExampleRun(CLP& cmd) + { #ifdef ENABLE_SILENTOT - auto isReceiver = cmd.get("r"); + auto isReceiver = cmd.get("r"); - // The number of OTs. - auto n = cmd.getOr("n", 100); + // The number of OTs. + auto n = cmd.getOr("n", 100); - auto verbose = cmd.isSet("v"); + auto verbose = cmd.isSet("v"); - // A buffering socket. This socket type internally buffers the - // protocol messages. It is then up to the user to manually send - // and receive messages via the getOutbond(...) and processInbount(...) - // methods. - coproto::BufferingSocket sock; + // A buffering socket. This socket type internally buffers the + // protocol messages. It is then up to the user to manually send + // and receive messages via the getOutbond(...) and processInbount(...) + // methods. + coproto::BufferingSocket sock; - // randomness source - PRNG prng(oc::sysRandomSeed()); + // randomness source + PRNG prng(sysRandomSeed()); - // Sets are always represented as 16 byte values. To support longer elements one can hash them. - if (!isReceiver) - { - oc::SilentOtExtSender sender; + // Sets are always represented as 16 byte values. To support longer elements one can hash them. + if (!isReceiver) + { + SilentOtExtSender sender; - std::vector> senderOutput(n); + std::vector> senderOutput(n); - if (verbose) - std::cout << "sender start\n"; + if (verbose) + std::cout << "sender start\n"; - // Eagerly start the protocol. This will run the protocol up to the point - // that it need to receive a message from the other party. - auto protocol = - sender.silentSend(senderOutput, prng, sock) - | macoro::make_eager(); + // Eagerly start the protocol. This will run the protocol up to the point + // that it need to receive a message from the other party. + auto protocol = + sender.silentSend(senderOutput, prng, sock) + | macoro::make_eager(); - // Perform the communication and complete the protocol. - communicate(protocol, true, sock, verbose); + // Perform the communication and complete the protocol. + communicate(protocol, true, sock, verbose); - std::cout << "sender done\n"; + std::cout << "sender done\n"; - for (u64 i = 0; i < std::min(10, n); ++i) - std::cout << "sender.msg[" << i << "] = { " << senderOutput[i][0] << ", " << senderOutput[i][1] << "}" << std::endl; - if (n > 10) - std::cout << "..." << std::endl; - } - else - { - std::vector receiverOutputMsg(n); - oc::BitVector receiverOutputBits(n); + for (u64 i = 0; i < std::min(10, n); ++i) + std::cout << "sender.msg[" << i << "] = { " << senderOutput[i][0] << ", " << senderOutput[i][1] << "}" << std::endl; + if (n > 10) + std::cout << "..." << std::endl; + } + else + { + std::vector receiverOutputMsg(n); + BitVector receiverOutputBits(n); - oc::SilentOtExtReceiver receiver; + SilentOtExtReceiver receiver; - if (verbose) - std::cout << "recver start\n"; + if (verbose) + std::cout << "recver start\n"; - // Eagerly start the protocol. This will run the protocol up to the point - // that it need to receive a message from the other party. - auto protocol = - receiver.silentReceive(receiverOutputBits, receiverOutputMsg, prng, sock) - | macoro::make_eager(); + // Eagerly start the protocol. This will run the protocol up to the point + // that it need to receive a message from the other party. + auto protocol = + receiver.silentReceive(receiverOutputBits, receiverOutputMsg, prng, sock) + | macoro::make_eager(); - // Perform the communication and complete the protocol. - communicate(protocol, false, sock, verbose); + // Perform the communication and complete the protocol. + communicate(protocol, false, sock, verbose); - std::cout << "recver done\n"; + std::cout << "recver done\n"; - for (u64 i = 0; i < std::min(10, n); ++i) - std::cout << "receiver.msg[" << i << "] = " << receiverOutputMsg[i] << " = sender.msg["< 10) - std::cout << "..." << std::endl; - } + for (u64 i = 0; i < std::min(10, n); ++i) + std::cout << "receiver.msg[" << i << "] = " << receiverOutputMsg[i] << " = sender.msg[" << i << "][" << receiverOutputBits[i] << "]" << std::endl; + if (n > 10) + std::cout << "..." << std::endl; + } #else - std::cout << "ENABLE_SILENTOT is not defined. Rebuilt with -DENABLE_SILENTOT=true" << std::endl; + std::cout << "ENABLE_SILENTOT is not defined. Rebuilt with -DENABLE_SILENTOT=true" << std::endl; #endif -} + } -void messagePassingExample(oc::CLP& cmd) -{ - // If the user specified -r, then run that party. - // Otherwise run both parties. - if (cmd.hasValue("r")) - { - messagePassingExampleRun(cmd); - } - else + void messagePassingExample(CLP& cmd) { - auto s = cmd; - s.setDefault("r", 0); - cmd.setDefault("r", 1); - auto a = std::async([&]() {messagePassingExampleRun(s); }); - messagePassingExampleRun(cmd); - a.get(); + // If the user specified -r, then run that party. + // Otherwise run both parties. + if (cmd.hasValue("r")) + { + messagePassingExampleRun(cmd); + } + else + { + auto s = cmd; + s.setDefault("r", 0); + cmd.setDefault("r", 1); + auto a = std::async([&]() {messagePassingExampleRun(s); }); + messagePassingExampleRun(cmd); + a.get(); + } } -} +} \ No newline at end of file diff --git a/frontend/benchmark.h b/frontend/benchmark.h index 25043f5..111a45c 100644 --- a/frontend/benchmark.h +++ b/frontend/benchmark.h @@ -13,6 +13,7 @@ #include "libOTe/Vole/Silent/SilentVoleSender.h" #include "libOTe/Vole/Silent/SilentVoleReceiver.h" #include "libOTe/Tools/CoeffCtx.h" +#include "libOTe/Tools/TungstenCode/TungstenCode.h" namespace osuCrypto { @@ -172,6 +173,55 @@ namespace osuCrypto std::cout << verbose << std::endl; } + + inline void TungstenCodeBench(CLP& cmd) + { + u64 trials = cmd.getOr("t", 10); + + // the message length of the code. + // The noise vector will have size n=2*k. + // the user can use + // -k X + // to state that exactly X rows should be used or + // -kk X + // to state that 2^X rows should be used. + u64 k = cmd.getOr("k", 1ull << cmd.getOr("kk", 10)); + + u64 n = cmd.getOr("n", k * cmd.getOr("R", 2.0)); + + // verbose flag. + bool v = cmd.isSet("v"); + + experimental::TungstenCode code; + code.config(k, n); + code.mNumIter = cmd.getOr("iter", 2); + + if (v) + { + std::cout << "n: " << code.mCodeSize << std::endl; + std::cout << "k: " << code.mMessageSize << std::endl; + } + + std::vector x(code.mCodeSize); + Timer timer, verbose; + + + timer.setTimePoint("_____________________"); + for (u64 i = 0; i < trials; ++i) + { + code.dualEncode(x.data(), {}); + + timer.setTimePoint("encode"); + } + + std::cout << "tungsten " << std::endl; + std::cout << timer << std::endl; + + if (v) + std::cout << verbose << std::endl; + } + + inline void transpose(const CLP& cmd) { #ifdef ENABLE_AVX diff --git a/frontend/main.cpp b/frontend/main.cpp index f98584f..af204dd 100644 --- a/frontend/main.cpp +++ b/frontend/main.cpp @@ -1,12 +1,9 @@ #include - -//using namespace std; #include "tests_cryptoTools/UnitTests.h" #include "libOTe_Tests/UnitTests.h" #include #include "cryptoTools/Crypto/RandomOracle.h" -using namespace osuCrypto; #include #include @@ -32,9 +29,8 @@ using namespace osuCrypto; #include "libOTe/TwoChooseOne/Iknp/IknpOtExtSender.h" #include "libOTe/TwoChooseOne/Iknp/IknpOtExtReceiver.h" +using namespace osuCrypto; #ifdef ENABLE_IKNP -using namespace oc; - void minimal() { // Setup networking. See cryptoTools\frontend_cryptoTools\Tutorials\Network.cpp @@ -82,11 +78,11 @@ void minimal() #endif -#include "cryptoTools/Crypto/RandomOracle.h" int main(int argc, char** argv) { CLP cmd; cmd.parse(argc, argv); + bool flagSet = false; // various benchmarks @@ -100,8 +96,11 @@ int main(int argc, char** argv) VoleBench2(cmd); else if (cmd.isSet("ea")) EACodeBench(cmd); - else + else if (cmd.isSet("ec")) ExConvCodeBench(cmd); + else if (cmd.isSet("tungsten")) + TungstenCodeBench(cmd); + return 0; } diff --git a/libOTe/Tools/ExConvCode/Util.h b/libOTe/Tools/ExConvCode/Util.h new file mode 100644 index 0000000..f637dc6 --- /dev/null +++ b/libOTe/Tools/ExConvCode/Util.h @@ -0,0 +1,224 @@ +#include "cryptoTools/Crypto/PRNG.h" +#include +#ifdef ENABLE_AVX +#define LIBDIVIDE_AVX2 +#elif ENABLE_SSE +#define LIBDIVIDE_SSE2 +#endif +#include "libdivide.h" +namespace osuCrypto +{ + namespace detail + { + + + struct ExConvModd + { + using value_type = u64; + PRNG prng; + u64 modVal, idx; + AlignedUnVector vals; + libdivide::libdivide_u64_t mod; + bool mIsPow2; + std::vector mPow2Vals; + u64 mPow2; + value_type mPow2Mask; + block mPow2MaskBlk; + + //static const auto numIdx = + + ExConvModd(block seed, u64 m) + : prng(seed, 256) + , modVal(m) + , mod(libdivide::libdivide_u64_gen(m)) + { + mPow2 = log2ceil(modVal); + mIsPow2 = mPow2 == log2floor(modVal); + //mIsPow2 = false; + if (mIsPow2) + { + mPow2Mask = modVal - 1; + //mPow2MaskBlk = std::array{ mPow2Mask, mPow2Mask, mPow2Mask, mPow2Mask }; + mPow2MaskBlk = std::array{ mPow2Mask, mPow2Mask}; + //mPow2Step = divCeil(mPow2, 8); + //mPow2Vals.resize(prng.mBufferByteCapacity / mPow2Step); + //vals = mPow2Vals; + } + else + { + //throw RTE_LOC; + } + //vals = span((u64*)prng.mBuffer.data(), prng.mBuffer.size() * 2); + //std::cout << "mIsPow2 " << mIsPow2 << std::endl; + vals.resize(prng.mBuffer.size() * sizeof(block) / sizeof(vals[0])); + refill(); + } + + void refill() + { + idx = 0; + + assert(prng.mBuffer.size() == 256); + //block b[8]; + for (u64 i = 0; i < 256; i += 8) + { + //auto idx = mPrng.mBuffer[i].get(); + block* __restrict b = prng.mBuffer.data() + i; + block* __restrict k = prng.mBuffer.data() + (u8)(i - 8); + //for (u64 j = 0; j < 8; ++j) + //{ + // b = b ^ mPrng.mBuffer.data()[idx[j]]; + //} + b[0] = AES::roundEnc(b[0], k[0]); + b[1] = AES::roundEnc(b[1], k[1]); + b[2] = AES::roundEnc(b[2], k[2]); + b[3] = AES::roundEnc(b[3], k[3]); + b[4] = AES::roundEnc(b[4], k[4]); + b[5] = AES::roundEnc(b[5], k[5]); + b[6] = AES::roundEnc(b[6], k[6]); + b[7] = AES::roundEnc(b[7], k[7]); + + b[0] = b[0] ^ k[0]; + b[1] = b[1] ^ k[1]; + b[2] = b[2] ^ k[2]; + b[3] = b[3] ^ k[3]; + b[4] = b[4] ^ k[4]; + b[5] = b[5] ^ k[5]; + b[6] = b[6] ^ k[6]; + b[7] = b[7] ^ k[7]; + } + + auto src = prng.mBuffer.data(); + auto dst = (block*)vals.data(); + if (mIsPow2 ) + { + assert(prng.mBuffer.size() == 256); + + for (u64 i = 0; i < 256; i += 8) + { + dst[i + 0] = src[i + 0] & mPow2MaskBlk; + dst[i + 1] = src[i + 1] & mPow2MaskBlk; + dst[i + 2] = src[i + 2] & mPow2MaskBlk; + dst[i + 3] = src[i + 3] & mPow2MaskBlk; + dst[i + 4] = src[i + 4] & mPow2MaskBlk; + dst[i + 5] = src[i + 5] & mPow2MaskBlk; + dst[i + 6] = src[i + 6] & mPow2MaskBlk; + dst[i + 7] = src[i + 7] & mPow2MaskBlk; + //vals[i] + //vals.data()[i] = *(u64*)ptr & mPow2Mask; + //ptr += mPow2Step; + //++ptr; + } + } + else + { + memcpy(dst, src, vals.size() * sizeof(value_type)); + //throw RTE_LOC; + //assert(vals.size() % 32 == 0); + for (u64 i = 0; i < vals.size(); i += 32) + doMod32(vals.data() + i, &mod, modVal); + } + } + + OC_FORCEINLINE u64 get() + { + if (idx == vals.size()) + refill(); + + return vals.data()[idx++]; + } + + +#ifdef ENABLE_AVX + using block256 = __m256i; + static inline block256 my_libdivide_u64_do_vec256(const block256& x, const libdivide::libdivide_u64_t* divider) + { + return libdivide::libdivide_u64_do_vec256(x, divider); + } +#else + using block256 = std::array; + + static inline block256 _mm256_loadu_si256(block256* p) { return *p; } + + static inline block256 my_libdivide_u64_do_vec256(const block256& x, const libdivide::libdivide_u64_t* divider) + { + block256 y; + auto x64 = (u64*)&x; + auto y64 = (u64*)&y; + for (u64 i = 0; i < 4; ++i) + { + y64[i] = libdivide::libdivide_u64_do(x64[i], divider); + } + + return y; + } +#endif + + + static inline void doMod32(u64* vals, const libdivide::libdivide_u64_t* divider, const u64& modVal) + { + { + u64 i = 0; + block256 row256a = _mm256_loadu_si256((block256*)&vals[i]); + block256 row256b = _mm256_loadu_si256((block256*)&vals[i + 4]); + block256 row256c = _mm256_loadu_si256((block256*)&vals[i + 8]); + block256 row256d = _mm256_loadu_si256((block256*)&vals[i + 12]); + block256 row256e = _mm256_loadu_si256((block256*)&vals[i + 16]); + block256 row256f = _mm256_loadu_si256((block256*)&vals[i + 20]); + block256 row256g = _mm256_loadu_si256((block256*)&vals[i + 24]); + block256 row256h = _mm256_loadu_si256((block256*)&vals[i + 28]); + auto tempa = my_libdivide_u64_do_vec256(row256a, divider); + auto tempb = my_libdivide_u64_do_vec256(row256b, divider); + auto tempc = my_libdivide_u64_do_vec256(row256c, divider); + auto tempd = my_libdivide_u64_do_vec256(row256d, divider); + auto tempe = my_libdivide_u64_do_vec256(row256e, divider); + auto tempf = my_libdivide_u64_do_vec256(row256f, divider); + auto tempg = my_libdivide_u64_do_vec256(row256g, divider); + auto temph = my_libdivide_u64_do_vec256(row256h, divider); + //auto temp = libdivide::libdivide_u64_branchfree_do_vec256(row256, divider); + auto temp64a = (u64*)&tempa; + auto temp64b = (u64*)&tempb; + auto temp64c = (u64*)&tempc; + auto temp64d = (u64*)&tempd; + auto temp64e = (u64*)&tempe; + auto temp64f = (u64*)&tempf; + auto temp64g = (u64*)&tempg; + auto temp64h = (u64*)&temph; + vals[i + 0] -= temp64a[0] * modVal; + vals[i + 1] -= temp64a[1] * modVal; + vals[i + 2] -= temp64a[2] * modVal; + vals[i + 3] -= temp64a[3] * modVal; + vals[i + 4] -= temp64b[0] * modVal; + vals[i + 5] -= temp64b[1] * modVal; + vals[i + 6] -= temp64b[2] * modVal; + vals[i + 7] -= temp64b[3] * modVal; + vals[i + 8] -= temp64c[0] * modVal; + vals[i + 9] -= temp64c[1] * modVal; + vals[i + 10] -= temp64c[2] * modVal; + vals[i + 11] -= temp64c[3] * modVal; + vals[i + 12] -= temp64d[0] * modVal; + vals[i + 13] -= temp64d[1] * modVal; + vals[i + 14] -= temp64d[2] * modVal; + vals[i + 15] -= temp64d[3] * modVal; + vals[i + 16] -= temp64e[0] * modVal; + vals[i + 17] -= temp64e[1] * modVal; + vals[i + 18] -= temp64e[2] * modVal; + vals[i + 19] -= temp64e[3] * modVal; + vals[i + 20] -= temp64f[0] * modVal; + vals[i + 21] -= temp64f[1] * modVal; + vals[i + 22] -= temp64f[2] * modVal; + vals[i + 23] -= temp64f[3] * modVal; + vals[i + 24] -= temp64g[0] * modVal; + vals[i + 25] -= temp64g[1] * modVal; + vals[i + 26] -= temp64g[2] * modVal; + vals[i + 27] -= temp64g[3] * modVal; + vals[i + 28] -= temp64h[0] * modVal; + vals[i + 29] -= temp64h[1] * modVal; + vals[i + 30] -= temp64h[2] * modVal; + vals[i + 31] -= temp64h[3] * modVal; + } + } + + }; + } +} \ No newline at end of file diff --git a/libOTe/Tools/TungstenCode/TungstenCode.h b/libOTe/Tools/TungstenCode/TungstenCode.h new file mode 100644 index 0000000..b67e0f5 --- /dev/null +++ b/libOTe/Tools/TungstenCode/TungstenCode.h @@ -0,0 +1,330 @@ +#pragma once + + +#include "cryptoTools/Common/Defines.h" +#include "cryptoTools/Common/Aligned.h" +#include "cryptoTools/Crypto/PRNG.h" +#include "libOTe/Tools/TungstenCode/TungstenData.h" +#include + +namespace osuCrypto { + namespace experimental { + + + struct TungstenNoop + { + template + OC_FORCEINLINE void applyChunk(T*, T*, Ctx&) {} + + void skip(u64) {} + void reset() {} + }; + + // this expander/permuter maps chunks of inputs uniformly. The final expander is obtained by doing linear sums. + template + struct TungstenPerm + { + static constexpr int chunkSize = chunkSize_; + AlignedUnVector mPerm; + u32* mPermIter = nullptr; + + void reset() + { + mPermIter = mPerm.data(); + } + + void init(u64 size, block seed) + { + + u64 n = divCeil(size, chunkSize); + mPerm.resize(n); + std::iota(mPerm.begin(), mPerm.end(), 0); + + PRNG prng(seed); + for (u64 i = 0; i < n; ++i) + { + auto j = prng.get() % (n - i) + i; + std::swap(mPerm[i], mPerm[j]); + } + reset(); + } + + template + OC_FORCEINLINE void applyChunk( + Iter output, + Iter x, + Ctx& ctx + ) + { + assert(mPermIter < mPerm.data() + mPerm.size()); + auto dst = output + (*(u32 * __restrict)mPermIter * chunkSize); + ++mPermIter; + + ctx.copy(x, x + chunkSize, dst); + } + + + void skip(u64 i) + { + assert(i % chunkSize == 0); + mPermIter += i / chunkSize; + } + }; + + + template + struct TungstenAdder + { + static constexpr int chunkSize = chunkSize_; + u64 mIdx = 0; + + void reset() + { + mIdx = 0; + } + + template + OC_FORCEINLINE void applyChunk( + Iter output, + Iter x, + Ctx& ctx + ) + { + T* __restrict dst = output + mIdx; + mIdx += chunkSize; + + if constexpr (chunkSize == 8) + { + ctx.plus(*(dst + 0), *(dst + 0), *(x + 0)); + ctx.plus(*(dst + 1), *(dst + 1), *(x + 1)); + ctx.plus(*(dst + 2), *(dst + 2), *(x + 2)); + ctx.plus(*(dst + 3), *(dst + 3), *(x + 3)); + ctx.plus(*(dst + 4), *(dst + 4), *(x + 4)); + ctx.plus(*(dst + 5), *(dst + 5), *(x + 5)); + ctx.plus(*(dst + 6), *(dst + 6), *(x + 6)); + ctx.plus(*(dst + 7), *(dst + 7), *(x + 7)); + } + else + { + for (u64 j = 0; j < chunkSize; ++j) + ctx.plus(*(dst + j), *(dst + j), *(x + j)); + } + } + + void skip(u64 i) + { + assert(i % chunkSize == 0); + mIdx += i; + } + }; + + struct TungstenCode + { + static const u64 ChunkSize = 8; + TungstenPerm mPerm; + + u64 mMessageSize = 0; + + u64 mCodeSize = 0; + + u64 mNumIter = 2; + + void config(u64 messageSize, u64 codeSize, block seed = block(452345234, 6756754363)) + { + if (messageSize % ChunkSize) + throw std::runtime_error("messageSize must be a multiple of ChunkSize. " LOCATION); + if (codeSize % ChunkSize) + throw std::runtime_error("codeSize must be a multiple of ChunkSize. " LOCATION); + + mMessageSize = messageSize; + mCodeSize = codeSize; + mPerm.init(mCodeSize - mMessageSize, seed); + } + + template< + typename F, + typename CoeffCtx, + typename Iter + > + void dualEncode(Iter&& e, CoeffCtx ctx) + { + using VecF = typename CoeffCtx::template Vec; + + VecF temp(mCodeSize - mMessageSize); + + if (temp.size() / ChunkSize != mPerm.mPerm.size()) + throw RTE_LOC; + + using RestrictIter = decltype(ctx.template restrictPtr(e)); + + std::array buffs{ + ctx.template restrictPtr(e + (mCodeSize - temp.size())), + ctx.template restrictPtr(temp.begin()) + }; + + for (u64 i = 0; i < mNumIter; ++i) + { + accumulate( + buffs[0], + buffs[1], + mCodeSize - mMessageSize, + mPerm, + ctx); + + std::swap(buffs[0], buffs[1]); + } + + if (mMessageSize > temp.size()) + throw RTE_LOC;// not impl + + TungstenAdder adder; + accumulate( + buffs[0], + ctx.template restrictPtr(e), + mMessageSize, + adder, + ctx); + } + + template< + typename Table, + typename F, + bool rangeCheck, + typename OutputMap, + typename CoeffCtx, + typename Iter + > + void accumulateBlock( + 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();) + { + if (rangeCheck == false || i + Table::data.size() * 2 < size) + _mm_prefetch((char*)(x + i + Table::data.size() * 2), _MM_HINT_T0); + + 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 + 1) % size); + ctx.plus(*xs, *xs, *xi); + + 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 + 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); + + } + } + else + { + throw RTE_LOC; + } + } + + output.template applyChunk(dst, x + (i - ChunkSize), ctx); + + if (rangeCheck && i >= size) + break; + } + } + + + template + void accumulate( + Iter input, + Iter output, + u64 size, + OutputMap& map, + CoeffCtx& ctx) + { + + using Table = TableTungsten1024x4; + + u64 main = std::max(size / Table::data.size() - 1, 0) * Table::data.size(); + u64 i = 0; + map.reset(); + + // for the first iteration, the last accumulateBlock + // will wrap anmd change its value. We therefore can't + // yet map the output for this part. We do this at the end. + while (i < Table::max) + { + TungstenNoop noop; + if (i < main) + accumulateBlock(input, i, output, size, noop, ctx); + else + accumulateBlock(input, i, output, size, noop, ctx); + i += Table::data.size(); + } + map.skip(i); + + // accumulate and map. no range check required. + for (; i < main; i += Table::data.size()) + { + accumulateBlock(input, i, output, size, map, ctx); + } + + // last iteration or two requires range checking. + for (; i < size; i += Table::data.size()) + { + accumulateBlock(input, i, output, size, map, ctx); + } + + // map the missing blocks at the start. + map.reset(); + i = 0; + auto end = std::min(Table::max, size); + while (i < end) + { + map.template applyChunk(output, input + i, ctx); + i += ChunkSize; + } + } + + }; + + } +} \ No newline at end of file diff --git a/libOTe/Tools/TungstenCode/TungstenData.cpp b/libOTe/Tools/TungstenCode/TungstenData.cpp new file mode 100644 index 0000000..7d8decd --- /dev/null +++ b/libOTe/Tools/TungstenCode/TungstenData.cpp @@ -0,0 +1,8 @@ + +#include "TungstenData.h" + +namespace osuCrypto::experimental +{ + constexpr std::array, 1024> TableTungsten1024x4::data; + constexpr std::array, 128> TableTungsten128x4::data; +} \ No newline at end of file diff --git a/libOTe/Tools/TungstenCode/TungstenData.h b/libOTe/Tools/TungstenCode/TungstenData.h new file mode 100644 index 0000000..a8f80f4 --- /dev/null +++ b/libOTe/Tools/TungstenCode/TungstenData.h @@ -0,0 +1,1178 @@ +#pragma once + +#include +#include "cryptoTools/Common/Defines.h" + +namespace osuCrypto::experimental +{ + struct TableTungsten1024x4 + { + static constexpr u16 max = 1022; + + static constexpr std::array, 1024> data + { { + {{ 138, 329, 360, 859 }}, + {{ 130, 618, 775, 946 }}, + {{ 46, 148, 233, 973 }}, + {{ 294, 343, 907, 974 }}, + {{ 43, 236, 370, 898 }}, + {{ 117, 149, 286, 322 }}, + {{ 282, 473, 619, 1010 }}, + {{ 227, 314, 429, 462 }}, + {{ 527, 684, 799, 1001 }}, + {{ 204, 369, 904, 993 }}, + {{ 316, 322, 581, 761 }}, + {{ 138, 239, 919, 943 }}, + {{ 506, 630, 645, 936 }}, + {{ 76, 283, 555, 824 }}, + {{ 180, 762, 918, 970 }}, + {{ 46, 196, 210, 737 }}, + {{ 168, 301, 648, 727 }}, + {{ 5, 156, 610, 938 }}, + {{ 117, 258, 385, 639 }}, + {{ 131, 254, 387, 650 }}, + {{ 26, 647, 776, 967 }}, + {{ 67, 625, 861, 932 }}, + {{ 256, 278, 594, 826 }}, + {{ 251, 427, 711, 963 }}, + {{ 340, 744, 851, 952 }}, + {{ 197, 300, 320, 324 }}, + {{ 29, 518, 555, 570 }}, + {{ 57, 100, 789, 818 }}, + {{ 126, 412, 462, 723 }}, + {{ 61, 173, 513, 874 }}, + {{ 40, 264, 874, 939 }}, + {{ 210, 435, 506, 837 }}, + {{ 169, 327, 352, 394 }}, + {{ 18, 61, 453, 545 }}, + {{ 218, 445, 597, 720 }}, + {{ 57, 168, 479, 525 }}, + {{ 279, 527, 803, 1018 }}, + {{ 233, 302, 476, 900 }}, + {{ 425, 434, 709, 969 }}, + {{ 226, 349, 698, 992 }}, + {{ 45, 828, 888, 995 }}, + {{ 163, 379, 469, 546 }}, + {{ 292, 570, 758, 994 }}, + {{ 244, 354, 866, 987 }}, + {{ 60, 513, 681, 845 }}, + {{ 24, 181, 278, 971 }}, + {{ 121, 508, 686, 937 }}, + {{ 632, 785, 850, 988 }}, + {{ 248, 372, 795, 1002 }}, + {{ 300, 479, 552, 671 }}, + {{ 153, 443, 526, 876 }}, + {{ 379, 624, 728, 830 }}, + {{ 468, 689, 802, 885 }}, + {{ 75, 245, 534, 908 }}, + {{ 69, 107, 279, 886 }}, + {{ 126, 175, 233, 983 }}, + {{ 233, 268, 445, 634 }}, + {{ 77, 252, 472, 582 }}, + {{ 305, 497, 523, 704 }}, + {{ 51, 285, 303, 424 }}, + {{ 33, 216, 245, 739 }}, + {{ 398, 473, 632, 692 }}, + {{ 263, 272, 445, 970 }}, + {{ 46, 263, 362, 562 }}, + {{ 99, 124, 515, 640 }}, + {{ 123, 195, 845, 984 }}, + {{ 429, 915, 974, 1021 }}, + {{ 548, 760, 772, 998 }}, + {{ 327, 419, 458, 832 }}, + {{ 112, 122, 821, 831 }}, + {{ 65, 410, 555, 919 }}, + {{ 213, 409, 733, 781 }}, + {{ 69, 350, 374, 473 }}, + {{ 86, 94, 575, 638 }}, + {{ 472, 497, 556, 722 }}, + {{ 10, 375, 668, 1001 }}, + {{ 13, 129, 533, 640 }}, + {{ 230, 496, 578, 647 }}, + {{ 66, 281, 539, 561 }}, + {{ 2, 544, 646, 864 }}, + {{ 299, 407, 751, 978 }}, + {{ 101, 790, 824, 971 }}, + {{ 194, 235, 641, 693 }}, + {{ 21, 684, 699, 857 }}, + {{ 376, 489, 924, 966 }}, + {{ 73, 723, 849, 1013 }}, + {{ 21, 280, 373, 655 }}, + {{ 98, 404, 551, 704 }}, + {{ 323, 499, 542, 910 }}, + {{ 220, 358, 933, 1019 }}, + {{ 54, 415, 488, 700 }}, + {{ 191, 476, 559, 573 }}, + {{ 629, 782, 891, 946 }}, + {{ 545, 616, 719, 736 }}, + {{ 139, 431, 727, 767 }}, + {{ 261, 489, 589, 654 }}, + {{ 273, 287, 530, 656 }}, + {{ 141, 411, 458, 1002 }}, + {{ 47, 224, 734, 947 }}, + {{ 29, 431, 491, 892 }}, + {{ 56, 106, 149, 692 }}, + {{ 112, 255, 288, 371 }}, + {{ 293, 328, 710, 928 }}, + {{ 62, 204, 656, 1005 }}, + {{ 302, 362, 463, 756 }}, + {{ 196, 595, 814, 879 }}, + {{ 134, 148, 327, 922 }}, + {{ 116, 197, 451, 473 }}, + {{ 167, 386, 513, 951 }}, + {{ 11, 535, 536, 786 }}, + {{ 75, 261, 881, 888 }}, + {{ 219, 236, 404, 609 }}, + {{ 374, 415, 517, 725 }}, + {{ 104, 560, 733, 1002 }}, + {{ 84, 311, 463, 745 }}, + {{ 262, 472, 688, 815 }}, + {{ 102, 116, 440, 980 }}, + {{ 184, 610, 843, 930 }}, + {{ 279, 351, 794, 828 }}, + {{ 162, 268, 389, 841 }}, + {{ 196, 345, 684, 731 }}, + {{ 535, 537, 981, 1018 }}, + {{ 357, 420, 580, 1009 }}, + {{ 31, 37, 176, 717 }}, + {{ 15, 85, 117, 441 }}, + {{ 342, 421, 457, 799 }}, + {{ 404, 410, 754, 960 }}, + {{ 180, 560, 587, 771 }}, + {{ 25, 496, 817, 895 }}, + {{ 156, 527, 565, 726 }}, + {{ 650, 800, 893, 916 }}, + {{ 349, 376, 565, 600 }}, + {{ 174, 628, 874, 1011 }}, + {{ 178, 646, 661, 672 }}, + {{ 383, 429, 586, 629 }}, + {{ 43, 502, 718, 981 }}, + {{ 64, 256, 546, 576 }}, + {{ 416, 504, 646, 709 }}, + {{ 143, 170, 300, 665 }}, + {{ 254, 274, 431, 748 }}, + {{ 58, 403, 736, 856 }}, + {{ 371, 569, 709, 1013 }}, + {{ 149, 871, 985, 1019 }}, + {{ 726, 918, 924, 980 }}, + {{ 110, 126, 168, 477 }}, + {{ 339, 429, 713, 1005 }}, + {{ 136, 620, 733, 911 }}, + {{ 46, 168, 690, 907 }}, + {{ 335, 814, 913, 1012 }}, + {{ 323, 366, 878, 1006 }}, + {{ 230, 254, 373, 513 }}, + {{ 248, 744, 760, 833 }}, + {{ 151, 604, 817, 995 }}, + {{ 70, 205, 492, 845 }}, + {{ 401, 507, 594, 1004 }}, + {{ 53, 100, 769, 898 }}, + {{ 372, 404, 856, 873 }}, + {{ 313, 388, 441, 718 }}, + {{ 274, 565, 698, 972 }}, + {{ 138, 319, 446, 1007 }}, + {{ 125, 240, 482, 900 }}, + {{ 56, 157, 612, 731 }}, + {{ 66, 222, 350, 806 }}, + {{ 183, 444, 736, 987 }}, + {{ 354, 436, 800, 894 }}, + {{ 434, 494, 524, 714 }}, + {{ 236, 349, 831, 999 }}, + {{ 26, 397, 678, 1013 }}, + {{ 92, 112, 242, 794 }}, + {{ 88, 416, 599, 634 }}, + {{ 38, 91, 775, 869 }}, + {{ 96, 517, 630, 690 }}, + {{ 252, 393, 550, 744 }}, + {{ 82, 492, 642, 915 }}, + {{ 395, 545, 709, 930 }}, + {{ 77, 343, 641, 713 }}, + {{ 469, 714, 856, 1001 }}, + {{ 658, 709, 815, 929 }}, + {{ 287, 370, 377, 430 }}, + {{ 425, 555, 612, 735 }}, + {{ 36, 243, 496, 992 }}, + {{ 139, 387, 584, 624 }}, + {{ 42, 230, 648, 812 }}, + {{ 226, 244, 687, 850 }}, + {{ 83, 318, 594, 678 }}, + {{ 38, 166, 455, 724 }}, + {{ 154, 650, 817, 857 }}, + {{ 10, 25, 71, 583 }}, + {{ 260, 355, 455, 717 }}, + {{ 370, 488, 538, 541 }}, + {{ 495, 739, 853, 956 }}, + {{ 309, 641, 774, 871 }}, + {{ 556, 774, 818, 838 }}, + {{ 212, 235, 532, 739 }}, + {{ 65, 183, 386, 798 }}, + {{ 704, 779, 790, 1003 }}, + {{ 96, 179, 765, 779 }}, + {{ 102, 103, 176, 941 }}, + {{ 139, 385, 519, 782 }}, + {{ 30, 113, 745, 1009 }}, + {{ 78, 448, 713, 829 }}, + {{ 47, 717, 721, 922 }}, + {{ 23, 103, 251, 438 }}, + {{ 271, 500, 532, 833 }}, + {{ 31, 221, 439, 636 }}, + {{ 30, 278, 532, 893 }}, + {{ 463, 552, 635, 753 }}, + {{ 485, 539, 762, 965 }}, + {{ 190, 376, 386, 635 }}, + {{ 187, 341, 482, 647 }}, + {{ 182, 227, 422, 918 }}, + {{ 136, 286, 329, 870 }}, + {{ 69, 235, 450, 660 }}, + {{ 6, 274, 560, 696 }}, + {{ 176, 379, 752, 870 }}, + {{ 43, 185, 382, 831 }}, + {{ 561, 603, 730, 911 }}, + {{ 575, 749, 855, 992 }}, + {{ 167, 249, 551, 566 }}, + {{ 71, 490, 568, 776 }}, + {{ 122, 299, 547, 786 }}, + {{ 47, 676, 734, 753 }}, + {{ 206, 221, 873, 1011 }}, + {{ 219, 429, 728, 877 }}, + {{ 255, 505, 746, 840 }}, + {{ 179, 740, 774, 881 }}, + {{ 220, 356, 387, 701 }}, + {{ 138, 214, 251, 494 }}, + {{ 19, 129, 425, 629 }}, + {{ 166, 379, 849, 990 }}, + {{ 583, 636, 758, 778 }}, + {{ 35, 71, 316, 912 }}, + {{ 36, 427, 638, 730 }}, + {{ 78, 485, 731, 775 }}, + {{ 147, 345, 678, 943 }}, + {{ 38, 137, 404, 754 }}, + {{ 207, 516, 778, 929 }}, + {{ 144, 248, 283, 565 }}, + {{ 104, 112, 459, 561 }}, + {{ 124, 293, 548, 900 }}, + {{ 41, 50, 193, 792 }}, + {{ 569, 607, 641, 800 }}, + {{ 37, 53, 159, 477 }}, + {{ 590, 752, 754, 914 }}, + {{ 603, 868, 996, 1018 }}, + {{ 741, 759, 930, 990 }}, + {{ 345, 507, 778, 934 }}, + {{ 735, 816, 888, 960 }}, + {{ 366, 486, 680, 814 }}, + {{ 4, 243, 520, 1004 }}, + {{ 90, 226, 608, 930 }}, + {{ 171, 566, 644, 689 }}, + {{ 21, 184, 217, 403 }}, + {{ 168, 219, 586, 677 }}, + {{ 42, 94, 444, 577 }}, + {{ 209, 237, 345, 643 }}, + {{ 241, 611, 696, 946 }}, + {{ 525, 587, 687, 823 }}, + {{ 173, 548, 891, 913 }}, + {{ 415, 547, 618, 895 }}, + {{ 60, 242, 323, 1014 }}, + {{ 214, 314, 592, 611 }}, + {{ 646, 651, 744, 957 }}, + {{ 212, 293, 479, 630 }}, + {{ 740, 811, 897, 1017 }}, + {{ 48, 87, 266, 638 }}, + {{ 93, 274, 706, 985 }}, + {{ 113, 149, 843, 853 }}, + {{ 141, 308, 690, 978 }}, + {{ 9, 275, 814, 860 }}, + {{ 164, 339, 570, 641 }}, + {{ 107, 294, 477, 579 }}, + {{ 276, 350, 755, 772 }}, + {{ 112, 341, 384, 701 }}, + {{ 147, 447, 488, 929 }}, + {{ 2, 154, 614, 726 }}, + {{ 701, 824, 859, 954 }}, + {{ 292, 342, 478, 669 }}, + {{ 483, 543, 1003, 1014 }}, + {{ 101, 374, 617, 629 }}, + {{ 696, 702, 930, 972 }}, + {{ 225, 341, 436, 514 }}, + {{ 354, 543, 795, 878 }}, + {{ 173, 216, 266, 381 }}, + {{ 370, 373, 622, 753 }}, + {{ 359, 529, 839, 941 }}, + {{ 67, 310, 345, 615 }}, + {{ 73, 313, 676, 698 }}, + {{ 419, 687, 794, 957 }}, + {{ 191, 416, 841, 907 }}, + {{ 604, 748, 880, 903 }}, + {{ 98, 100, 335, 603 }}, + {{ 341, 630, 768, 945 }}, + {{ 67, 812, 940, 965 }}, + {{ 28, 36, 344, 1000 }}, + {{ 106, 169, 818, 980 }}, + {{ 12, 531, 720, 922 }}, + {{ 66, 166, 632, 675 }}, + {{ 25, 361, 522, 990 }}, + {{ 566, 715, 769, 973 }}, + {{ 27, 123, 610, 916 }}, + {{ 41, 202, 822, 1002 }}, + {{ 396, 446, 500, 656 }}, + {{ 134, 387, 578, 794 }}, + {{ 205, 439, 608, 622 }}, + {{ 23, 576, 892, 920 }}, + {{ 372, 590, 918, 954 }}, + {{ 15, 470, 672, 1018 }}, + {{ 47, 688, 788, 867 }}, + {{ 82, 252, 419, 989 }}, + {{ 92, 533, 839, 986 }}, + {{ 56, 641, 686, 699 }}, + {{ 135, 441, 468, 966 }}, + {{ 260, 720, 835, 884 }}, + {{ 261, 700, 794, 1008 }}, + {{ 41, 383, 581, 924 }}, + {{ 92, 488, 841, 846 }}, + {{ 32, 361, 508, 942 }}, + {{ 27, 218, 446, 575 }}, + {{ 111, 349, 870, 883 }}, + {{ 265, 326, 627, 947 }}, + {{ 269, 521, 614, 798 }}, + {{ 6, 257, 863, 965 }}, + {{ 107, 597, 843, 978 }}, + {{ 5, 296, 407, 639 }}, + {{ 221, 335, 856, 943 }}, + {{ 150, 157, 179, 1011 }}, + {{ 701, 776, 804, 859 }}, + {{ 53, 206, 893, 945 }}, + {{ 97, 125, 346, 726 }}, + {{ 145, 266, 397, 627 }}, + {{ 281, 329, 559, 606 }}, + {{ 12, 541, 897, 899 }}, + {{ 82, 255, 605, 664 }}, + {{ 254, 270, 382, 945 }}, + {{ 111, 415, 702, 999 }}, + {{ 29, 37, 315, 870 }}, + {{ 126, 350, 464, 482 }}, + {{ 202, 295, 510, 818 }}, + {{ 379, 729, 785, 843 }}, + {{ 219, 558, 584, 646 }}, + {{ 140, 168, 644, 967 }}, + {{ 142, 182, 942, 965 }}, + {{ 125, 669, 905, 957 }}, + {{ 293, 850, 898, 912 }}, + {{ 160, 320, 651, 689 }}, + {{ 661, 663, 671, 962 }}, + {{ 82, 323, 530, 621 }}, + {{ 422, 460, 553, 988 }}, + {{ 47, 66, 449, 516 }}, + {{ 33, 324, 553, 941 }}, + {{ 21, 247, 649, 909 }}, + {{ 212, 422, 423, 677 }}, + {{ 344, 607, 832, 988 }}, + {{ 14, 163, 210, 231 }}, + {{ 4, 170, 456, 845 }}, + {{ 232, 611, 673, 984 }}, + {{ 116, 200, 598, 856 }}, + {{ 94, 325, 818, 982 }}, + {{ 285, 597, 645, 911 }}, + {{ 47, 382, 418, 923 }}, + {{ 126, 338, 799, 804 }}, + {{ 160, 569, 653, 745 }}, + {{ 632, 819, 865, 947 }}, + {{ 94, 445, 481, 711 }}, + {{ 156, 381, 721, 833 }}, + {{ 3, 5, 60, 280 }}, + {{ 47, 325, 713, 975 }}, + {{ 48, 314, 456, 770 }}, + {{ 552, 603, 634, 689 }}, + {{ 92, 279, 295, 460 }}, + {{ 53, 236, 874, 1018 }}, + {{ 50, 113, 397, 971 }}, + {{ 594, 716, 790, 841 }}, + {{ 60, 176, 492, 894 }}, + {{ 18, 83, 712, 987 }}, + {{ 296, 669, 741, 937 }}, + {{ 125, 447, 650, 975 }}, + {{ 64, 542, 624, 785 }}, + {{ 226, 565, 733, 892 }}, + {{ 335, 613, 710, 720 }}, + {{ 253, 516, 687, 889 }}, + {{ 17, 187, 735, 751 }}, + {{ 388, 805, 816, 933 }}, + {{ 501, 563, 739, 924 }}, + {{ 34, 138, 573, 822 }}, + {{ 276, 604, 632, 674 }}, + {{ 11, 28, 451, 595 }}, + {{ 407, 489, 967, 997 }}, + {{ 400, 472, 528, 655 }}, + {{ 134, 191, 298, 797 }}, + {{ 181, 477, 582, 788 }}, + {{ 255, 350, 628, 809 }}, + {{ 512, 641, 819, 936 }}, + {{ 238, 456, 901, 923 }}, + {{ 139, 290, 769, 953 }}, + {{ 349, 527, 1012, 1019 }}, + {{ 224, 459, 474, 860 }}, + {{ 581, 701, 785, 838 }}, + {{ 358, 463, 522, 710 }}, + {{ 323, 716, 811, 954 }}, + {{ 88, 192, 281, 338 }}, + {{ 273, 283, 376, 984 }}, + {{ 133, 325, 618, 840 }}, + {{ 237, 837, 848, 994 }}, + {{ 658, 795, 857, 881 }}, + {{ 37, 508, 610, 816 }}, + {{ 66, 132, 439, 962 }}, + {{ 28, 378, 585, 768 }}, + {{ 417, 511, 562, 779 }}, + {{ 148, 406, 844, 965 }}, + {{ 47, 468, 741, 927 }}, + {{ 344, 644, 857, 982 }}, + {{ 32, 600, 804, 858 }}, + {{ 307, 501, 674, 801 }}, + {{ 618, 700, 944, 996 }}, + {{ 140, 297, 702, 783 }}, + {{ 246, 371, 724, 740 }}, + {{ 33, 467, 513, 749 }}, + {{ 262, 313, 353, 538 }}, + {{ 140, 177, 498, 945 }}, + {{ 518, 557, 601, 666 }}, + {{ 226, 363, 396, 628 }}, + {{ 112, 360, 625, 910 }}, + {{ 596, 691, 840, 921 }}, + {{ 466, 508, 629, 760 }}, + {{ 9, 62, 849, 935 }}, + {{ 77, 590, 644, 762 }}, + {{ 265, 278, 889, 984 }}, + {{ 56, 133, 598, 643 }}, + {{ 205, 215, 268, 303 }}, + {{ 302, 331, 681, 990 }}, + {{ 254, 279, 840, 1021 }}, + {{ 142, 375, 385, 565 }}, + {{ 195, 827, 1005, 1013 }}, + {{ 376, 854, 959, 1006 }}, + {{ 117, 200, 732, 840 }}, + {{ 254, 610, 711, 734 }}, + {{ 507, 605, 682, 726 }}, + {{ 128, 667, 696, 925 }}, + {{ 130, 330, 415, 816 }}, + {{ 23, 210, 324, 844 }}, + {{ 100, 102, 547, 800 }}, + {{ 162, 485, 863, 979 }}, + {{ 543, 608, 630, 807 }}, + {{ 293, 753, 811, 884 }}, + {{ 55, 322, 375, 593 }}, + {{ 422, 590, 852, 890 }}, + {{ 502, 775, 997, 1014 }}, + {{ 82, 104, 164, 269 }}, + {{ 436, 657, 817, 849 }}, + {{ 269, 332, 590, 733 }}, + {{ 52, 265, 298, 529 }}, + {{ 21, 524, 836, 873 }}, + {{ 499, 804, 904, 975 }}, + {{ 279, 362, 472, 717 }}, + {{ 348, 617, 770, 808 }}, + {{ 206, 223, 226, 975 }}, + {{ 521, 792, 983, 1016 }}, + {{ 123, 460, 712, 937 }}, + {{ 50, 677, 854, 907 }}, + {{ 23, 176, 283, 447 }}, + {{ 192, 608, 927, 942 }}, + {{ 630, 657, 674, 823 }}, + {{ 249, 432, 454, 1009 }}, + {{ 55, 230, 389, 1003 }}, + {{ 145, 603, 661, 758 }}, + {{ 139, 391, 517, 734 }}, + {{ 98, 552, 587, 806 }}, + {{ 242, 762, 779, 816 }}, + {{ 274, 539, 566, 744 }}, + {{ 375, 468, 482, 713 }}, + {{ 187, 575, 741, 884 }}, + {{ 88, 176, 409, 772 }}, + {{ 206, 473, 918, 1011 }}, + {{ 24, 226, 249, 417 }}, + {{ 145, 569, 622, 679 }}, + {{ 431, 517, 739, 795 }}, + {{ 60, 263, 714, 721 }}, + {{ 70, 75, 194, 256 }}, + {{ 78, 572, 585, 936 }}, + {{ 101, 191, 457, 593 }}, + {{ 45, 970, 980, 987 }}, + {{ 15, 310, 780, 934 }}, + {{ 471, 656, 744, 929 }}, + {{ 550, 577, 606, 825 }}, + {{ 327, 643, 772, 998 }}, + {{ 355, 553, 876, 948 }}, + {{ 19, 20, 148, 585 }}, + {{ 445, 710, 912, 944 }}, + {{ 71, 531, 559, 777 }}, + {{ 361, 452, 509, 758 }}, + {{ 315, 731, 804, 838 }}, + {{ 145, 335, 738, 762 }}, + {{ 110, 435, 442, 816 }}, + {{ 284, 496, 865, 895 }}, + {{ 20, 131, 585, 691 }}, + {{ 28, 182, 309, 537 }}, + {{ 739, 903, 912, 938 }}, + {{ 159, 169, 228, 645 }}, + {{ 542, 549, 735, 835 }}, + {{ 764, 779, 838, 885 }}, + {{ 176, 320, 516, 627 }}, + {{ 429, 522, 601, 671 }}, + {{ 22, 488, 603, 614 }}, + {{ 61, 449, 640, 703 }}, + {{ 271, 462, 504, 686 }}, + {{ 15, 326, 439, 881 }}, + {{ 163, 375, 606, 1020 }}, + {{ 623, 804, 974, 997 }}, + {{ 55, 76, 339, 915 }}, + {{ 380, 574, 664, 668 }}, + {{ 29, 274, 437, 824 }}, + {{ 460, 540, 878, 914 }}, + {{ 133, 246, 924, 950 }}, + {{ 303, 352, 753, 1015 }}, + {{ 41, 110, 857, 1017 }}, + {{ 214, 327, 948, 996 }}, + {{ 172, 239, 677, 686 }}, + {{ 130, 302, 461, 715 }}, + {{ 270, 343, 498, 792 }}, + {{ 90, 486, 803, 1016 }}, + {{ 149, 631, 774, 912 }}, + {{ 179, 410, 702, 1018 }}, + {{ 262, 401, 773, 964 }}, + {{ 163, 704, 830, 956 }}, + {{ 322, 493, 870, 987 }}, + {{ 414, 616, 876, 964 }}, + {{ 145, 375, 413, 1015 }}, + {{ 240, 396, 488, 707 }}, + {{ 89, 198, 220, 912 }}, + {{ 206, 533, 743, 829 }}, + {{ 174, 212, 411, 624 }}, + {{ 46, 65, 77, 969 }}, + {{ 340, 383, 684, 833 }}, + {{ 147, 226, 413, 667 }}, + {{ 484, 659, 727, 823 }}, + {{ 159, 456, 656, 822 }}, + {{ 554, 619, 755, 827 }}, + {{ 201, 288, 295, 705 }}, + {{ 51, 529, 610, 717 }}, + {{ 45, 82, 410, 974 }}, + {{ 2, 641, 861, 917 }}, + {{ 159, 331, 341, 542 }}, + {{ 577, 970, 1001, 1009 }}, + {{ 65, 187, 622, 917 }}, + {{ 295, 297, 724, 773 }}, + {{ 175, 374, 389, 659 }}, + {{ 223, 313, 675, 1010 }}, + {{ 572, 760, 848, 926 }}, + {{ 33, 164, 241, 312 }}, + {{ 281, 500, 612, 645 }}, + {{ 41, 78, 248, 701 }}, + {{ 31, 304, 651, 964 }}, + {{ 16, 822, 858, 870 }}, + {{ 21, 79, 984, 991 }}, + {{ 133, 310, 359, 756 }}, + {{ 67, 525, 915, 951 }}, + {{ 152, 685, 705, 919 }}, + {{ 181, 517, 855, 1012 }}, + {{ 716, 785, 906, 1000 }}, + {{ 81, 424, 705, 727 }}, + {{ 88, 301, 391, 614 }}, + {{ 256, 388, 714, 956 }}, + {{ 97, 368, 709, 952 }}, + {{ 67, 298, 728, 798 }}, + {{ 170, 473, 729, 906 }}, + {{ 255, 309, 627, 968 }}, + {{ 388, 443, 636, 671 }}, + {{ 4, 236, 278, 700 }}, + {{ 232, 323, 623, 807 }}, + {{ 263, 298, 315, 524 }}, + {{ 6, 183, 991, 997 }}, + {{ 166, 500, 774, 961 }}, + {{ 733, 814, 932, 946 }}, + {{ 105, 329, 360, 663 }}, + {{ 424, 749, 987, 989 }}, + {{ 232, 417, 428, 548 }}, + {{ 292, 908, 917, 949 }}, + {{ 157, 446, 614, 1016 }}, + {{ 217, 226, 443, 961 }}, + {{ 61, 336, 415, 975 }}, + {{ 519, 601, 673, 744 }}, + {{ 168, 246, 641, 760 }}, + {{ 194, 636, 871, 922 }}, + {{ 85, 315, 508, 859 }}, + {{ 510, 615, 892, 1006 }}, + {{ 158, 209, 893, 980 }}, + {{ 34, 328, 383, 843 }}, + {{ 300, 625, 714, 851 }}, + {{ 164, 504, 511, 861 }}, + {{ 35, 363, 862, 930 }}, + {{ 147, 215, 221, 826 }}, + {{ 29, 234, 254, 259 }}, + {{ 250, 298, 640, 1011 }}, + {{ 52, 567, 803, 819 }}, + {{ 490, 578, 867, 1005 }}, + {{ 344, 582, 844, 870 }}, + {{ 225, 693, 860, 995 }}, + {{ 375, 402, 587, 882 }}, + {{ 181, 368, 500, 654 }}, + {{ 353, 418, 498, 714 }}, + {{ 143, 533, 949, 984 }}, + {{ 106, 436, 917, 1016 }}, + {{ 227, 262, 485, 637 }}, + {{ 382, 478, 794, 863 }}, + {{ 377, 471, 875, 929 }}, + {{ 23, 98, 539, 1002 }}, + {{ 48, 58, 731, 948 }}, + {{ 167, 246, 707, 915 }}, + {{ 164, 470, 593, 928 }}, + {{ 23, 222, 419, 562 }}, + {{ 302, 699, 845, 847 }}, + {{ 192, 254, 501, 851 }}, + {{ 274, 311, 716, 794 }}, + {{ 130, 269, 533, 662 }}, + {{ 431, 598, 630, 982 }}, + {{ 51, 137, 777, 783 }}, + {{ 68, 394, 660, 860 }}, + {{ 239, 716, 810, 899 }}, + {{ 322, 323, 491, 571 }}, + {{ 295, 471, 720, 727 }}, + {{ 423, 443, 745, 1020 }}, + {{ 152, 346, 603, 660 }}, + {{ 254, 410, 678, 738 }}, + {{ 453, 670, 756, 791 }}, + {{ 75, 194, 506, 809 }}, + {{ 589, 816, 974, 1017 }}, + {{ 542, 633, 738, 846 }}, + {{ 295, 349, 382, 699 }}, + {{ 133, 253, 704, 1002 }}, + {{ 55, 105, 471, 578 }}, + {{ 131, 428, 662, 736 }}, + {{ 337, 528, 705, 907 }}, + {{ 139, 604, 649, 1013 }}, + {{ 266, 468, 813, 945 }}, + {{ 14, 323, 375, 415 }}, + {{ 340, 529, 597, 711 }}, + {{ 246, 528, 673, 767 }}, + {{ 392, 555, 654, 723 }}, + {{ 72, 152, 291, 351 }}, + {{ 68, 430, 601, 796 }}, + {{ 73, 669, 713, 971 }}, + {{ 34, 632, 788, 987 }}, + {{ 34, 364, 525, 770 }}, + {{ 139, 142, 847, 867 }}, + {{ 120, 310, 722, 916 }}, + {{ 112, 272, 601, 715 }}, + {{ 292, 603, 900, 942 }}, + {{ 36, 98, 215, 455 }}, + {{ 150, 203, 697, 887 }}, + {{ 15, 402, 693, 807 }}, + {{ 183, 313, 922, 1013 }}, + {{ 500, 557, 722, 791 }}, + {{ 319, 491, 721, 964 }}, + {{ 29, 156, 170, 485 }}, + {{ 168, 654, 969, 1011 }}, + {{ 444, 561, 699, 977 }}, + {{ 151, 356, 1000, 1018 }}, + {{ 44, 717, 735, 758 }}, + {{ 601, 613, 740, 806 }}, + {{ 121, 546, 834, 957 }}, + {{ 180, 569, 691, 961 }}, + {{ 10, 207, 243, 794 }}, + {{ 400, 402, 439, 974 }}, + {{ 171, 875, 906, 912 }}, + {{ 15, 22, 25, 478 }}, + {{ 171, 316, 700, 953 }}, + {{ 161, 312, 519, 762 }}, + {{ 321, 493, 696, 888 }}, + {{ 16, 59, 579, 929 }}, + {{ 88, 420, 519, 711 }}, + {{ 102, 113, 716, 749 }}, + {{ 152, 738, 747, 880 }}, + {{ 252, 429, 460, 964 }}, + {{ 391, 626, 667, 819 }}, + {{ 19, 231, 406, 516 }}, + {{ 252, 287, 941, 1000 }}, + {{ 317, 648, 858, 870 }}, + {{ 73, 201, 262, 769 }}, + {{ 116, 457, 772, 959 }}, + {{ 102, 117, 579, 799 }}, + {{ 30, 104, 443, 656 }}, + {{ 6, 181, 345, 792 }}, + {{ 103, 396, 620, 956 }}, + {{ 339, 559, 694, 870 }}, + {{ 150, 373, 747, 986 }}, + {{ 154, 453, 805, 818 }}, + {{ 16, 69, 502, 580 }}, + {{ 10, 170, 672, 737 }}, + {{ 39, 201, 329, 943 }}, + {{ 75, 505, 522, 665 }}, + {{ 72, 258, 449, 699 }}, + {{ 242, 348, 434, 593 }}, + {{ 397, 623, 778, 856 }}, + {{ 401, 427, 675, 691 }}, + {{ 202, 248, 602, 941 }}, + {{ 283, 429, 801, 934 }}, + {{ 27, 116, 804, 854 }}, + {{ 91, 166, 411, 465 }}, + {{ 267, 318, 445, 820 }}, + {{ 187, 227, 320, 762 }}, + {{ 377, 428, 484, 1009 }}, + {{ 105, 170, 491, 813 }}, + {{ 132, 375, 426, 982 }}, + {{ 75, 257, 454, 646 }}, + {{ 170, 325, 413, 976 }}, + {{ 82, 128, 696, 790 }}, + {{ 51, 271, 638, 846 }}, + {{ 130, 319, 752, 850 }}, + {{ 46, 85, 380, 685 }}, + {{ 129, 707, 810, 1020 }}, + {{ 298, 332, 432, 737 }}, + {{ 318, 460, 859, 1012 }}, + {{ 58, 332, 477, 881 }}, + {{ 212, 357, 741, 889 }}, + {{ 13, 119, 289, 607 }}, + {{ 32, 168, 664, 751 }}, + {{ 17, 297, 400, 564 }}, + {{ 4, 160, 201, 652 }}, + {{ 565, 625, 824, 931 }}, + {{ 113, 338, 561, 611 }}, + {{ 227, 514, 669, 778 }}, + {{ 321, 500, 847, 975 }}, + {{ 130, 568, 897, 1013 }}, + {{ 326, 445, 554, 1011 }}, + {{ 125, 570, 692, 1005 }}, + {{ 278, 336, 401, 937 }}, + {{ 70, 208, 423, 648 }}, + {{ 337, 373, 449, 1000 }}, + {{ 89, 310, 921, 1004 }}, + {{ 361, 778, 783, 940 }}, + {{ 66, 244, 277, 907 }}, + {{ 84, 97, 611, 974 }}, + {{ 150, 337, 742, 823 }}, + {{ 45, 203, 289, 313 }}, + {{ 395, 624, 739, 1018 }}, + {{ 439, 493, 590, 640 }}, + {{ 159, 372, 514, 894 }}, + {{ 115, 402, 813, 871 }}, + {{ 620, 650, 733, 779 }}, + {{ 14, 101, 261, 341 }}, + {{ 23, 328, 416, 933 }}, + {{ 56, 214, 294, 997 }}, + {{ 12, 437, 755, 875 }}, + {{ 316, 370, 885, 941 }}, + {{ 82, 165, 540, 943 }}, + {{ 296, 374, 796, 954 }}, + {{ 46, 330, 361, 665 }}, + {{ 583, 810, 881, 930 }}, + {{ 35, 141, 675, 890 }}, + {{ 248, 468, 890, 1006 }}, + {{ 390, 523, 967, 968 }}, + {{ 492, 632, 654, 995 }}, + {{ 17, 335, 366, 710 }}, + {{ 161, 665, 721, 831 }}, + {{ 81, 476, 976, 984 }}, + {{ 224, 447, 493, 817 }}, + {{ 42, 203, 795, 1006 }}, + {{ 25, 31, 439, 827 }}, + {{ 484, 487, 618, 1022 }}, + {{ 3, 131, 280, 392 }}, + {{ 55, 264, 359, 507 }}, + {{ 16, 465, 819, 951 }}, + {{ 248, 838, 893, 968 }}, + {{ 63, 235, 302, 1017 }}, + {{ 192, 339, 592, 619 }}, + {{ 120, 221, 440, 444 }}, + {{ 295, 495, 670, 805 }}, + {{ 288, 637, 708, 1022 }}, + {{ 187, 533, 673, 695 }}, + {{ 30, 101, 141, 489 }}, + {{ 38, 97, 738, 971 }}, + {{ 50, 78, 802, 991 }}, + {{ 164, 232, 375, 886 }}, + {{ 491, 632, 684, 979 }}, + {{ 125, 134, 674, 1005 }}, + {{ 83, 512, 550, 721 }}, + {{ 484, 559, 579, 920 }}, + {{ 289, 426, 471, 759 }}, + {{ 202, 537, 671, 860 }}, + {{ 99, 182, 400, 512 }}, + {{ 294, 691, 882, 944 }}, + {{ 139, 269, 368, 925 }}, + {{ 60, 613, 770, 1014 }}, + {{ 270, 420, 889, 967 }}, + {{ 268, 638, 724, 744 }}, + {{ 36, 46, 287, 763 }}, + {{ 89, 455, 589, 891 }}, + {{ 379, 408, 783, 940 }}, + {{ 74, 430, 854, 938 }}, + {{ 257, 646, 693, 832 }}, + {{ 305, 517, 573, 820 }}, + {{ 178, 268, 477, 540 }}, + {{ 273, 296, 379, 696 }}, + {{ 80, 286, 1021, 1022 }}, + {{ 85, 583, 787, 808 }}, + {{ 631, 674, 895, 1016 }}, + {{ 141, 479, 879, 952 }}, + {{ 100, 320, 832, 978 }}, + {{ 358, 454, 745, 751 }}, + {{ 256, 892, 916, 1004 }}, + {{ 113, 684, 724, 840 }}, + {{ 132, 198, 697, 761 }}, + {{ 9, 347, 911, 966 }}, + {{ 366, 549, 818, 1007 }}, + {{ 411, 415, 510, 882 }}, + {{ 42, 688, 884, 993 }}, + {{ 266, 618, 763, 905 }}, + {{ 621, 685, 752, 953 }}, + {{ 323, 344, 511, 730 }}, + {{ 156, 177, 377, 890 }}, + {{ 70, 378, 443, 920 }}, + {{ 213, 517, 664, 869 }}, + {{ 45, 585, 627, 704 }}, + {{ 144, 227, 837, 1021 }}, + {{ 47, 774, 826, 871 }}, + {{ 131, 267, 523, 798 }}, + {{ 420, 439, 801, 818 }}, + {{ 37, 323, 488, 904 }}, + {{ 67, 334, 745, 971 }}, + {{ 105, 276, 557, 786 }}, + {{ 318, 530, 643, 830 }}, + {{ 64, 344, 662, 811 }}, + {{ 126, 723, 798, 906 }}, + {{ 188, 194, 645, 925 }}, + {{ 791, 874, 928, 963 }}, + {{ 58, 199, 472, 494 }}, + {{ 333, 544, 957, 985 }}, + {{ 141, 541, 564, 660 }}, + {{ 356, 404, 736, 954 }}, + {{ 71, 246, 785, 812 }}, + {{ 258, 270, 691, 1015 }}, + {{ 299, 573, 656, 777 }}, + {{ 41, 639, 793, 963 }}, + {{ 38, 41, 78, 730 }}, + {{ 482, 521, 751, 860 }}, + {{ 27, 642, 675, 975 }}, + {{ 104, 195, 401, 1014 }}, + {{ 432, 495, 630, 820 }}, + {{ 175, 284, 919, 952 }}, + {{ 131, 238, 605, 921 }}, + {{ 322, 508, 614, 899 }}, + {{ 592, 600, 719, 880 }}, + {{ 624, 680, 692, 990 }}, + {{ 166, 180, 771, 943 }}, + {{ 237, 632, 782, 845 }}, + {{ 272, 564, 828, 978 }}, + {{ 205, 222, 442, 571 }}, + {{ 39, 232, 777, 914 }}, + {{ 28, 52, 291, 850 }}, + {{ 113, 666, 822, 905 }}, + {{ 109, 224, 503, 921 }}, + {{ 103, 387, 827, 890 }}, + {{ 241, 528, 771, 864 }}, + {{ 111, 464, 577, 884 }}, + {{ 518, 578, 844, 975 }}, + {{ 113, 494, 542, 955 }}, + {{ 215, 621, 698, 786 }}, + {{ 3, 421, 717, 844 }}, + {{ 453, 521, 585, 596 }}, + {{ 252, 496, 700, 874 }}, + {{ 601, 754, 828, 846 }}, + {{ 616, 725, 745, 764 }}, + {{ 313, 691, 765, 771 }}, + {{ 71, 252, 544, 711 }}, + {{ 334, 453, 516, 960 }}, + {{ 11, 343, 872, 972 }}, + {{ 77, 353, 799, 1009 }}, + {{ 14, 157, 454, 473 }}, + {{ 186, 502, 536, 1014 }}, + {{ 48, 102, 187, 507 }}, + {{ 166, 265, 691, 859 }}, + {{ 555, 646, 760, 933 }}, + {{ 91, 223, 563, 892 }}, + {{ 149, 525, 875, 944 }}, + {{ 39, 123, 131, 870 }}, + {{ 179, 233, 965, 967 }}, + {{ 162, 471, 829, 995 }}, + {{ 14, 269, 516, 716 }}, + {{ 434, 447, 666, 734 }}, + {{ 26, 36, 253, 692 }}, + {{ 39, 306, 893, 1020 }}, + {{ 24, 168, 851, 890 }}, + {{ 15, 230, 263, 434 }}, + {{ 108, 620, 886, 933 }}, + {{ 728, 777, 898, 979 }}, + {{ 224, 269, 444, 1017 }}, + {{ 154, 190, 748, 833 }}, + {{ 15, 199, 705, 839 }}, + {{ 196, 211, 757, 848 }}, + {{ 141, 396, 468, 690 }}, + {{ 12, 234, 559, 798 }}, + {{ 110, 591, 645, 928 }}, + {{ 217, 359, 486, 516 }}, + {{ 560, 789, 835, 1015 }}, + {{ 388, 619, 760, 761 }}, + {{ 28, 664, 819, 885 }}, + {{ 80, 238, 627, 936 }}, + {{ 35, 282, 368, 493 }}, + {{ 52, 678, 748, 794 }}, + {{ 289, 295, 379, 380 }}, + {{ 418, 632, 751, 848 }}, + {{ 68, 75, 859, 862 }}, + {{ 95, 468, 488, 611 }}, + {{ 233, 623, 722, 949 }}, + {{ 496, 629, 639, 812 }}, + {{ 304, 315, 320, 748 }}, + {{ 248, 319, 471, 627 }}, + {{ 112, 321, 828, 1009 }}, + {{ 480, 526, 580, 814 }}, + {{ 3, 242, 498, 765 }}, + {{ 221, 238, 878, 909 }}, + {{ 75, 415, 783, 940 }}, + {{ 109, 128, 567, 961 }}, + {{ 288, 660, 711, 964 }}, + {{ 575, 585, 641, 923 }}, + {{ 610, 616, 645, 853 }}, + {{ 118, 241, 800, 899 }}, + {{ 30, 44, 419, 630 }}, + {{ 139, 174, 430, 693 }}, + {{ 101, 344, 610, 731 }}, + {{ 133, 212, 563, 610 }}, + {{ 10, 133, 134, 882 }}, + {{ 138, 161, 394, 598 }}, + {{ 179, 688, 734, 937 }}, + {{ 22, 396, 497, 588 }}, + {{ 195, 649, 698, 969 }}, + {{ 275, 465, 668, 858 }}, + {{ 73, 260, 910, 929 }}, + {{ 202, 582, 723, 994 }}, + {{ 207, 447, 665, 826 }}, + {{ 252, 560, 565, 889 }}, + {{ 161, 354, 658, 962 }}, + {{ 202, 571, 751, 841 }}, + {{ 234, 418, 541, 844 }}, + {{ 133, 270, 386, 565 }}, + {{ 14, 212, 690, 955 }}, + {{ 65, 97, 349, 900 }}, + {{ 136, 200, 942, 959 }}, + {{ 144, 189, 270, 781 }}, + {{ 195, 644, 783, 897 }}, + {{ 169, 277, 551, 582 }}, + {{ 381, 489, 705, 1004 }}, + {{ 43, 50, 783, 1017 }}, + {{ 104, 287, 612, 638 }}, + {{ 6, 179, 680, 825 }}, + {{ 120, 208, 453, 491 }}, + {{ 194, 244, 985, 1010 }}, + {{ 173, 449, 457, 627 }}, + {{ 229, 365, 711, 734 }}, + {{ 132, 536, 760, 996 }}, + {{ 391, 835, 871, 884 }}, + {{ 345, 616, 688, 882 }}, + {{ 477, 488, 526, 901 }}, + {{ 95, 187, 240, 460 }}, + {{ 160, 183, 761, 790 }}, + {{ 210, 312, 804, 893 }}, + {{ 429, 569, 888, 923 }}, + {{ 46, 369, 426, 561 }}, + {{ 176, 328, 679, 825 }}, + {{ 130, 184, 758, 923 }}, + {{ 164, 304, 871, 886 }}, + {{ 27, 121, 516, 815 }}, + {{ 385, 465, 578, 649 }}, + {{ 101, 462, 720, 740 }}, + {{ 564, 630, 839, 1000 }}, + {{ 25, 253, 460, 659 }}, + {{ 33, 47, 527, 921 }}, + {{ 20, 231, 709, 798 }}, + {{ 394, 491, 921, 948 }}, + {{ 172, 181, 199, 403 }}, + {{ 511, 899, 925, 975 }}, + {{ 196, 256, 509, 697 }}, + {{ 436, 462, 627, 844 }}, + {{ 102, 677, 724, 939 }}, + {{ 290, 393, 436, 823 }}, + {{ 433, 536, 644, 873 }}, + {{ 127, 128, 831, 941 }}, + {{ 2, 260, 276, 712 }}, + {{ 68, 166, 255, 1020 }}, + {{ 382, 619, 965, 985 }}, + {{ 140, 226, 555, 660 }}, + {{ 110, 535, 584, 685 }}, + {{ 108, 538, 866, 929 }}, + {{ 276, 540, 719, 783 }}, + {{ 536, 651, 734, 949 }}, + {{ 137, 173, 264, 320 }}, + {{ 119, 227, 772, 856 }}, + {{ 158, 291, 595, 753 }}, + {{ 99, 256, 314, 450 }}, + {{ 469, 587, 625, 736 }}, + {{ 103, 379, 740, 937 }}, + {{ 429, 430, 530, 685 }}, + {{ 188, 221, 296, 980 }}, + {{ 103, 249, 552, 580 }}, + {{ 639, 697, 821, 1014 }}, + {{ 214, 387, 546, 595 }}, + {{ 177, 203, 508, 897 }}, + {{ 620, 656, 704, 958 }}, + {{ 463, 659, 815, 840 }}, + {{ 237, 441, 807, 845 }}, + {{ 2, 453, 484, 639 }}, + {{ 331, 646, 721, 735 }}, + {{ 168, 229, 490, 691 }}, + {{ 64, 660, 690, 925 }}, + {{ 81, 282, 618, 790 }}, + {{ 283, 522, 568, 867 }}, + {{ 293, 509, 766, 976 }}, + {{ 16, 365, 425, 1005 }}, + {{ 12, 89, 185, 588 }}, + {{ 458, 744, 920, 972 }}, + {{ 292, 331, 713, 815 }}, + {{ 4, 434, 860, 913 }}, + {{ 202, 388, 471, 787 }}, + {{ 225, 291, 781, 958 }}, + {{ 402, 860, 926, 935 }}, + {{ 195, 484, 659, 938 }}, + {{ 46, 195, 676, 844 }}, + {{ 482, 579, 850, 911 }}, + {{ 45, 200, 205, 943 }}, + {{ 274, 421, 684, 1016 }}, + {{ 339, 565, 726, 977 }}, + {{ 65, 102, 103, 771 }} + } }; + }; + + struct TableTungsten128x4 + { + static constexpr u8 max = 126; + + static constexpr std::array, 128> data + { { + {{ 10, 73, 91, 104 }}, + {{ 19, 29, 56, 80 }}, + {{ 7, 8, 79, 107 }}, + {{ 28, 88, 90, 99 }}, + {{ 4, 71, 76, 90 }}, + {{ 48, 80, 98, 100 }}, + {{ 19, 81, 82, 100 }}, + {{ 81, 112, 120, 121 }}, + {{ 19, 31, 36, 105 }}, + {{ 22, 92, 111, 113 }}, + {{ 63, 81, 101, 102 }}, + {{ 8, 27, 52, 89 }}, + {{ 44, 74, 106, 109 }}, + {{ 8, 17, 113, 117 }}, + {{ 20, 52, 74, 110 }}, + {{ 18, 33, 39, 81 }}, + {{ 23, 43, 80, 119 }}, + {{ 11, 33, 47, 108 }}, + {{ 51, 61, 65, 97 }}, + {{ 15, 47, 55, 59 }}, + {{ 4, 29, 32, 52 }}, + {{ 20, 74, 93, 95 }}, + {{ 16, 25, 81, 118 }}, + {{ 18, 49, 81, 97 }}, + {{ 8, 15, 23, 96 }}, + {{ 30, 41, 82, 123 }}, + {{ 21, 61, 87, 102 }}, + {{ 34, 54, 80, 84 }}, + {{ 64, 74, 88, 123 }}, + {{ 13, 33, 39, 89 }}, + {{ 10, 28, 75, 103 }}, + {{ 28, 36, 39, 58 }}, + {{ 79, 87, 98, 107 }}, + {{ 90, 99, 103, 107 }}, + {{ 25, 34, 48, 114 }}, + {{ 10, 43, 69, 89 }}, + {{ 7, 22, 32, 56 }}, + {{ 51, 85, 89, 105 }}, + {{ 18, 41, 63, 72 }}, + {{ 4, 22, 51, 111 }}, + {{ 100, 101, 110, 125 }}, + {{ 19, 58, 66, 102 }}, + {{ 16, 29, 32, 56 }}, + {{ 57, 85, 120, 121 }}, + {{ 4, 19, 61, 98 }}, + {{ 29, 52, 86, 115 }}, + {{ 8, 46, 89, 111 }}, + {{ 14, 24, 28, 100 }}, + {{ 19, 21, 29, 58 }}, + {{ 42, 44, 65, 113 }}, + {{ 5, 19, 53, 84 }}, + {{ 25, 29, 32, 109 }}, + {{ 24, 31, 57, 108 }}, + {{ 13, 46, 70, 104 }}, + {{ 79, 95, 123, 126 }}, + {{ 28, 109, 119, 123 }}, + {{ 58, 73, 122, 123 }}, + {{ 5, 32, 60, 75 }}, + {{ 2, 67, 75, 126 }}, + {{ 4, 14, 61, 111 }}, + {{ 27, 49, 68, 121 }}, + {{ 35, 105, 107, 110 }}, + {{ 31, 65, 106, 113 }}, + {{ 64, 67, 91, 101 }}, + {{ 6, 18, 55, 59 }}, + {{ 64, 71, 73, 109 }}, + {{ 27, 77, 97, 107 }}, + {{ 32, 50, 67, 86 }}, + {{ 38, 101, 109, 124 }}, + {{ 52, 85, 86, 116 }}, + {{ 28, 31, 66, 101 }}, + {{ 74, 75, 76, 81 }}, + {{ 3, 63, 70, 87 }}, + {{ 37, 39, 99, 113 }}, + {{ 11, 39, 91, 121 }}, + {{ 24, 59, 81, 115 }}, + {{ 6, 54, 65, 69 }}, + {{ 47, 113, 116, 121 }}, + {{ 61, 64, 80, 107 }}, + {{ 2, 11, 102, 109 }}, + {{ 9, 20, 37, 118 }}, + {{ 46, 73, 91, 112 }}, + {{ 19, 31, 109, 122 }}, + {{ 32, 62, 93, 123 }}, + {{ 11, 103, 121, 124 }}, + {{ 65, 74, 88, 91 }}, + {{ 8, 12, 40, 126 }}, + {{ 3, 46, 70, 78 }}, + {{ 24, 49, 51, 58 }}, + {{ 6, 48, 49, 111 }}, + {{ 7, 35, 73, 92 }}, + {{ 16, 19, 70, 93 }}, + {{ 16, 31, 45, 82 }}, + {{ 48, 53, 59, 70 }}, + {{ 14, 46, 50, 59 }}, + {{ 2, 7, 23, 106 }}, + {{ 87, 99, 101, 109 }}, + {{ 18, 46, 51, 99 }}, + {{ 57, 58, 91, 120 }}, + {{ 47, 65, 89, 101 }}, + {{ 4, 79, 102, 114 }}, + {{ 18, 24, 65, 124 }}, + {{ 8, 19, 55, 81 }}, + {{ 18, 46, 55, 121 }}, + {{ 2, 11, 31, 63 }}, + {{ 46, 65, 94, 108 }}, + {{ 23, 55, 68, 76 }}, + {{ 24, 45, 85, 107 }}, + {{ 54, 57, 104, 112 }}, + {{ 7, 32, 35, 63 }}, + {{ 19, 34, 59, 70 }}, + {{ 7, 11, 45, 112 }}, + {{ 22, 43, 81, 116 }}, + {{ 13, 19, 57, 80 }}, + {{ 18, 33, 85, 98 }}, + {{ 46, 93, 97, 124 }}, + {{ 57, 62, 69, 90 }}, + {{ 14, 62, 114, 119 }}, + {{ 26, 27, 74, 95 }}, + {{ 49, 60, 107, 123 }}, + {{ 30, 31, 34, 97 }}, + {{ 18, 32, 82, 112 }}, + {{ 82, 85, 118, 122 }}, + {{ 54, 87, 92, 99 }}, + {{ 7, 57, 112, 126 }}, + {{ 97, 105, 112, 120 }}, + {{ 54, 79, 81, 88 }}, + {{ 16, 22, 24, 125 }} + } }; + }; + +} \ No newline at end of file diff --git a/libOTe/TwoChooseOne/ConfigureCode.cpp b/libOTe/TwoChooseOne/ConfigureCode.cpp index 110227c..c206bb7 100644 --- a/libOTe/TwoChooseOne/ConfigureCode.cpp +++ b/libOTe/TwoChooseOne/ConfigureCode.cpp @@ -37,7 +37,7 @@ namespace osuCrypto u64& mRequestedNumOTs, u64& mNumPartitions, u64& mSizePer, - u64& mN2, + u64& mNoiseVecSize, u64& mN, EACode& mEncoder ) @@ -72,8 +72,8 @@ namespace osuCrypto mRequestedNumOTs = numOTs; mNumPartitions = getRegNoiseWeight(minDist, secParam); mSizePer = roundUpTo((numOTs * mScaler + mNumPartitions - 1) / mNumPartitions, 8); - mN2 = mSizePer * mNumPartitions; - mN = mN2 / mScaler; + mNoiseVecSize = mSizePer * mNumPartitions; + mN = mNoiseVecSize / mScaler; mEncoder.config(numOTs, numOTs * mScaler, w); } @@ -85,7 +85,7 @@ namespace osuCrypto u64& mRequestedNumOTs, u64& mNumPartitions, u64& mSizePer, - u64& mN2, + u64& mNoiseVecSize, u64& mN, ExConvCode& mEncoder ) @@ -112,8 +112,8 @@ namespace osuCrypto mRequestedNumOTs = numOTs; mNumPartitions = getRegNoiseWeight(minDist, secParam); mSizePer = roundUpTo((numOTs * mScaler + mNumPartitions - 1) / mNumPartitions, 8); - mN2 = mSizePer * mNumPartitions; - mN = mN2 / mScaler; + mNoiseVecSize = mSizePer * mNumPartitions; + mN = mNoiseVecSize / mScaler; mEncoder.config(numOTs, numOTs * mScaler, w, a, true); } @@ -205,7 +205,7 @@ namespace osuCrypto u64& mRequestedNumOTs, u64& mNumPartitions, u64& mSizePer, - u64& mN2, + u64& mNoiseVecSize, u64& mN, u64& mP, u64& mScaler) @@ -220,8 +220,8 @@ namespace osuCrypto mNumPartitions = getRegNoiseWeight(0.2, secParam); auto ss = (mP * scaler + mNumPartitions - 1) / mNumPartitions; mSizePer = roundUpTo(ss, 8); - mN2 = mSizePer * mNumPartitions; - mN = mN2 / scaler; + mNoiseVecSize = mSizePer * mNumPartitions; + mN = mNoiseVecSize / scaler; mScaler = scaler; } diff --git a/libOTe/TwoChooseOne/ConfigureCode.h b/libOTe/TwoChooseOne/ConfigureCode.h index 720e75d..e838375 100644 --- a/libOTe/TwoChooseOne/ConfigureCode.h +++ b/libOTe/TwoChooseOne/ConfigureCode.h @@ -18,8 +18,11 @@ namespace osuCrypto ExAcc40 = 7, // conservative // https://eprint.iacr.org/2023/882 - ExConv7x24 = 8, //fastest - ExConv21x24 = 9 // conservative. + ExConv7x24 = 8, //fast + ExConv21x24 = 9, // conservative. + + // experimental + Tungsten // very fast, based on turbo codes. Unknown min distance. }; inline std::ostream& operator<<(std::ostream& o, MultType m) @@ -48,6 +51,9 @@ namespace osuCrypto case osuCrypto::MultType::ExConv7x24: o << "ExConv7x24"; break; + case osuCrypto::MultType::Tungsten: + o << "Tungsten"; + break; default: throw RTE_LOC; break; @@ -76,7 +82,7 @@ namespace osuCrypto u64& mRequestedNumOTs, u64& mNumPartitions, u64& mSizePer, - u64& mN2, + u64& mNoiseVecSize, u64& mN, EACode& mEncoder ); @@ -89,7 +95,7 @@ namespace osuCrypto u64& mRequestedNumOTs, u64& mNumPartitions, u64& mSizePer, - u64& mN2, + u64& mNoiseVecSize, u64& mN, ExConvCode& mEncoder ); @@ -110,7 +116,7 @@ namespace osuCrypto u64& mRequestedNumOTs, u64& mNumPartitions, u64& mSizePer, - u64& mN2, + u64& mNoiseVecSize, u64& mN, u64& mP, u64& mScaler); @@ -121,8 +127,19 @@ namespace osuCrypto double& minDist) { if (mScaler == 2) - minDist = 0.2; // psuedo min dist + minDist = 0.2; // estimated psuedo min dist else throw RTE_LOC; // not impl } + + + inline void TungstenConfigure( + double mScaler, + double& minDist) + { + if (mScaler == 2) + minDist = 0.2; // estimated psuedo min dist + else + throw RTE_LOC; // not impl + } } \ No newline at end of file diff --git a/libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.cpp b/libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.cpp index c473459..9fa451c 100644 --- a/libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.cpp +++ b/libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.cpp @@ -13,6 +13,7 @@ #include #include "libOTe/Tools/QuasiCyclicCode.h" #include "libOTe/Tools/CoeffCtx.h" +#include "libOTe/Tools/TungstenCode/TungstenCode.h" namespace osuCrypto { @@ -213,17 +214,18 @@ namespace osuCrypto { mMalType = malType; mNumThreads = numThreads; + u64 secParam = 128; switch (mMultType) { case osuCrypto::MultType::QuasiCyclic: - QuasiCyclicConfigure(numOTs, 128, scaler, + QuasiCyclicConfigure(numOTs, secParam, scaler, mMultType, - mRequestedNumOts, + mRequestNumOts, mNumPartitions, mSizePer, - mN2, + mNoiseVecSize, mN, mP, mScaler); @@ -234,13 +236,26 @@ namespace osuCrypto case osuCrypto::MultType::ExAcc21: case osuCrypto::MultType::ExAcc40: - EAConfigure(numOTs, 128, mMultType, mRequestedNumOts, mNumPartitions, mSizePer, mN2, mN, mEAEncoder); + EAConfigure(numOTs, secParam, mMultType, mRequestNumOts, mNumPartitions, mSizePer, mNoiseVecSize, mN, mEAEncoder); break; case osuCrypto::MultType::ExConv7x24: case osuCrypto::MultType::ExConv21x24: - ExConvConfigure(numOTs, 128, mMultType, mRequestedNumOts, mNumPartitions, mSizePer, mN2, mN, mExConvEncoder); + ExConvConfigure(numOTs, secParam, mMultType, mRequestNumOts, mNumPartitions, mSizePer, mNoiseVecSize, mN, mExConvEncoder); break; + case osuCrypto::MultType::Tungsten: + { + double minDist; + mRequestNumOts = numOTs; + mN = roundUpTo(numOTs, 8); + TungstenConfigure(mScaler, minDist); + + mNumPartitions = getRegNoiseWeight(minDist, secParam); + mSizePer = std::max(4, roundUpTo(divCeil(mRequestNumOts * mScaler, mNumPartitions), 2)); + mNoiseVecSize = mSizePer * mNumPartitions; + + break; + } default: throw RTE_LOC; break; @@ -421,7 +436,7 @@ namespace osuCrypto configure(n, mScaler, mNumThreads, mMalType); } - if (n != mRequestedNumOts) + if (n != mRequestNumOts) throw std::invalid_argument("messages.size() > n"); if (mGen.hasBaseOts() == false) @@ -434,7 +449,7 @@ namespace osuCrypto gTimer.setTimePoint("recver.expand.start"); - mA.resize(mN2); + mA.resize(mNoiseVecSize); mC.resize(0); @@ -449,17 +464,17 @@ namespace osuCrypto if (mDebug) { - rT = MatrixView(mA.data(), mN2, 1); + rT = MatrixView(mA.data(), mNoiseVecSize, 1); MC_AWAIT(checkRT(chl, rT)); } compress(type); - mA.resize(mRequestedNumOts); + mA.resize(mRequestNumOts); if (mC.size()) { - mC.resize(mRequestedNumOts); + mC.resize(mRequestNumOts); } MC_END(); @@ -519,15 +534,15 @@ namespace osuCrypto span messages, ChoiceBitPacking type) { - if (choices.size() != mRequestedNumOts) + if (choices.size() != mRequestNumOts) throw RTE_LOC; - if ((u64)messages.size() != mRequestedNumOts) + if ((u64)messages.size() != mRequestNumOts) throw RTE_LOC; auto cIter = choices.begin(); //std::array hashBuffer; - auto n8 = mRequestedNumOts / 8 * 8; + auto n8 = mRequestNumOts / 8 * 8; auto m = &messages[0]; auto r = &mA[0]; @@ -606,7 +621,7 @@ namespace osuCrypto { // zero out the lsb of mA. We will store mC there. block mask = OneBlock ^ AllOneBlock; - auto m8 = mN2 / 8 * 8; + auto m8 = mNoiseVecSize / 8 * 8; auto r = mA.data(); for (u64 i = 0; i < m8; i += 8) { @@ -620,7 +635,7 @@ namespace osuCrypto r[7] = r[7] & mask; r += 8; } - for (u64 i = m8; i < mN2; ++i) + for (u64 i = m8; i < mNoiseVecSize; ++i) { mA[i] = mA[i] & mask; } @@ -668,6 +683,12 @@ namespace osuCrypto mExConvEncoder.setTimer(getTimer()); mExConvEncoder.dualEncode(mA.begin(), {}); break; + case osuCrypto::MultType::Tungsten: + { + experimental::TungstenCode encoder; + encoder.dualEncode(mA.begin(), {}); + break; + } default: throw RTE_LOC; break; @@ -678,8 +699,8 @@ namespace osuCrypto } else { - mC.resize(mN2); - std::memset(mC.data(), 0, mN2); + mC.resize(mNoiseVecSize); + std::memset(mC.data(), 0, mNoiseVecSize); auto cc = mC.data(); for (auto p : mS) cc[p] = 1; @@ -731,6 +752,13 @@ namespace osuCrypto mC.begin(), {}); break; + case osuCrypto::MultType::Tungsten: + { + experimental::TungstenCode encoder; + encoder.dualEncode(mA.begin(), {}); + encoder.dualEncode(mC.begin(), {}); + break; + } default: throw RTE_LOC; break; @@ -743,8 +771,8 @@ namespace osuCrypto void SilentOtExtReceiver::clear() { mN = 0; - mN2 = 0; - mRequestedNumOts = 0; + mNoiseVecSize = 0; + mRequestNumOts = 0; mSizePer = 0; mC = {}; diff --git a/libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.h b/libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.h index 0ac227e..12ed591 100644 --- a/libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.h +++ b/libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.h @@ -37,13 +37,13 @@ namespace osuCrypto u64 mP = 0; // the number of OTs being requested. - u64 mRequestedNumOts = 0; + u64 mRequestNumOts = 0; - // The dense vector size, this will be at least as big as mRequestedNumOts. + // The dense vector size, this will be at least as big as mRequestNumOts. u64 mN = 0; // The sparse vector size, this will be mN * mScaler. - u64 mN2 = 0; + u64 mNoiseVecSize = 0; // The scaling factor that the sparse vector will be compressed by. u64 mScaler = 2; diff --git a/libOTe/TwoChooseOne/Silent/SilentOtExtSender.cpp b/libOTe/TwoChooseOne/Silent/SilentOtExtSender.cpp index 73a927a..09a3417 100644 --- a/libOTe/TwoChooseOne/Silent/SilentOtExtSender.cpp +++ b/libOTe/TwoChooseOne/Silent/SilentOtExtSender.cpp @@ -11,6 +11,7 @@ #include #include "libOTe/Vole/Noisy/NoisyVoleReceiver.h" #include "libOTe/Tools/QuasiCyclicCode.h" +#include "libOTe/Tools/TungstenCode/TungstenCode.h" namespace osuCrypto { @@ -163,18 +164,19 @@ namespace osuCrypto { mMalType = malType; mNumThreads = numThreads; + u64 secParam = 128; switch (mMultType) { case osuCrypto::MultType::QuasiCyclic: - QuasiCyclicConfigure(numOTs, 128, scaler, + QuasiCyclicConfigure(numOTs, secParam, scaler, mMultType, mRequestNumOts, mNumPartitions, mSizePer, - mN2, + mNoiseVecSize, mN, mP, mScaler); @@ -185,13 +187,26 @@ namespace osuCrypto case osuCrypto::MultType::ExAcc21: case osuCrypto::MultType::ExAcc40: - EAConfigure(numOTs, 128, mMultType, mRequestNumOts, mNumPartitions, mSizePer, mN2, mN, mEAEncoder); + EAConfigure(numOTs, secParam, mMultType, mRequestNumOts, mNumPartitions, mSizePer, mNoiseVecSize, mN, mEAEncoder); break; case osuCrypto::MultType::ExConv7x24: case osuCrypto::MultType::ExConv21x24: - ExConvConfigure(numOTs, 128, mMultType, mRequestNumOts, mNumPartitions, mSizePer, mN2, mN, mExConvEncoder); + ExConvConfigure(numOTs, secParam, mMultType, mRequestNumOts, mNumPartitions, mSizePer, mNoiseVecSize, mN, mExConvEncoder); break; + case osuCrypto::MultType::Tungsten: + { + double minDist; + mRequestNumOts = numOTs; + mN = roundUpTo(numOTs, 8); + TungstenConfigure(mScaler, minDist); + + mNumPartitions = getRegNoiseWeight(minDist, secParam); + mSizePer = std::max(4, roundUpTo(divCeil(mRequestNumOts * mScaler, mNumPartitions), 2)); + mNoiseVecSize = mSizePer * mNumPartitions; + + break; + } default: throw RTE_LOC; break; @@ -214,7 +229,7 @@ namespace osuCrypto void SilentOtExtSender::clear() { mN = 0; - mN2 = 0; + mNoiseVecSize = 0; mRequestNumOts = 0; mSizePer = 0; mNumPartitions = 0; @@ -391,7 +406,7 @@ namespace osuCrypto mDelta = d; // allocate b - mB.resize(mN2); + mB.resize(mNoiseVecSize); delta.resize(1); delta[0] = mDelta; @@ -495,6 +510,12 @@ namespace osuCrypto mExConvEncoder.setTimer(getTimer()); mExConvEncoder.dualEncode(mB.begin(), {}); break; + case osuCrypto::MultType::Tungsten: + { + experimental::TungstenCode encoder; + encoder.dualEncode(mB.begin(), {}); + break; + } default: throw RTE_LOC; break; @@ -502,129 +523,6 @@ namespace osuCrypto } -// -// -// void SilentOtExtSender::randMulQuasiCyclic() -// { -//#ifdef ENABLE_BITPOLYMUL -// -// const u64 rows(128); -// auto nBlocks = mN / rows; -// auto n2Blocks = mN2 / rows; -// MatrixView rT(mB.data(), rows, n2Blocks); -// auto n64 = i64(nBlocks * 2); -// std::vector a(mScaler - 1); -// MatrixcModP1(128, nBlocks, AllocType::Uninitialized); -// -// std::unique_ptr brs(new ThreadBarrier[mScaler]); -// for (u64 i = 0; i < mScaler; ++i) -// brs[i].reset(mNumThreads); -// -// auto routine = [&](u64 index) -// { -// u64 j = 0; -// FFTPoly bPoly; -// FFTPoly cPoly; -// -// Matrixtt(1, 2 * nBlocks, AllocType::Uninitialized); -// auto temp128 = tt[0]; -// -// FFTPoly::DecodeCache cache; -// for (u64 s = index + 1; s < mScaler; s += mNumThreads) -// { -// auto a64 = spanCast(temp128).subspan(n64); -// PRNG pubPrng(toBlock(s)); -// pubPrng.get(a64.data(), a64.size()); -// a[s - 1].encode(a64); -// } -// -// if (index == 0) -// setTimePoint("sender.expand.qc.randGen"); -// -// brs[j++].decrementWait(); -// -// if (index == 0) -// setTimePoint("sender.expand.qc.randGenWait"); -// -// auto multAddReduce = [this, nBlocks, n64, &a, &bPoly, &cPoly, &temp128, &cache](span b128, span dest) -// { -// for (u64 s = 1; s < mScaler; ++s) -// { -// auto& aPoly = a[s - 1]; -// auto b64 = spanCast(b128).subspan(s * n64, n64); -// -// bPoly.encode(b64); -// -// if (s == 1) -// { -// cPoly.mult(aPoly, bPoly); -// } -// else -// { -// bPoly.multEq(aPoly); -// cPoly.addEq(bPoly); -// } -// } -// -// // decode c[i] and store it at t64Ptr -// cPoly.decode(spanCast(temp128), cache, true); -// -// for (u64 j = 0; j < nBlocks; ++j) -// temp128[j] = temp128[j] ^ b128[j]; -// -// // reduce s[i] mod (x^n - 1) and store it at cModP1[i] -// modp(dest, temp128, mP); -// -// }; -// -// for (u64 i = index; i < rows; i += mNumThreads) -// multAddReduce(rT[i], cModP1[i]); -// -// if (index == 0) -// setTimePoint("sender.expand.qc.mulAddReduce"); -// -// brs[j++].decrementWait(); -// -// -// std::array tpBuffer; -// auto numBlocks = (mRequestNumOts + 127) / 128; -// auto begin = index * numBlocks / mNumThreads; -// auto end = (index + 1) * numBlocks / mNumThreads; -// for (u64 i = begin; i < end; ++i) -// { -// u64 j = i * tpBuffer.size(); -// auto min = std::min(tpBuffer.size(), mN - j); -// -// for (u64 k = 0; k < tpBuffer.size(); ++k) -// tpBuffer[k] = cModP1(k, i); -// -// transpose128(tpBuffer); -// -// auto end = i * tpBuffer.size() + min; -// for (u64 k = 0; j < end; ++j, ++k) -// mB[j] = tpBuffer[k]; -// } -// -// if (index == 0) -// setTimePoint("sender.expand.qc.transposeXor"); -// }; -// -// std::vector thrds(mNumThreads - 1); -// for (u64 i = 0; i < thrds.size(); ++i) -// thrds[i] = std::thread(routine, i); -// -// routine(thrds.size()); -// -// for (u64 i = 0; i < thrds.size(); ++i) -// thrds[i].join(); -// -// -//#else -// std::cout << "bit poly mul is not enabled. Please recompile with ENABLE_BITPOLYMUL defined. " LOCATION << std::endl; -// throw RTE_LOC; -//#endif -// -// } } #endif \ No newline at end of file diff --git a/libOTe/TwoChooseOne/Silent/SilentOtExtSender.h b/libOTe/TwoChooseOne/Silent/SilentOtExtSender.h index 88ee73e..1c81376 100644 --- a/libOTe/TwoChooseOne/Silent/SilentOtExtSender.h +++ b/libOTe/TwoChooseOne/Silent/SilentOtExtSender.h @@ -81,9 +81,9 @@ namespace osuCrypto u64 mP = 0; // The sparse vector size, this will be mN * mScaler. - u64 mN2 = 0; + u64 mNoiseVecSize = 0; - // The dense vector size, this will be at least as big as mRequestedNumOts. + // The dense vector size, this will be at least as big as mRequestNumOts. u64 mN = 0; // The number of regular section of the sparse vector. diff --git a/libOTe/Vole/Silent/SilentVoleReceiver.h b/libOTe/Vole/Silent/SilentVoleReceiver.h index 1302492..6755c9d 100644 --- a/libOTe/Vole/Silent/SilentVoleReceiver.h +++ b/libOTe/Vole/Silent/SilentVoleReceiver.h @@ -27,6 +27,7 @@ #include "libOTe/Tools/QuasiCyclicCode.h" #include "libOTe/TwoChooseOne/Silent/SilentOtExtUtil.h" #include +#include namespace osuCrypto { @@ -295,6 +296,12 @@ namespace osuCrypto case MultType::QuasiCyclic: QuasiCyclicConfigure(mScaler, minDist); break; + case osuCrypto::MultType::Tungsten: + { + mRequestSize = roundUpTo(mRequestSize, 8); + TungstenConfigure(mScaler, minDist); + break; + } default: throw RTE_LOC; break; @@ -304,8 +311,6 @@ namespace osuCrypto mSizePer = std::max(4, roundUpTo(divCeil(mRequestSize * mScaler, mNumPartitions), 2)); mNoiseVecSize = mSizePer * mNumPartitions; - //std::cout << "n " << mRequestSize << " -> " << mNoiseVecSize << " = " << mSizePer << " * " << mNumPartitions << std::endl; - mGen.configure(mSizePer, mNumPartitions); } @@ -469,7 +474,7 @@ namespace osuCrypto configure(n, SilentBaseType::BaseExtend); } - if (mRequestSize != n) + if (mRequestSize < n) throw std::invalid_argument("n does not match the requested number of OTs via configure(...). " LOCATION); if (hasSilentBaseOts() == false) @@ -588,6 +593,14 @@ namespace osuCrypto #endif break; } + case osuCrypto::MultType::Tungsten: + { + experimental::TungstenCode encoder; + encoder.config(mRequestSize, mNoiseVecSize); + encoder.dualEncode(mA.begin(), mCtx); + encoder.dualEncode(mC.begin(), mCtx); + break; + } default: throw std::runtime_error("Code is not supported. " LOCATION); break; diff --git a/libOTe/Vole/Silent/SilentVoleSender.h b/libOTe/Vole/Silent/SilentVoleSender.h index 81fcce8..74e8309 100644 --- a/libOTe/Vole/Silent/SilentVoleSender.h +++ b/libOTe/Vole/Silent/SilentVoleSender.h @@ -25,6 +25,7 @@ #include #include #include +#include namespace osuCrypto { @@ -241,6 +242,12 @@ namespace osuCrypto case MultType::QuasiCyclic: QuasiCyclicConfigure(mScaler, minDist); break; + case osuCrypto::MultType::Tungsten: + { + mRequestSize = roundUpTo(mRequestSize, 8); + TungstenConfigure(mScaler, minDist); + break; + } default: throw RTE_LOC; break; @@ -345,7 +352,7 @@ namespace osuCrypto configure(n, SilentBaseType::BaseExtend); } - if (mRequestSize != n) + if (mRequestSize < n) throw std::invalid_argument("n does not match the requested number of OTs via configure(...). " LOCATION); if (mGen.hasBaseOts() == false) @@ -432,6 +439,13 @@ namespace osuCrypto break; } + case osuCrypto::MultType::Tungsten: + { + experimental::TungstenCode encoder; + encoder.config(mRequestSize, mNoiseVecSize); + encoder.dualEncode(mB.begin(), mCtx); + break; + } default: throw std::runtime_error("Code is not supported. " LOCATION); break; diff --git a/libOTe_Tests/SilentOT_Tests.cpp b/libOTe_Tests/SilentOT_Tests.cpp index e95bba7..d1a9d8c 100644 --- a/libOTe_Tests/SilentOT_Tests.cpp +++ b/libOTe_Tests/SilentOT_Tests.cpp @@ -193,8 +193,8 @@ void Tools_quasiCyclic_test(const oc::CLP& cmd) //auto mNumPartitions = getPartitions(scaler, mP, secParam); //auto ss = (mP * scaler + mNumPartitions - 1) / mNumPartitions; //mSizePer = roundUpTo(ss, 8); - //mN2 = mSizePer * mNumPartitions; - //mN = mN2 / scaler; + //mNoiseVecSize = mSizePer * mNumPartitions; + //mN = mNoiseVecSize / scaler; //mScaler = scaler; AlignedUnVector A(n), B(n), C(n); @@ -699,10 +699,10 @@ void OtExt_Silent_QuasiCyclic_Test(const oc::CLP& cmd) #endif } -void OtExt_Silent_Silver_Test(const oc::CLP& cmd) +void OtExt_Silent_Tungsten_Test(const oc::CLP& cmd) { -#if defined(ENABLE_SILENTOT) && defined(ENABLE_INSECURE_SILVER) +#if defined(ENABLE_SILENTOT) auto sockets = cp::LocalAsyncSocket::makePair(); @@ -720,18 +720,14 @@ void OtExt_Silent_Silver_Test(const oc::CLP& cmd) SilentOtExtSender sender; SilentOtExtReceiver recver; - sender.mMultType = MultType::slv5; - recver.mMultType = MultType::slv5; + sender.mMultType = MultType::Tungsten; + recver.mMultType = MultType::Tungsten; - //sender.mDebug = true; - //recver.mDebug = true; block delta = prng.get(); - //auto type = OTType::Correlated; for (auto n : nn) { - //block delta std::vector> msg2(n); std::vector msg1(n); BitVector choice(n); diff --git a/libOTe_Tests/SilentOT_Tests.h b/libOTe_Tests/SilentOT_Tests.h index 26ff014..3b7be3a 100644 --- a/libOTe_Tests/SilentOT_Tests.h +++ b/libOTe_Tests/SilentOT_Tests.h @@ -15,7 +15,7 @@ void OtExt_Silent_correlated_Test(const oc::CLP& cmd); void OtExt_Silent_inplace_Test(const oc::CLP& cmd); void OtExt_Silent_paramSweep_Test(const oc::CLP& cmd); void OtExt_Silent_QuasiCyclic_Test(const oc::CLP& cmd); -void OtExt_Silent_Silver_Test(const oc::CLP& cmd); +void OtExt_Silent_Tungsten_Test(const oc::CLP& cmd); void OtExt_Silent_baseOT_Test(const oc::CLP& cmd); void OtExt_Silent_mal_Test(const oc::CLP& cmd); @@ -23,4 +23,3 @@ void Tools_bitShift_test(const oc::CLP& cmd); void Tools_modp_test(const oc::CLP& cmd); void Tools_quasiCyclic_test(const oc::CLP& cmd); -void SilentOT_mul_Test(const oc::CLP& cmd); diff --git a/libOTe_Tests/TungstenCode_Tests.cpp b/libOTe_Tests/TungstenCode_Tests.cpp new file mode 100644 index 0000000..12608cf --- /dev/null +++ b/libOTe_Tests/TungstenCode_Tests.cpp @@ -0,0 +1,181 @@ +#include "cryptoTools/Common/CLP.h" +#include "libOTe/Tools/TungstenCode/TungstenCode.h" +#include "cryptoTools/Crypto/PRNG.h" +#include "libOTe/Tools/CoeffCtx.h" + +using namespace oc; +using namespace oc::experimental; +namespace tests_libOTe +{ + + + template< + typename Table, + typename T> + void accumulateBlock( + span x, + u64 i) + { + auto table = Table::data; + for (u64 j = 0; j < Table::data.size(); ++j, ++i) + { + if (i == x.size()) + return; + + x[(i + 1) % x.size()] ^= x[i]; + + for (u64 k = 0; k < table[j].size(); ++k) + { + auto d = (i + table[j][k]) % x.size(); + if (d != i) + x[d] ^= x[i]; + + } + } + } + + void TungstenCode_encode_test(const oc::CLP& cmd) + { + + auto K = cmd.getManyOr("k", { 256, 3328, 152336 }); + auto R = cmd.getManyOr("R", { 2.0 }); + + for (auto k : K) for (auto r : R) + { + + using F = block; + using Ctx = CoeffCtxGF128; + + Ctx ctx; + u64 n = k * r; + TungstenCode encoder; + + encoder.config(k, n); + + //std::iota(encoder.mPerm.mPerm.begin(), encoder.mPerm.mPerm.end(), 0); + //std::swap(encoder.mPerm.mPerm[0], encoder.mPerm.mPerm[1]); + + PRNG prng(CCBlock); + + std::vector x(n); + prng.get(x); + + + + + auto z = x; + { + + std::vector in(roundUpTo(n - k, encoder.ChunkSize)); + std::vector out(roundUpTo(n - k, encoder.ChunkSize)); + auto i = n - in.size(); + std::copy(x.begin() + i, x.end(), in.begin()); + + u64 tableSize = TableTungsten1024x4::data.size(); + + for (u64 j = 0; j <= encoder.mNumIter; ++j) + { + auto in2 = in; + auto in3 = in; + for (u64 i = 0; i < in.size(); i += tableSize) + { + accumulateBlock(in, i); + } + + TungstenNoop noop; + encoder.accumulate(in2.data(), nullptr, in.size(), noop, ctx); + + if (in2 != in) + throw RTE_LOC; + + if (j < encoder.mNumIter) + { + auto perm = encoder.mPerm.mPerm; + std::vector flags(perm.size()); + for (u64 p = 0; p < perm.size(); ++p) + { + if (std::exchange(flags[perm[p]], 1)) + throw RTE_LOC; + + for (u64 k = 0; k < encoder.ChunkSize; ++k) + out[perm[p] * encoder.ChunkSize + k] = in[p * encoder.ChunkSize + k]; + } + + + //for (u64 p = 0; p < std::min(10, z.size()); ++p) + //{ + // std::cout << p << " ti " << j << ": " << in3[p] << std::endl; + //} + //std::cout << "\n"; + encoder.mPerm.reset(); + std::vector out2(out.size()); + encoder.accumulate(in3.data(), out2.data(), in.size(), encoder.mPerm, ctx); + + + if (in3 != in) + throw RTE_LOC; + + //for (u64 p = 0; p < std::min(10, z.size()); ++p) + //{ + // std::cout << p << " to " <(20, z.size()); ++j) + //{ + // std::cout << j << " ft : " << in3[j] << " " << w[j] << std::endl; + //} + //std::cout << "\n\n"; + + TungstenAdder adder; + encoder.accumulate(in3.data(), w.data(), in.size(), adder, ctx); + w.resize(k); + if (w != z) + throw RTE_LOC; + + } + } + } + + auto y = x; + encoder.dualEncode(y.data(), ctx); + y.resize(k); + + if (z != y) + { + auto m = std::min(40, z.size()); + for (u64 p = 0; p < m; ++p) + { + std::cout << p << " " << (p / encoder.ChunkSize) << " " << z[p] << " " << y[p] << (z[p] != y[p] ? " <<<<<" : "") << std::endl; + } + for (u64 p = m; p < z.size(); ++p) + { + if(z[p] != y[p]) + std::cout << p << " " << (p / encoder.ChunkSize) << " " << z[p] << " " << y[p] << (z[p] != y[p] ? " <<<<<" : "") << std::endl; + } + throw RTE_LOC; + } + } + + } +} \ No newline at end of file diff --git a/libOTe_Tests/TungstenCode_Tests.h b/libOTe_Tests/TungstenCode_Tests.h new file mode 100644 index 0000000..6d8247c --- /dev/null +++ b/libOTe_Tests/TungstenCode_Tests.h @@ -0,0 +1,13 @@ +// © 2024 Peter Rindal. +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +#include "cryptoTools/Common/CLP.h" +namespace tests_libOTe +{ + void TungstenCode_encode_test(const oc::CLP& cmd); +} \ No newline at end of file diff --git a/libOTe_Tests/UnitTests.cpp b/libOTe_Tests/UnitTests.cpp index f2f1bb5..85cb614 100644 --- a/libOTe_Tests/UnitTests.cpp +++ b/libOTe_Tests/UnitTests.cpp @@ -15,6 +15,7 @@ #include "libOTe_Tests/EACode_Tests.h" #include "libOTe/Tools/LDPC/Mtx.h" #include "libOTe_Tests/Pprf_Tests.h" +#include "libOTe_Tests/TungstenCode_Tests.h" using namespace osuCrypto; namespace tests_libOTe @@ -43,6 +44,7 @@ namespace tests_libOTe tc.add("EACode_encode_basic_test ", EACode_encode_basic_test); tc.add("ExConvCode_encode_basic_test ", ExConvCode_encode_basic_test); + tc.add("TungstenCode_encode_test ", TungstenCode_encode_test); tc.add("Tools_Pprf_expandOne_test ", Tools_Pprf_expandOne_test); tc.add("Tools_Pprf_inter_test ", Tools_Pprf_inter_test); @@ -81,7 +83,7 @@ namespace tests_libOTe tc.add("OtExt_Silent_inplace_Test ", OtExt_Silent_inplace_Test); tc.add("OtExt_Silent_paramSweep_Test ", OtExt_Silent_paramSweep_Test); tc.add("OtExt_Silent_QuasiCyclic_Test ", OtExt_Silent_QuasiCyclic_Test); - tc.add("OtExt_Silent_Silver_Test ", OtExt_Silent_Silver_Test); + tc.add("OtExt_Silent_Tungsten_Test ", OtExt_Silent_Tungsten_Test); tc.add("OtExt_Silent_baseOT_Test ", OtExt_Silent_baseOT_Test); tc.add("OtExt_Silent_mal_Test ", OtExt_Silent_mal_Test); @@ -93,8 +95,9 @@ namespace tests_libOTe tc.add("DotExt_SoftSpokenMaliciousLeaky_Test ", DotExt_SoftSpokenMaliciousLeaky_Test); tc.add("Vole_Noisy_test ", Vole_Noisy_test); - tc.add("Vole_Silent_QuasiCyclic_test ", Vole_Silent_QuasiCyclic_test); tc.add("Vole_Silent_paramSweep_test ", Vole_Silent_paramSweep_test); + tc.add("Vole_Silent_Tungsten_test ", Vole_Silent_Tungsten_test); + tc.add("Vole_Silent_QuasiCyclic_test ", Vole_Silent_QuasiCyclic_test); tc.add("Vole_Silent_baseOT_test ", Vole_Silent_baseOT_test); tc.add("Vole_Silent_mal_test ", Vole_Silent_mal_test); tc.add("Vole_Silent_Rounds_test ", Vole_Silent_Rounds_test); diff --git a/libOTe_Tests/Vole_Tests.cpp b/libOTe_Tests/Vole_Tests.cpp index 52ced20..86a6fd7 100644 --- a/libOTe_Tests/Vole_Tests.cpp +++ b/libOTe_Tests/Vole_Tests.cpp @@ -192,7 +192,7 @@ void Vole_Silent_paramSweep_test(const oc::CLP& cmd) void Vole_Silent_QuasiCyclic_test(const oc::CLP& cmd) { -#if defined(ENABLE_SILENTOT) && defined(ENABLE_BITPOLYMUL) +#if defined(ENABLE_BITPOLYMUL) auto debug = cmd.isSet("debug"); for (u64 n : {128, 333}) Vole_Silent_test_impl(n, MultType::QuasiCyclic, debug, false, false); @@ -200,6 +200,12 @@ void Vole_Silent_QuasiCyclic_test(const oc::CLP& cmd) throw UnitTestSkipped("ENABLE_BITPOLYMUL not defined." LOCATION); #endif } +void Vole_Silent_Tungsten_test(const oc::CLP& cmd) +{ + auto debug = cmd.isSet("debug"); + for (u64 n : {128, 33341}) + Vole_Silent_test_impl(n, MultType::Tungsten, debug, false, false); +} void Vole_Silent_baseOT_test(const oc::CLP& cmd) diff --git a/libOTe_Tests/Vole_Tests.h b/libOTe_Tests/Vole_Tests.h index 664ace3..ea44bb8 100644 --- a/libOTe_Tests/Vole_Tests.h +++ b/libOTe_Tests/Vole_Tests.h @@ -9,8 +9,9 @@ #include void Vole_Noisy_test(const oc::CLP& cmd); -void Vole_Silent_QuasiCyclic_test(const oc::CLP& cmd); void Vole_Silent_paramSweep_test(const oc::CLP& cmd); +void Vole_Silent_QuasiCyclic_test(const oc::CLP& cmd); +void Vole_Silent_Tungsten_test(const oc::CLP& cmd); void Vole_Silent_baseOT_test(const oc::CLP& cmd); void Vole_Silent_mal_test(const oc::CLP& cmd); void Vole_Silent_Rounds_test(const oc::CLP& cmd);