Adding a Protocol¶
In order to illustrate how to create a virtual machine for a new protocol, we have created one with blanks to be filled in. It is defined in the following files:
Contains the main function.
NoShareclass, which is supposed to hold one share.
NoSharetakes the cleartext type as a template parameter.
Contains a number of classes representing instances of protocols:
NoLivePrepclass, representing a preprocessing instance.
The number of blanks can be overwhelming. We therefore recommend the
following approach to get started. If the desired protocol resembles
one that is already implemented, you can check its code for
inspiration. The main function of
<protocol>-party.x can be found
Machines/<protocol>-party.cpp, which in turns contains the name
of the share class. For example
Machines/replicated-ring-party.cpp, which refers to
Protocols/Rep3Share2.h. There you will
find that it uses
Replicated() for multiplication, which is
Protocols/Replicated.h. You can also consult the
tutorial for the lowest-level interface.
Fill in the
constant()static member function of
NoShareas well as the
exchange()member function of
NoOutput. Check out
Protocols/SemiMC.hppfor a simple example. It opens an additive secret sharing by sending all shares to all other parties and then summing up the received. See this reference for documentation on the necessary infrastructure. Constant sharing and public output allows to execute the following program:
print_ln('result: %s', sint(123).reveal())
This allows to check the correct execution of further functionality.
Put the above code in
Programs/Source/test.mpcand run the following if your protocol works for two parties (otherwise add more parties and change the
make no-party.x ./compile.py test ./no-party.x 0 test -N 2 & ./no-party.1 test -N 2
This should output
Fill in the operator functions in
NoShareand check them:
print_ln('%s', (sint(2) + sint(3)).reveal()) print_ln('%s', (sint(2) - sint(3)).reveal()) print_ln('%s', (sint(2) * cint(3)).reveal())
Many protocols use these basic operations, which makes it beneficial to check the correctness
NoProtocol. Alternatively, if the desired protocol is based on Beaver multiplication, you can specify the following in
typedef Beaver<This> Protocol;
Then add the desired triple generation to
NoLivePrep::buffer_triples(). In any case you should then be able to execute:
print_ln('%s', (sint(2) * sint(3)).reveal())
In order to execute many kinds of non-linear computation, random bits are needed. After filling in
NoLivePrep::buffer_bits(), you should be able to execute:
print_ln('%s', (sint(2) < sint(3)).reveal()
The following classes are fundamental building blocks in protocols. See also the this reference for networking-related classes.
Pseudo-random number generator. This uses counter-mode AES by default, which can be changed libsodium’s expansion by undefining
Construction without initialization. Usage without initialization will fail.
Initialize from local randomness.
void SeedGlobally(const Player &P, bool secure = true)¶
Coordinate random seed
P – communication instances
secure – seeding prevents tampering at higher cost
void SetSeed(const unsigned char*)¶
SEED_SIZEbytes from pointer.
inline bool get_bit()¶
inline unsigned char get_uchar()¶
unsigned int get_uint()¶
Random 32-bit integer.
unsigned int get_uint(int upper)¶
Random 32-bit integer between 0 and
void randomBnd(T &res, const bigint &B, bool positive = true)¶
Random integer in
res – result
B – bound
positive – positive result (random sign otherwise)
inline word get_word()¶
Random 64-bit integer.
inline __m128i get_doubleword()¶
Random 128-bit integer.
inline void get_octets(octet *ans, int len)¶
Fill array with random data
ans – result
len – byte length
inline void get_octets(octet *ans)¶
Fill array with random data (compile-time length)
ans – result