# Low-Level InterfaceΒΆ

In the following we will explain the basic 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.

```
Names N;
int my_number = atoi(argv[1]);
int n_parties = atoi(argv[2]);
int port_base = 9999;
Server::start_networking(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. `Server::start_networking()`

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.

```
// initialize fields
T::clear::init_default(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.

```
T::clear::next::init_default(prime_length, false);
```

For computation modulo a prime, it is more efficient to use Montgomery representation, which is not compatible with the MASCOT offline phase however. This line initializes another field instance for MASCOT without using Montgomery representation.

```
// must initialize MAC key for security of some protocols
typename T::mac_key_type mac_key;
T::read_or_generate_mac_key("", P, mac_key);
```

Some protocols use an information-theoretic tag that is constant throughout the protocol. This codes reads it from storage if available or generates a fresh one otherwise.

```
// global OT setup
BaseMachine machine;
if (T::needs_ot)
machine.ot_setups.push_back({P});
```

Many protocols for a dishonest majority use oblivious transfer. This
block runs a few instances to seed the oblivious transfer
extension. The resulting setup only works for one thread. For several
threads, you need to add sufficiently many instances to
`ot_setups`

and set `BaseMachine::thread_num`

(thread-local) to a different consecutive number in every thread.

```
// keeps tracks of preprocessing usage (triples etc)
DataPositions usage;
usage.set_num_players(P.num_players());
```

To help keeping track of the required preprocessing, it is necessary
to initialize preprocessing instances with a `DataPositions`

variable that will store the usage.

```
// initialize binary computation
T::bit_type::mac_key_type::init_field();
typename T::bit_type::mac_key_type binary_mac_key;
T::bit_type::part_type::read_or_generate_mac_key("", P, binary_mac_key);
GC::ShareThread<typename T::bit_type> thread(N,
OnlineOptions::singleton, P, binary_mac_key, usage);
```

While this example only uses arithmetic computation, you need to
initialize binary computation as well unless you use the compile-time
option `NO_MIXED_CIRCUITS`

.

```
// output protocol
typename T::MAC_Check output(mac_key);
```

Some output protocols use the MAC key to check the correctness.

```
// various preprocessing
typename T::LivePrep preprocessing(0, usage);
SubProcessor<T> processor(output, preprocessing, P);
```

In this example we use live preprocessing, but it is also possible to
read preprocessing data from disk by using `Sub_Data_Files`

instead. You can use a live preprocessing instances to generate
preprocessing data independently, but many protocols require that a
`SubProcessor`

instance has been created as well. The latter
essentially glues an instance of the output and the preprocessing
protocol together, which is necessary for Beaver-based multiplication
protocols.

```
// input protocol
typename T::Input input(processor, output);
```

Some input protocols depend on preprocessing and an output protocol, which is reflect in the standard constructor. Other constructors are available depending on the protocol.

```
// multiplication protocol
typename T::Protocol protocol(P);
```

This instantiates a multiplication protocol. `P`

is required
because some protocols start by exchanging keys for pseudo-random
secret sharing.

```
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.

```
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 except that it is necessary to call the checking in order to verify the outputs.

```
T::LivePrep::teardown();
```

This frees the memory used for global key material when using homomorphic encryption. Otherwise, this does not do anything.