Networking¶
All protocols in MP-SPDZ rely on point-to-point connections between
all pairs of parties. This is realized using TCP, which means that
every party must be reachable under at least one TCP port. The default
is to set this port to a base plus the player number. This allows for
easily running all parties on the same host. The base defaults to 5000,
which can be changed with the command-line option
--portnumbase
. However, the scripts in Scripts
use a random
base port number, which can be changed using the same option.
There are two ways of communicating hosts and individually setting ports:
All parties first connect to a coordination server, which broadcasts the data for all parties. This is the default with the coordination server being run as a thread of party 0. The hostname of the coordination server has to be given with the command-line parameter
--hostname
, and the coordination server runs on the base port number, thus defaulting to 5000. Furthermore, you can specify a party’s listening port using--my-port
.The parties read the information from a local file, which needs to be the same everywhere. The file can be specified using
--ip-file-name
and has the following format:<host0>[:<port0>] <host1>[:<port1>] ...
The hosts can be both hostnames and IP addresses. If not given, the ports default to base plus party number.
Whether or not encrypted connections are used depends on the security
model of the protocol. Honest-majority protocols default to encrypted
whereas dishonest-majority protocols default to unencrypted. You
change this by either using --encrypted/-e
or
--unencrypted/-u
.
If using encryption, the certificates (Player-Data/*.pem
) must be
the same on all hosts, and you have to run c_rehash Player-Data
on
all of them. Scripts/setup-ssl.sh
can be used to generate the
necessary certificates. The common name has to be P<player number>
for computing parties and C<client number>
for clients.
Internal Infrastructure¶
The internal networking infrastructure of MP-SPDZ reflects the needs of the various multi-party computation. For example, some protocols require a simultaneous broadcast from all parties whereas other protocols require that every party sends different information to different parties (include none at all). The infrastructure makes sure to send and receive in parallel whenever possible.
All communication is handled through two subclasses of Player
defined in Networking/Player.h
. PlainPlayer
communicates
in cleartext while CryptoPlayer
uses TLS encryption. The
former uses the same BSD socket for sending and receiving but the
latter uses two different connections for sending and receiving. This
is because TLS communication is never truly one-way due key renewals
etc., so the only way for simultaneous sending and receiving we found
was to use two connections in two threads.
If you wish to use a different networking facility, we recommend to
subclass Player
and fill in the virtual-only functions
required by the compiler (e.g., send_to_no_stats()
for
sending to one other party). Note that not all protocols require all
functions, so you only need to properly implement those you need. You
can then replace uses of PlainPlayer
or
CryptoPlayer
by your own class. Furthermore, you might
need to extend the Names
class to suit your purpose. By
default, Names
manages one TCP port that a party is
listening on for connections. If this suits you, you don’t need to
change anything
Reference¶
-
class Names¶
Network setup (hostnames and port numbers)
Public Functions
-
void init(int player, int pnb, int my_port, const char *servername, bool setup_socket = true)¶
Initialize with central server
- Parameters
player – my number
pnb – base port number (server listens one below)
my_port – my port number (
DEFAULT_PORT
for default, which is base port number plus player number)servername – location of server
setup_socket – whether to start listening
-
inline Names(int player, int pnb, int my_port, const char *servername)¶
-
Names(int player, int nplayers, const string &servername, int pnb, int my_port = DEFAULT_PORT)¶
Initialize with central server running on player 0
- Parameters
player – my number
nplayers – number of players
servername – location of player 0
pnb – base port number
my_port – my port number (
DEFAULT_PORT
for default, which is base port number plus player number)
-
void init(int player, int pnb, vector<string> Nms)¶
Initialize without central server
- Parameters
player – my number
pnb – base port number
Nms – locations of all parties
-
inline Names(int player, int pnb, vector<string> Nms)¶
-
void init(int player, int pnb, const string &hostsfile, int players = 0)¶
Initialize from file. One party per line, format
<hostname>[:<port>]
- Parameters
player – my number
pnb – base port number
hostsfile – filename
players – number of players (0 to take from file)
-
inline Names(int player, int pnb, const string &hostsfile)¶
-
Names(ez::ezOptionParser &opt, int argc, const char **argv, int default_nplayers = 2)¶
Initialize from command-line options
- Parameters
opt – option parser instance
argc – number of command-line arguments
argv – command-line arguments
default_nplayers – default number of players (used if not given in arguments)
-
Names(int my_num = 0, int num_players = 1)¶
-
~Names()¶
-
inline int num_players() const¶
-
inline int my_num() const¶
-
inline const string get_name(int i) const¶
-
inline int get_portnum_base() const¶
Public Static Attributes
-
static const int DEFAULT_PORT = -1¶
-
void init(int player, int pnb, int my_port, const char *servername, bool setup_socket = true)¶
-
class Player : public PlayerBase¶
Abstract class for multi-player communication.
*_no_stats
functions are called by their equivalents after accounting for communications statistics.Subclassed by MultiPlayer< int >, MultiPlayer< ssl_socket * >, AllButLastPlayer, MultiPlayer< T >
Public Functions
-
inline virtual int num_players() const¶
Get number of players
-
inline virtual int my_num() const¶
Get my player number
-
virtual void send_all(const octetStream &o) const¶
Send the same to all other players
-
void send_to(int player, const octetStream &o) const¶
Send to a specific player
-
void receive_all(vector<octetStream> &os) const¶
Receive from all other players. Information from player 0 at
os[0]
etc.
-
virtual void receive_player(int i, octetStream &o) const¶
Receive from a specific player
-
void send_relative(const vector<octetStream> &o) const¶
Send to all other players by offset.
o[0]
gets sent to the next player etc.
-
void receive_relative(vector<octetStream> &o) const¶
Receive from all other players by offset.
o[0]
will contain data from the next player etc.
-
void receive_relative(int offset, octetStream &o) const¶
Receive from other player specified by offset. 1 stands for the next player etc.
-
void exchange(int other, const octetStream &to_send, octetStream &ot_receive) const¶
Exchange information with one other party, reusing the buffer if possible.
-
void exchange(int other, octetStream &o) const¶
Exchange information with one other party, reusing the buffer.
-
void exchange_relative(int offset, octetStream &o) const¶
Exchange information with one other party specified by offset, reusing the buffer if possible.
-
inline virtual void pass_around(octetStream &o, int offset = 1) const¶
Send information to a party while receiving from another by offset, The default is to send to the next party while receiving from the previous. The buffer is reused.
-
void pass_around(octetStream &to_send, octetStream &to_receive, int offset) const¶
Send information to a party while receiving from another by offset. The default is to send to the next party while receiving from the previous.
-
virtual void unchecked_broadcast(vector<octetStream> &o) const¶
Broadcast and receive data to/from all players. Assumes o[player_no] contains the data to be broadcast by me.
-
virtual void Broadcast_Receive(vector<octetStream> &o) const¶
Broadcast and receive data to/from all players with eventual verification. Assumes o[player_no] contains the data to be broadcast by me.
-
virtual void Check_Broadcast() const¶
Run protocol to verify broadcast is correct
-
virtual void send_receive_all(const vector<octetStream> &to_send, vector<octetStream> &to_receive) const¶
Send something different to each player.
-
void send_receive_all(const vector<bool> &senders, const vector<octetStream> &to_send, vector<octetStream> &to_receive) const¶
Specified senders only send something different to each player.
- Parameters
senders – set whether a player sends or not, must be equal on all players
to_send – data to send by player number
to_receive – received data by player number
-
void send_receive_all(const vector<vector<bool>> &channels, const vector<octetStream> &to_send, vector<octetStream> &to_receive) const¶
Send something different only one specified channels.
- Parameters
channels –
channel[i][j]
indicates whether partyi
sends to partyj
to_send – data to send by player number
to_receive – received data by player number
-
virtual void partial_broadcast(const vector<bool> &senders, const vector<bool> &receivers, vector<octetStream> &os) const¶
Specified senders broadcast information to specified receivers.
- Parameters
senders – specify which parties do send
receivers – specify which parties do send
os – data to send at
os[my_number]
, received data elsewhere
-
inline virtual int num_players() const¶
-
template<class T>
class MultiPlayer : public Player¶ Multi-player communication helper class.
T = int
for unencrypted BSD sockets andT = ssl_socket*
for Boost SSL streams.
-
class PlainPlayer : public MultiPlayer<int>¶
Plaintext multi-player communication
Subclassed by ThreadPlayer
-
class CryptoPlayer : public MultiPlayer<ssl_socket*>¶
Encrypted multi-party communication. Uses OpenSSL and certificates issued to “P<player_no>”. Sending and receiving is done in separate threads to allow for bidirectional communication.
Public Functions
-
CryptoPlayer(const Names &Nms, const string &id)¶
Start a new set of encrypted connections.
- Parameters
Nms – network setup
id – unique identifier
-
virtual void partial_broadcast(const vector<bool> &my_senders, const vector<bool> &my_receivers, vector<octetStream> &os) const¶
Specified senders broadcast information to specified receivers.
- Parameters
senders – specify which parties do send
receivers – specify which parties do send
os – data to send at
os[my_number]
, received data elsewhere
-
CryptoPlayer(const Names &Nms, const string &id)¶
-
class octetStream¶
Buffer for network communication with a pointer for sequential reading. When sent over the network or stored in a file, the length is prefixed as eight bytes in little-endian order.
Public Functions
-
inline void resize(size_t l)¶
Increase allocation if needed.
-
void clear()¶
Free memory.
-
octetStream(size_t len, const octet *source)¶
Initial buffer.
-
octetStream(const string &other)¶
Initial buffer.
-
inline size_t get_ptr() const¶
Number of bytes already read.
-
inline size_t get_length() const¶
Length.
-
inline size_t get_total_length() const¶
Length including size tag.
-
inline size_t get_max_length() const¶
Allocation.
-
inline octet *get_data() const¶
Data pointer.
-
inline octet *get_data_ptr() const¶
Read pointer.
-
inline bool done() const¶
Whether done reading.
-
inline bool empty() const¶
Whether empty.
-
inline size_t left() const¶
Bytes left to read.
-
string str() const¶
Convert to string.
-
octetStream hash() const¶
Hash content.
-
void concat(const octetStream &os)¶
Append other buffer.
-
inline void reset_read_head()¶
Reset reading.
-
inline void reset_write_head()¶
Set length to zero but keep allocation.
-
inline bool operator==(const octetStream &a) const¶
Equality test.
-
void append_random(size_t num)¶
Append
num
random bytes.
-
inline void append(const octet *x, const size_t l)¶
Append
l
bytes fromx
-
inline void consume(octet *x, const size_t l)¶
Read
l
bytes tox
-
inline void store(unsigned int a)¶
Append 4-byte integer.
-
void store(int a)¶
Append 4-byte integer.
-
inline void get(unsigned int &a)¶
Read 4-byte integer.
-
void get(int &a)¶
Read 4-byte integer.
-
inline void store(size_t a)¶
Append 8-byte integer.
-
inline void get(size_t &a)¶
Read 8-byte integer.
-
inline void store_int(size_t a, int n_bytes)¶
Append integer of
n_bytes
bytes.
-
inline size_t get_int(int n_bytes)¶
Read integer of
n_bytes
bytes.
-
template<int N_BYTES>
inline void store_int(size_t a)¶ Append integer of
N_BYTES
bytes.
-
template<int N_BYTES>
inline size_t get_int()¶ Read integer of
N_BYTES
bytes.
-
template<class T>
void get(vector<T> &v, const T &init = {})¶ Read vector of type implementing
unpack
- Parameters
v – results
init – initialization if required
-
template<class T>
void get_no_resize(vector<T> &v)¶ Read vector of type implementing
unpack
if vector already has the right size
-
inline void consume(octetStream &s, size_t l)¶
Read
l
bytes into separate buffer.
-
void store(const string &str)¶
Append string.
-
void get(string &str)¶
Read string.
-
template<class T>
inline void Receive(T socket_num)¶ Receive on
socket_num
, overwriting current content.
-
void input(const string &filename)¶
Input from file, overwriting current content.
-
void input(istream &s)¶
Input from stream, overwriting current content.
-
void output(ostream &s) const¶
Output to stream.
-
template<class T>
inline void exchange(T send_socket, T receive_socket)¶ Send on
socket_num
while receiving onreceiving_socket
, overwriting current content
-
template<class T>
void exchange(T send_socket, T receive_socket, octetStream &receive_stream) const¶ Send this buffer on
socket_num
while receiving toreceive_stream
onreceiving_socket
-
inline void resize(size_t l)¶