async broadcastHandshake(nodes) {
    const payload = {
      ip: this.node.ip,
      lastMessageId: this.node.publisher.lastMessageId,
      nodeId: this.node.nodeId,
    };

    const encoder = this.protoroot.lookupType("HandshakeRequest");
    const encoded = encoder.encode(encoder.create(payload)).finish();

    const responses = await Bluebird.map(nodes, ({ id, ip }) =>
      this._sendSingleHandshake(id, ip, encoded),
    );

    const decoder = this.protoroot.lookupType("HandshakeResponse");
    const result = {};

    for (let i = 0; i < nodes.length; i++) {
      if (responses[i] === null) {
        result[nodes[i].id] = null;
      } else {
        result[nodes[i].id] = decoder.toObject(decoder.decode(responses[i]));
      }
    }

    return result;
  }
Sends a handshake request to other remote nodes and process their response
Returns an object with the following structure:

{
  [nodeId]: { added: <boolean>, lastMessageId: <number> },
  [nodeId]: null, // no response received, node is probably dead
}

@param  {Array.<IdCard>} nodes
@return {Object}