<commit_before>#include "Crypto/CppDsaPrivateKey.hpp"
#include "Crypto/CppDsaPublicKey.hpp"
#include "Utils/QRunTimeError.hpp"
#include "Utils/Timer.hpp"
#include "Utils/TimerCallback.hpp"

#include "NeffKeyShuffle.hpp"

namespace Dissent {
  using Crypto::CppDsaPrivateKey;
  using Crypto::CppDsaPublicKey;
  using Utils::QRunTimeError;

namespace Anonymity {
  NeffKeyShuffle::NeffKeyShuffle(const Group &group,
      const PrivateIdentity &ident, const Id &round_id,
      QSharedPointer<Network> network,
      GetDataCallback &get_data) :
    Round(group, ident, round_id, network, get_data),
    _state_machine(this)
  {
    _state_machine.AddState(OFFLINE);
    _state_machine.AddState(KEY_GENERATION, -1, 0, &NeffKeyShuffle::GenerateKey);
    _state_machine.AddState(KEY_SUBMISSION, -1, 0, &NeffKeyShuffle::SubmitKey);
    _state_machine.AddState(WAITING_FOR_ANONYMIZED_KEYS, ANONYMIZED_KEYS,
        &NeffKeyShuffle::HandleAnonymizedKeys);
    _state_machine.AddState(PROCESSING_ANONYMIZED_KEYS, -1, 0,
        &NeffKeyShuffle::ProcessAnonymizedKeys);
    _state_machine.AddState(FINISHED);
    _state_machine.SetState(OFFLINE);

    _state_machine.AddTransition(OFFLINE, KEY_GENERATION);
    _state_machine.AddTransition(KEY_GENERATION, KEY_SUBMISSION);
    _state_machine.AddTransition(WAITING_FOR_ANONYMIZED_KEYS,
        PROCESSING_ANONYMIZED_KEYS);

    if(group.GetSubgroup().Contains(ident.GetLocalId())) {
      InitServer();
    } else {
      InitClient();
    }
  }

  NeffKeyShuffle::~NeffKeyShuffle()
  {
  }

  void NeffKeyShuffle::InitServer()
  {
    _server_state = QSharedPointer<ServerState>(new ServerState());
    _state = _server_state;

    _state_machine.AddState(SHUFFLING, -1, 0, &NeffKeyShuffle::ShuffleKeys);

    if(GetGroup().GetSubgroup().GetIndex(GetLocalId()) == 0) {
      _state_machine.AddState(WAITING_FOR_KEYS, KEY_SUBMIT,
          &NeffKeyShuffle::HandleKeySubmission,
          &NeffKeyShuffle::PrepareForKeySubmissions);

      _state_machine.AddTransition(KEY_SUBMISSION, WAITING_FOR_KEYS);
      _state_machine.AddTransition(WAITING_FOR_KEYS, SHUFFLING);
    } else {
      _state_machine.AddState(WAITING_FOR_SHUFFLE, KEY_SHUFFLE,
          &NeffKeyShuffle::HandleShuffle);

      _state_machine.AddTransition(KEY_SUBMISSION, WAITING_FOR_SHUFFLE);
      _state_machine.AddTransition(WAITING_FOR_SHUFFLE, SHUFFLING);
    }

    _state_machine.AddTransition(SHUFFLING, WAITING_FOR_ANONYMIZED_KEYS);
  }

  void NeffKeyShuffle::InitClient()
  {
    _state = QSharedPointer<State>(new State());

    _state_machine.AddTransition(KEY_SUBMISSION,
        WAITING_FOR_ANONYMIZED_KEYS);
  }

  void NeffKeyShuffle::OnStart()
  {
    Round::OnStart();
    _state_machine.StateComplete();
  }

  void NeffKeyShuffle::OnStop()
  {
    _state_machine.SetState(FINISHED);
    Round::OnStop();
  }

  void NeffKeyShuffle::HandleDisconnect(const Id &id)
  {
    if(!GetGroup().Contains(id)) {
      return;
    }

    if(GetGroup().GetSubgroup().Contains(id)) {
      qDebug() << "A server (" << id << ") disconnected.";
      SetInterrupted();
      Stop("A server (" + id.ToString() +") disconnected.");
    } else {
      qDebug() << "A client (" << id << ") disconnected, ignoring.";
    }
  }

  void NeffKeyShuffle::HandleKeySubmission(const Id &from, QDataStream &stream)
  {
    int gidx = GetGroup().GetIndex(from);
    if(_server_state->shuffle_input[gidx] != 0) {
      throw QRunTimeError("Received multiples data messages.");
    }

    Integer key;
    stream >> key;

    if(key == 0) {
      throw QRunTimeError("Received a 0 key");
    } else if(GetModulus() <= key) {
      throw QRunTimeError("Key is not valid in this modulus");
    }
    
    _server_state->shuffle_input[gidx] = key;
    ++_server_state->keys_received;
    
    qDebug() << GetGroup().GetIndex(GetLocalId()) << GetLocalId() <<
        ": received key from" << GetGroup().GetIndex(from) << from <<
        "Have:" << _server_state->keys_received << "expect:" << GetGroup().Count();

    if(_server_state->keys_received == GetGroup().Count()) {
      _server_state->key_receive_period.Stop();
      _state_machine.StateComplete();
    }
  }

  void NeffKeyShuffle::HandleShuffle(const Id &from, QDataStream &stream)
  {
    if(GetGroup().GetSubgroup().Previous(GetLocalId()) != from) {
      throw QRunTimeError("Received a shuffle out of order");
    }

    Integer generator_input;
    QVector<Integer> shuffle_input;

    stream >> generator_input >> shuffle_input;

    if(generator_input == 0) {
      throw QRunTimeError("Invalid generator found");
    } else if(shuffle_input.count() <= GetGroup().GetSubgroup().Count()) {
      throw QRunTimeError("Missing public keys");
    }

    _server_state->generator_input = generator_input;
    _server_state->shuffle_input = shuffle_input;

    qDebug() << GetGroup().GetIndex(GetLocalId()) << GetLocalId() <<
        ": received shuffle data from" << GetGroup().GetIndex(from) << from;

    _state_machine.StateComplete();
  }

  void NeffKeyShuffle::HandleAnonymizedKeys(const Id &from,
      QDataStream &stream)
  {
    if(GetGroup().GetSubgroup().Last() != from) {
      throw QRunTimeError("Received from wrong server");
    }

    Integer new_generator;
    QVector<Integer> new_public_elements;

    stream >> new_generator >> new_public_elements;

    if(new_generator == 0) {
      throw QRunTimeError("Invalid generator found");
    } else if(new_public_elements.count() <= GetGroup().GetSubgroup().Count()) {
      throw QRunTimeError("Missing public keys");
    }

    _state->new_generator = new_generator;
    _state->new_public_elements = new_public_elements;

    qDebug() << GetGroup().GetIndex(GetLocalId()) << GetLocalId() <<
        ": received keys from" << GetGroup().GetIndex(from) << from;
    _state_machine.StateComplete();<commit_msg>[Anonymity] NeffKeyShuffle did not work if all members were servers<commit_after>#include "Crypto/CppDsaPrivateKey.hpp"
#include "Crypto/CppDsaPublicKey.hpp"
#include "Utils/QRunTimeError.hpp"
#include "Utils/Timer.hpp"
#include "Utils/TimerCallback.hpp"

#include "NeffKeyShuffle.hpp"

namespace Dissent {
  using Crypto::CppDsaPrivateKey;
  using Crypto::CppDsaPublicKey;
  using Utils::QRunTimeError;

namespace Anonymity {
  NeffKeyShuffle::NeffKeyShuffle(const Group &group,
      const PrivateIdentity &ident, const Id &round_id,
      QSharedPointer<Network> network,
      GetDataCallback &get_data) :
    Round(group, ident, round_id, network, get_data),
    _state_machine(this)
  {
    _state_machine.AddState(OFFLINE);
    _state_machine.AddState(KEY_GENERATION, -1, 0, &NeffKeyShuffle::GenerateKey);
    _state_machine.AddState(KEY_SUBMISSION, -1, 0, &NeffKeyShuffle::SubmitKey);
    _state_machine.AddState(WAITING_FOR_ANONYMIZED_KEYS, ANONYMIZED_KEYS,
        &NeffKeyShuffle::HandleAnonymizedKeys);
    _state_machine.AddState(PROCESSING_ANONYMIZED_KEYS, -1, 0,
        &NeffKeyShuffle::ProcessAnonymizedKeys);
    _state_machine.AddState(FINISHED);
    _state_machine.SetState(OFFLINE);

    _state_machine.AddTransition(OFFLINE, KEY_GENERATION);
    _state_machine.AddTransition(KEY_GENERATION, KEY_SUBMISSION);
    _state_machine.AddTransition(WAITING_FOR_ANONYMIZED_KEYS,
        PROCESSING_ANONYMIZED_KEYS);

    if(group.GetSubgroup().Contains(ident.GetLocalId())) {
      InitServer();
    } else {
      InitClient();
    }
  }

  NeffKeyShuffle::~NeffKeyShuffle()
  {
  }

  void NeffKeyShuffle::InitServer()
  {
    _server_state = QSharedPointer<ServerState>(new ServerState());
    _state = _server_state;

    _state_machine.AddState(SHUFFLING, -1, 0, &NeffKeyShuffle::ShuffleKeys);

    if(GetGroup().GetSubgroup().GetIndex(GetLocalId()) == 0) {
      _state_machine.AddState(WAITING_FOR_KEYS, KEY_SUBMIT,
          &NeffKeyShuffle::HandleKeySubmission,
          &NeffKeyShuffle::PrepareForKeySubmissions);

      _state_machine.AddTransition(KEY_SUBMISSION, WAITING_FOR_KEYS);
      _state_machine.AddTransition(WAITING_FOR_KEYS, SHUFFLING);
    } else {
      _state_machine.AddState(WAITING_FOR_SHUFFLE, KEY_SHUFFLE,
          &NeffKeyShuffle::HandleShuffle);

      _state_machine.AddTransition(KEY_SUBMISSION, WAITING_FOR_SHUFFLE);
      _state_machine.AddTransition(WAITING_FOR_SHUFFLE, SHUFFLING);
    }

    _state_machine.AddTransition(SHUFFLING, WAITING_FOR_ANONYMIZED_KEYS);
  }

  void NeffKeyShuffle::InitClient()
  {
    _state = QSharedPointer<State>(new State());

    _state_machine.AddTransition(KEY_SUBMISSION,
        WAITING_FOR_ANONYMIZED_KEYS);
  }

  void NeffKeyShuffle::OnStart()
  {
    Round::OnStart();
    _state_machine.StateComplete();
  }

  void NeffKeyShuffle::OnStop()
  {
    _state_machine.SetState(FINISHED);
    Round::OnStop();
  }

  void NeffKeyShuffle::HandleDisconnect(const Id &id)
  {
    if(!GetGroup().Contains(id)) {
      return;
    }

    if(GetGroup().GetSubgroup().Contains(id)) {
      qDebug() << "A server (" << id << ") disconnected.";
      SetInterrupted();
      Stop("A server (" + id.ToString() +") disconnected.");
    } else {
      qDebug() << "A client (" << id << ") disconnected, ignoring.";
    }
  }

  void NeffKeyShuffle::HandleKeySubmission(const Id &from, QDataStream &stream)
  {
    int gidx = GetGroup().GetIndex(from);
    if(_server_state->shuffle_input[gidx] != 0) {
      throw QRunTimeError("Received multiples data messages.");
    }

    Integer key;
    stream >> key;

    if(key == 0) {
      throw QRunTimeError("Received a 0 key");
    } else if(GetModulus() <= key) {
      throw QRunTimeError("Key is not valid in this modulus");
    }
    
    _server_state->shuffle_input[gidx] = key;
    ++_server_state->keys_received;
    
    qDebug() << GetGroup().GetIndex(GetLocalId()) << GetLocalId() <<
        ": received key from" << GetGroup().GetIndex(from) << from <<
        "Have:" << _server_state->keys_received << "expect:" << GetGroup().Count();

    if(_server_state->keys_received == GetGroup().Count()) {
      _server_state->key_receive_period.Stop();
      _state_machine.StateComplete();
    }
  }

  void NeffKeyShuffle::HandleShuffle(const Id &from, QDataStream &stream)
  {
    if(GetGroup().GetSubgroup().Previous(GetLocalId()) != from) {
      throw QRunTimeError("Received a shuffle out of order");
    }

    Integer generator_input;
    QVector<Integer> shuffle_input;

    stream >> generator_input >> shuffle_input;

    if(generator_input == 0) {
      throw QRunTimeError("Invalid generator found");
    } else if(shuffle_input.count() < GetGroup().GetSubgroup().Count()) {
      throw QRunTimeError("Missing public keys");
    }

    _server_state->generator_input = generator_input;
    _server_state->shuffle_input = shuffle_input;

    qDebug() << GetGroup().GetIndex(GetLocalId()) << GetLocalId() <<
        ": received shuffle data from" << GetGroup().GetIndex(from) << from;

    _state_machine.StateComplete();
  }

  void NeffKeyShuffle::HandleAnonymizedKeys(const Id &from,
      QDataStream &stream)
  {
    if(GetGroup().GetSubgroup().Last() != from) {
      throw QRunTimeError("Received from wrong server");
    }

    Integer new_generator;
    QVector<Integer> new_public_elements;

    stream >> new_generator >> new_public_elements;

    if(new_generator == 0) {
      throw QRunTimeError("Invalid generator found");
    } else if(new_public_elements.count() < GetGroup().GetSubgroup().Count()) {
      throw QRunTimeError("Missing public keys");
    }

    _state->new_generator = new_generator;
    _state->new_public_elements = new_public_elements;

    qDebug() << GetGroup().GetIndex(GetLocalId()) << GetLocalId() <<
        ": received keys from" << GetGroup().GetIndex(from) << from;
    _state_machine.StateComplete();
{'fraction_non_alphanumeric': 0.12958226768968456, 'fraction_numerical': 0.0023870417732310316, 'mean_word_length': 4.122707423580786, 'pattern_counts': {'":': 6, '<': 119, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1986285', 'n_tokens_mistral': 3990, 'n_tokens_neox': 3892, 'n_words': 592}