Skip to content

Commit f332487

Browse files
jlhcrawfordhamishunesteffin
authored andcommitted
ContextBuilder
Co-authored-by: Hamish Hunt <[email protected]> Co-authored-by: Enrico Steffinlongo <[email protected]>
1 parent bfbac62 commit f332487

File tree

8 files changed

+904
-43
lines changed

8 files changed

+904
-43
lines changed

include/helib/Context.h

Lines changed: 320 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <helib/powerful.h>
2424
#include <helib/apiAttributes.h>
2525
#include <helib/range.h>
26+
#include <helib/scheme.h>
2627

2728
#include <NTL/Lazy.h>
2829

@@ -72,13 +73,13 @@ inline double lweEstimateSecurity(int n, double log2AlphaInv, int hwt)
7273
if (hwt == 0) { // dense keys
7374
slope = 3.8;
7475
consterm = -20;
75-
} else if (idx < numWghts - 1) {
76+
} else if (idx < numWghts - 1) {
7677
// estimate prms on a line from prms[i] to prms[i+1]
7778
// how far into this interval
7879
double a = double(hwt - hwgts[idx]) / (hwgts[idx + 1] - hwgts[idx]);
7980
slope = slopes[idx] + a * (slopes[idx + 1] - slopes[idx]);
8081
consterm = cnstrms[idx] + a * (cnstrms[idx + 1] - cnstrms[idx]);
81-
} else {
82+
} else {
8283
// Use the params corresponding to largest weight (450 above)
8384
slope = slopes[numWghts - 1];
8485
consterm = cnstrms[numWghts - 1];
@@ -387,6 +388,17 @@ class Context
387388
const std::vector<long>& gens = std::vector<long>(),
388389
const std::vector<long>& ords = std::vector<long>());
389390

391+
// FIXME: This is a temporary fix to allow proper copy of the context.
392+
// Without the fixes there would be discrepancies between context's zMStar and
393+
// alMod const reference one.
394+
// TODO: Add doxygen comments to the following methods.
395+
~Context() = default;
396+
Context(const Context& other);
397+
Context(Context&& other);
398+
// Deleted assignment operators.
399+
Context& operator=(const Context& other) = delete;
400+
Context& operator=(Context&& other) = delete;
401+
390402
void makeBootstrappable(const NTL::Vec<long>& mvec,
391403
long skWht = 0,
392404
bool build_cache = false,
@@ -596,6 +608,7 @@ void readContextBaseBinary(std::istream& s,
596608
unsigned long& r,
597609
std::vector<long>& gens,
598610
std::vector<long>& ords);
611+
599612
std::unique_ptr<Context> buildContextFromBinary(std::istream& str);
600613
void readContextBinary(std::istream& str, Context& context);
601614

@@ -616,10 +629,315 @@ void buildModChain(Context& context,
616629
long skHwt = 0,
617630
long resolution = 3,
618631
long bitsInSpecialPrimes = 0);
632+
619633
// should be called if after you build the mod chain in some way
620634
// *other* than calling buildModChain.
621635
void endBuildModChain(Context& context);
622636

637+
// Forward declaration of ContextBuilder
638+
template <typename SCHEME>
639+
class ContextBuilder;
640+
641+
/**
642+
* @brief `ostream` operator for serializing the `ContextBuilder` object.
643+
* @tparam SCHEME The encryption scheme to be used, must be `BGV` or `CKKS`.
644+
* @param os Reference to the output stream.
645+
* @param cb The `ContextBuilder` object to serialize.
646+
* @return Reference to the `std::ostream`
647+
**/
648+
template <typename SCHEME>
649+
std::ostream& operator<<(std::ostream& os, const ContextBuilder<SCHEME>& cb);
650+
651+
/**
652+
* @class ContextBuilder
653+
* @brief Builder to help construct a context.
654+
* @tparam SCHEME The encryption scheme to be used, must be `BGV` or `CKKS`.
655+
**/
656+
template <typename SCHEME>
657+
class ContextBuilder
658+
{
659+
static_assert(std::is_same<SCHEME, CKKS>::value ||
660+
std::is_same<SCHEME, BGV>::value,
661+
"Can only create context object parameterized by the crypto "
662+
"scheme (CKKS or BGV)");
663+
664+
private:
665+
// Default values by scheme.
666+
struct default_values;
667+
668+
// General parameters
669+
std::vector<long> gens_;
670+
std::vector<long> ords_;
671+
long m_ = default_values::m; // BGV: 3, CKKS: 4
672+
long p_ = default_values::p; // BGV: 2, CKKS: -1
673+
long r_ = default_values::r; // BGV: Hensel lifting = 1,
674+
// CKKS: Precision = 20
675+
long c_ = 3;
676+
677+
// Modulus chain params
678+
long bits_ = 300;
679+
long skHwt_ = 0;
680+
long resolution_ = 3;
681+
long bitsInSpecialPrimes_ = 0;
682+
bool buildModChainFlag_ = true; // Default build the modchain.
683+
684+
// Boostrap params (BGV only)
685+
NTL::Vec<long> mvec_;
686+
bool buildCacheFlag_ = false;
687+
bool thickFlag_ = false;
688+
bool bootstrappableFlag_ = false; // Default not boostrappable.
689+
690+
public:
691+
/**
692+
* @brief Sets `m` the order of the cyclotomic polynomial.
693+
* @param m The order of the cyclotomic polynomial.
694+
* @return Reference to this `ContextBuilder` object.
695+
**/
696+
ContextBuilder& m(long m)
697+
{
698+
m_ = m;
699+
return *this;
700+
}
701+
702+
/**
703+
* @brief Sets `p` the prime number of the ciphertext space.
704+
* @param p The prime number of the plaintext space.
705+
* @return Reference to the `ContextBuilder` object.
706+
* @note Only exists when the `SCHEME` is `BGV`.
707+
**/
708+
template <typename S = SCHEME,
709+
std::enable_if_t<std::is_same<S, BGV>::value>* = nullptr>
710+
ContextBuilder& p(long p)
711+
{
712+
p_ = p;
713+
return *this;
714+
}
715+
716+
/**
717+
* @brief Sets `r` the Hensel lifting parameter.
718+
* @param r The Hensel lifting parameter.
719+
* @return Reference to the `ContextBuilder` object.
720+
* @note Only exists when the `SCHEME` is `BGV`.
721+
**/
722+
template <typename S = SCHEME,
723+
std::enable_if_t<std::is_same<S, BGV>::value>* = nullptr>
724+
ContextBuilder& r(long r)
725+
{
726+
r_ = r;
727+
return *this;
728+
}
729+
730+
/**
731+
* @brief Sets `precision` the bit precision parameter.
732+
* @param precision The bit precision parameter.
733+
* @return Reference to the `ContextBuilder` object.
734+
* @note Only exists when the `SCHEME` is `CKKS`.
735+
**/
736+
template <typename S = SCHEME,
737+
std::enable_if_t<std::is_same<S, CKKS>::value>* = nullptr>
738+
ContextBuilder& precision(long precision)
739+
{
740+
r_ = precision;
741+
return *this;
742+
}
743+
744+
/**
745+
* @brief Sets `c` the number of columns (a.k.a. digits) in the key switching
746+
* matrices.
747+
* @param c The number of columns in the key switching matrix.
748+
* @return Reference to the `ContextBuilder` object.
749+
**/
750+
ContextBuilder& c(long c)
751+
{
752+
c_ = c;
753+
return *this;
754+
}
755+
756+
/**
757+
* @brief Sets `gens` the generators of the `ZMStar` group.
758+
* @param gens A `std::vector` containing the generators.
759+
* @return Reference to the `ContextBuilder` object.
760+
**/
761+
ContextBuilder& gens(const std::vector<long>& gens)
762+
{
763+
gens_ = gens;
764+
return *this;
765+
}
766+
767+
/**
768+
* @brief Sets `ords` the order of the corresponding generators in `gens` in
769+
* `ZmStar`.
770+
* @param ords A `std::vector` containing the orders of `gens`. The order
771+
* taken is the absolute value; a negative in `ords` represents a bad
772+
* dimension.
773+
* @return Reference to the `ContextBuilder` object.
774+
**/
775+
ContextBuilder& ords(const std::vector<long>& ords)
776+
{
777+
ords_ = ords;
778+
return *this;
779+
}
780+
781+
/**
782+
* @brief Sets the bit size of the primes in the modulus chain.
783+
* @param bits How many bits to make the modulus chain.
784+
* @return Reference to the `ContextBuilder` object.
785+
* @note The actual bit size that is set is typically higher than requested.
786+
**/
787+
ContextBuilder& bits(long bits)
788+
{
789+
bits_ = bits;
790+
return *this;
791+
}
792+
793+
/**
794+
* @brief Sets the secret key Hamming weight.
795+
* @param bits The secret key Hamming weight.
796+
* @return Reference to the `ContextBuilder` object.
797+
* @note If the Hamming weight is `0` (default) then a "dense" key will be
798+
* generated.
799+
**/
800+
ContextBuilder& skHwt(long skHwt)
801+
{
802+
skHwt_ = skHwt;
803+
return *this;
804+
}
805+
806+
/**
807+
* @brief Sets the resolution for the modulus chain.
808+
* @param bits How many bit size of resolution.
809+
* @return Reference to the `ContextBuilder` object.
810+
**/
811+
ContextBuilder& resolution(long bits)
812+
{
813+
resolution_ = bits;
814+
return *this;
815+
}
816+
817+
/**
818+
* @brief Sets the bit size of the special primes in the modulus chain.
819+
* @param bits The bit size of the special primes in the modulus chain.
820+
* @return Reference to this `ContextBuilder` object.
821+
**/
822+
ContextBuilder& bitsInSpecialPrimes(long bits)
823+
{
824+
bitsInSpecialPrimes_ = bits;
825+
return *this;
826+
}
827+
828+
/**
829+
* @brief Sets a flag determining whether the modulus chain will be built.
830+
* @param `yesno` A `bool` to determine whether the modulus chain should be
831+
* built.
832+
* @return Reference to the `ContextBuilder` object.
833+
* @note `ContextBuilder` by default will build the modulus chain.
834+
**/
835+
ContextBuilder& buildModChain(bool yesno)
836+
{
837+
buildModChainFlag_ = yesno;
838+
return *this;
839+
}
840+
841+
/**
842+
* @brief Sets `mvec` the unique primes which are factors of `m`.
843+
* @param mvec An `NTL::Vec` of primes factors.
844+
* @return Reference to the `ContextBuilder` object.
845+
* @note Only exists when the `SCHEME` is `BGV`.
846+
**/
847+
template <typename S = SCHEME,
848+
std::enable_if_t<std::is_same<S, BGV>::value>* = nullptr>
849+
ContextBuilder& mvec(const NTL::Vec<long>& mvec)
850+
{
851+
mvec_ = mvec;
852+
return *this;
853+
}
854+
855+
/**
856+
* @brief Sets boostrapping to be `thin`.
857+
* @return Reference to the `ContextBuilder` object.
858+
* @note Only exists when the `SCHEME` is `BGV`.
859+
**/
860+
template <typename S = SCHEME,
861+
std::enable_if_t<std::is_same<S, BGV>::value>* = nullptr>
862+
ContextBuilder& thinboot()
863+
{
864+
thickFlag_ = false;
865+
return *this;
866+
}
867+
868+
/**
869+
* @brief Sets boostrapping to be `thick`.
870+
* @return Reference to the `ContextBuilder` object.
871+
* @note Only exists when the `SCHEME` is `BGV`.
872+
**/
873+
template <typename S = SCHEME,
874+
std::enable_if_t<std::is_same<S, BGV>::value>* = nullptr>
875+
ContextBuilder& thickboot()
876+
{
877+
thickFlag_ = true;
878+
return *this;
879+
}
880+
881+
/**
882+
* @brief Sets flag to choose that the cache for boostrapping will be
883+
* built.
884+
* @param yesno A `bool` to determine whether the cache is built.
885+
* @return Reference to the `ContextBuilder` object.
886+
* @note @note Only exists when the `SCHEME` is `BGV`.
887+
**/
888+
template <typename S = SCHEME,
889+
std::enable_if_t<std::is_same<S, BGV>::value>* = nullptr>
890+
ContextBuilder& buildCache(bool yesno)
891+
{
892+
buildCacheFlag_ = yesno;
893+
return *this;
894+
}
895+
896+
/**
897+
* @brief Sets a flag determining if the context will be bootstrappable.
898+
* @param yesno A `bool` to determine whether the context will be
899+
* bootstrappable.
900+
* @return Reference to this `ContextBuilder` object.
901+
* @note `ContextBuilder` by default will not be bootstrappable.
902+
* @note Only exists when the `SCHEME` is `BGV`.
903+
**/
904+
template <typename S = SCHEME,
905+
std::enable_if_t<std::is_same<S, BGV>::value>* = nullptr>
906+
ContextBuilder& bootstrappable(bool yesno)
907+
{
908+
bootstrappableFlag_ = yesno;
909+
return *this;
910+
}
911+
912+
/**
913+
* @brief Builds a `Context` object from the arguments stored in the
914+
* `ContextBuilder` object.
915+
* @return A `Context` object.
916+
**/
917+
Context build() const;
918+
919+
friend std::ostream& operator<<<SCHEME>(std::ostream& os,
920+
const ContextBuilder& cb);
921+
};
922+
923+
// Default BGV values
924+
template <>
925+
struct ContextBuilder<BGV>::default_values
926+
{
927+
static constexpr long m = 3;
928+
static constexpr long p = 2;
929+
static constexpr long r = 1;
930+
};
931+
932+
// Default CKKS values
933+
template <>
934+
struct ContextBuilder<CKKS>::default_values
935+
{
936+
static constexpr long m = 4;
937+
static constexpr long p = -1;
938+
static constexpr long r = 20;
939+
};
940+
623941
///@}
624942
// Should point to the "current" context
625943
extern Context* activeContext;

0 commit comments

Comments
 (0)