Low-Level Interface¶
In the following we will explain the basics of the C++ interface by
walking trough Utils/paper-example.cpp
.
template<class T>
void run(char** argv, int prime_length);
MP-SPDZ heavily uses templating to allow to reuse code between
different protocols. run()
is a simple example of this. The
entire virtual machine in the Processor
directory is built on
the same principle. The central type is a type representing a share in
a particular type.
// bit length of prime
const int prime_length = 128;
// compute number of 64-bit words needed
const int n_limbs = (prime_length + 63) / 64;
Computation modulo a prime requires to fix the number of limbs (64-bit words) at compile time. This allows for optimal memory usage and computation.
if (protocol == "MASCOT")
run<Share<gfp_<0, n_limbs>>>(argv, prime_length);
else if (protocol == "CowGear")
run<CowGearShare<gfp_<0, n_limbs>>>(argv, prime_length);
Share types for computation module a prime (and in
\(\mathrm{GF}(2^n)\)) generally take one parameter for the
computation domain. gfp_
in turn takes two parameters, a
counter and the number of limbs. The counter allows to use several
instances with different parameters. It can be chosen freely, but the
convention is to use 0 for the online phase and 1 for the offline
phase where required.
else if (protocol == "SPDZ2k")
run<Spdz2kShare<64, 64>>(argv, 0);
Share types for computation modulo a power of two simply take the exponent as parameter, and some take an additional security parameter.
int my_number = atoi(argv[1]);
int n_parties = atoi(argv[2]);
int port_base = 9999;
Names N(my_number, n_parties, "localhost", port_base);
All implemented protocols require point-to-point connections between
all parties. Names
objects represent a setup of hostnames and
IPs used to set up the actual
connections. The chosen initialization provides a way where
every party connects to party 0 on a specified location (localhost in
this case), which then broadcasts the locations of all parties. The
base port number is used to derive the port numbers for the parties to
listen on (base + party number). See the the Names
class for
other possibilities such as a text file containing hostname and port
number for each party.
CryptoPlayer P(N);
The networking setup is used to set up the actual
connections. CryptoPlayer
uses encrypted connection while
PlainPlayer
does not. If you use several instances (for
several threads for example), you must use an integer identifier as
the second parameter, which must differ from any other by at least the
number of parties.
ProtocolSetup<T> setup(P, prime_length);
We have to use a specific prime for computation modulo a prime. This deterministically generates one of the desired length if necessary. For computation modulo a power of two, this does not do anything. Some protocols use an information-theoretic tag that is constant throughout the protocol. This code reads it from storage if available or generates a fresh one otherwise.
ProtocolSet<T> set(P, setup);
auto& input = set.input;
auto& protocol = set.protocol;
auto& output = set.output;
The ProtocolSet
contains one instance for every essential
protocol step.
int n = 1000;
vector<T> a(n), b(n);
T c;
typename T::clear result;
Remember that T
stands for a share in the protocol. The
derived type T::clear
stands for the cleartext domain. Share
types support linear operations such as addition, subtraction, and
multiplication with a constant. Use T::constant()
to convert a
constant to a share type.
input.reset_all(P);
for (int i = 0; i < n; i++)
input.add_from_all(i);
input.exchange();
for (int i = 0; i < n; i++)
{
a[i] = input.finalize(0);
b[i] = input.finalize(1);
}
The interface for all protocols proceeds in four stages:
Initialization. This is required to initialize and reset data structures in consecutive use.
Local data preparation
Communication
Output extraction
This blueprint allows for a minimal number of communication rounds.
protocol.init_dotprod(&processor);
for (int i = 0; i < n; i++)
protocol.prepare_dotprod(a[i], b[i]);
protocol.next_dotprod();
protocol.exchange();
c = protocol.finalize_dotprod(n);
The initialization of the multiplication sets the preprocessing and
output instances to use in Beaver multiplication. next_dotprod()
separates dot products in the data preparation phase.
set.check();
Some protocols require a check of all multiplications up to a certain point. To guarantee that outputs do not reveal secret information, it has to be run before using the output protocol.
output.init_open(P);
output.prepare_open(c);
output.exchange(P);
result = output.finalize_open();
cout << "result: " << result << endl;
output.Check(P);
The output protocol follows the same blueprint as the multiplication protocol.
set.check();
Some output protocols require an additional to guarantee the correctness of outputs.
Thread Safety¶
The low-level interface generally isn’t thread-safe. In particular,
you should only use one instance of ProtocolSetup
in the
whole program, and you should use only one instance of
CryptoPlayer
/PlainPlayer
and ProtocolSet
per thread.
Domain Types¶
|
Computation modulo a prime. |
|
Computation modulo \(2^K\). This is not a field. |
|
\(GF(2^n)\). |
Protocol Setup¶
-
template<class T>
class ProtocolSetup¶ Global setup for an arithmetic share type
Subclassed by MixedProtocolSetup< T >
Public Functions
Public Static Functions
-
static inline void set_batch_size(size_t batch_size)¶
Set how much preprocessing is produced at once.
-
static inline void set_batch_size(size_t batch_size)¶
-
template<class T>
class ProtocolSet¶ Input, multiplication, and output protocol instance for an arithmetic share type
Public Functions
-
inline ProtocolSet(Player &P, const ProtocolSetup<T> &setup)¶
- Parameters
P – communication instance
setup – one-time setup instance
-
inline void check()¶
Run all protocol checks
-
inline ProtocolSet(Player &P, const ProtocolSetup<T> &setup)¶
-
template<class T>
class BinaryProtocolSetup¶ Global setup for a binary share type
-
template<class T>
class BinaryProtocolSet¶ Input, multiplication, and output protocol instance for a binary share type
Public Functions
-
inline BinaryProtocolSet(Player &P, const BinaryProtocolSetup<T> &setup)¶
- Parameters
P – communication instance
setup – one-time setup instance
-
inline void check()¶
Run all protocol checks
-
inline BinaryProtocolSet(Player &P, const BinaryProtocolSetup<T> &setup)¶
-
template<class T>
class MixedProtocolSetup : public ProtocolSetup<T>¶ Global setup for an arithmetic share type and the corresponding binary one
-
template<class T>
class MixedProtocolSet¶ Input, multiplication, and output protocol instance for an arithmetic share type and the corresponding binary one
Public Functions
-
inline MixedProtocolSet(Player &P, const MixedProtocolSetup<T> &setup)¶
- Parameters
P – communication instance
setup – one-time setup instance
-
inline void check()¶
Run all protocol checks
-
inline MixedProtocolSet(Player &P, const MixedProtocolSetup<T> &setup)¶
Protocol Interfaces¶
-
template<class T>
class ProtocolBase¶ Abstract base class for multiplication protocols
Subclassed by Replicated< T >
Public Functions
-
inline virtual void init(Preprocessing<T>&, typename T::MAC_Check&)¶
Initialize protocol if needed (repeated call possible)
-
virtual void init_mul() = 0¶
Initialize multiplication round.
-
virtual void prepare_mul(const T &x, const T &y, int n = -1) = 0¶
Schedule multiplication of operand pair.
-
virtual void exchange() = 0¶
Run multiplication protocol.
-
inline void init_dotprod()¶
Initialize dot product round.
-
inline void next_dotprod()¶
Finish dot product.
-
inline virtual void init(Preprocessing<T>&, typename T::MAC_Check&)¶
-
template<class T>
class InputBase¶ Abstract base for input protocols
Subclassed by Input< T >
Public Functions
-
virtual void reset(int player) = 0¶
Initialize input round for
player
-
void reset_all(PlayerBase &P)¶
Initialize input round for all players.
-
virtual void add_mine(const typename T::open_type &input, int n_bits = -1) = 0¶
Schedule input from me.
-
virtual void add_other(int player, int n_bits = -1) = 0¶
Schedule input from other player.
-
void add_from_all(const typename T::open_type &input, int n_bits = -1)¶
Schedule input from all players.
-
virtual void exchange()¶
Run input protocol for all players.
-
virtual void reset(int player) = 0¶
-
template<class T>
class MAC_Check_Base¶ Abstract base class for opening protocols
-
template<class T>
class Preprocessing : public PrepBase¶ Abstract base class for preprocessing
Subclassed by BufferPrep< T >, Sub_Data_Files< T >
-
template<class T>
class BufferPrep : public Preprocessing<T>¶ Abstract base class for live preprocessing
Subclassed by BitPrep< T >
Public Functions
Domain Reference¶
-
template<int X, int L>
class gfp_ : public ValueInterface¶ Type for values in a field defined by integers modulo a prime in a specific range for fixed storage. It supports basic arithmetic operations and bit-wise operations. The latter use the canonical representation in the range
[0, p-1]
.X
is a counter to allow several moduli being used at the same time.L
is the number of 64-bit limbs, that is, the prime has to have bit length in[64*L-63, 64*L]
. Seegfpvar_
for a more flexible alternative. Convert tobigint
to access the canonical integer representation.Public Functions
-
inline gfp_()¶
Initialize to zero.
-
inline gfp_(const mpz_class &x)¶
Convert from integer without range restrictions.
-
template<int Y>
gfp_(const gfp_<Y, L> &x)¶ Convert from different domain via canonical integer representation.
-
inline void randomize(PRNG &G, int n = -1)¶
Sample with uniform distribution.
- Parameters
G – randomness generator
n – (unused)
-
inline void pack(octetStream &o, int n = -1) const¶
Append to buffer in native format.
- Parameters
o – buffer
n – (unused)
-
inline void unpack(octetStream &o, int n = -1)¶
Read from buffer in native format
- Parameters
o – buffer
n – (unused)
Public Static Functions
-
static void init_field(const bigint &p, bool mont = true)¶
Initialize the field.
- Parameters
p – prime modulus
mont – whether to use Montgomery representation
-
static void init_default(int lgp, bool mont = true)¶
Initialize the field to a prime of a given bit length.
- Parameters
lgp – bit length
mont – whether to use Montgomery representation
-
inline gfp_()¶
-
template<int X, int L>
class gfpvar_¶ Type for values in a field defined by integers modulo a prime up to a certain length for fixed storage.
X
is a counter to allow several moduli being used at the same time.L
is the maximum number of 64-bit limbs, that is, the prime has to have bit length at most64*L
. The interface replicatesgfp_
.
-
template<int K>
class Z2 : public ValueInterface¶ Type for values in the ring defined by the integers modulo
2^K
representing[0, 2^K-1]
. It supports arithmetic, bit-wise, and output streaming operations. It does not need initialization becauseK
completely defines the domain.Subclassed by SignedZ2< K >
Public Functions
-
inline Z2()¶
Initialize to zero.
-
template<int L>
inline Z2(const Z2<L> &x)¶ Convert from different domain via the canonical integer representation.
-
inline mp_limb_t get_limb(int i) const¶
Get 64-bit part.
- Parameters
i – return word containing 64*i- to 64*i+63-least significant bits
-
Z2 sqrRoot()¶
Deterministic square root for values with least significate bit 1. Raises an exception otherwise.
-
void randomize(PRNG &G, int n = -1)¶
Sample with uniform distribution.
- Parameters
G – randomness generator
n – (unused)
-
void pack(octetStream &o, int = -1) const¶
Append to buffer in native format.
- Parameters
o – buffer
n – (unused)
-
void unpack(octetStream &o, int n = -1)¶
Read from buffer in native format
- Parameters
o – buffer
n – (unused)
-
inline Z2()¶
-
template<int K>
class SignedZ2 : public Z2<K>¶ Type for values in the ring defined by the integers modulo
2^K
representing[-2^(K-1), 2^(K-1)-1]
. It supports arithmetic, bit-wise, comparison, and output streaming operations. It does not need initialization becauseK
completely defines the domain.
The following is not used as a domain, but it helps using the above types,
in particular gfp_<X, L>
and gfpvar_<X, L>
.
-
class bigint : public mpz_class¶
Type for arbitrarily large integers. This is a sub-class of
mpz_class
from GMP. As such, it implements all integers operations and input/output via C++ streams. In addition, theget_ui()
member function allows retrieving the least significant 64 bits.Public Functions
-
inline bigint()¶
Initialize to zero.
-
template<int X, int L>
bigint(const gfp_<X, L> &x)¶ Convert to canonical representation as non-negative number.
-
template<int X, int L>
bigint(const gfpvar_<X, L> &x)¶ Convert to canonical representation as non-negative number.
-
inline bigint()¶