void BulkRound::HandleBulkData(QDataStream &stream, const Id &from) { qDebug() << GetGroup().GetIndex(GetLocalId()) << GetLocalId().ToString() << ": received bulk data from " << GetGroup().GetIndex(from) << from.ToString(); if(IsLeader() || !_app_broadcast) { if(_state != DataSharing) { throw QRunTimeError("Received a misordered BulkData message"); } } else if(_app_broadcast && _state != ProcessingLeaderData) { throw QRunTimeError("Waiting for data from leader, received something else."); } int idx = GetGroup().GetIndex(from); if(!_messages[idx].isEmpty()) { throw QRunTimeError("Already have bulk data."); } QByteArray payload; stream >> payload; if(payload.size() != _expected_bulk_size) { throw QRunTimeError("Incorrect bulk message length"); } _messages[idx] = payload; if(++_received_messages == GetGroup().Count()) { ProcessMessages(); Finish(); } }
void RepeatingBulkRound::ProcessDataBase(const Id &from, const QByteArray &data) { QByteArray payload; if(!Verify(from, data, payload)) { throw QRunTimeError("Invalid signature or data"); } if(_state == Offline) { throw QRunTimeError("Should never receive a message in the bulk" " round while offline."); } QDataStream stream(payload); int mtype; QByteArray round_id; uint phase; stream >> mtype >> round_id >> phase; MessageType msg_type = (MessageType) mtype; Id rid(round_id); if(rid != GetRoundId()) { throw QRunTimeError("Not this round: " + rid.ToString() + " " + GetRoundId().ToString()); } if(_state == Shuffling) { _log.Pop(); _offline_log.Append(data, from); return; } if(_phase != phase) { if(_phase == phase - 1 && _state == DataSharing) { _log.Pop(); _offline_log.Append(data, from); return; } else { throw QRunTimeError("Received a message for phase: " + QString::number(phase) + ", while in phase: " + QString::number(_phase)); } } else if(_state == PhasePreparation) { _log.Pop(); _offline_log.Append(data, from); return; } switch(msg_type) { case BulkData: HandleBulkData(stream, from); break; default: throw QRunTimeError("Unknown message type"); } }
void RepeatingBulkRound::HandleBulkData(QDataStream &stream, const Id &from) { qDebug() << GetGroup().GetIndex(GetLocalId()) << GetLocalId().ToString() << ": received bulk data from " << GetGroup().GetIndex(from) << from.ToString() << "Have" << (_received_messages + 1) << "expecting" << _messages.count(); if(_state != DataSharing) { throw QRunTimeError("Received a misordered BulkData message"); } uint idx = GetGroup().GetIndex(from); if(!_messages[idx].isEmpty()) { throw QRunTimeError("Already have bulk data."); } QByteArray payload; stream >> payload; if(static_cast<uint>(payload.size()) != _expected_bulk_size) { throw QRunTimeError("Incorrect bulk message length, got " + QString::number(payload.size()) + " expected " + QString::number(_expected_bulk_size)); } _messages[idx] = payload; if(++_received_messages == static_cast<uint>(GetGroup().Count())) { ProcessMessages(); SetState(PhasePreparation); qDebug() << "In" << ToString() << "ending phase."; _phase++; if(!PrepForNextPhase()) { return; } SetState(DataSharing); uint count = static_cast<uint>(_offline_log.Count()); for(uint idx = 0; idx < count; idx++) { QPair<QByteArray, Id> entry = _offline_log.At(idx); ProcessData(entry.second, entry.first); } _offline_log.Clear(); NextPhase(); } }
void BulkRound::ProcessDataBase(const Id &from, const QByteArray &data) { QByteArray payload; if(!Verify(from, data, payload)) { throw QRunTimeError("Invalid signature or data"); } if(_state == Offline) { throw QRunTimeError("Should never receive a message in the bulk" " round while offline."); } QDataStream stream(payload); int mtype; QByteArray round_id; stream >> mtype >> round_id; MessageType msg_type = (MessageType) mtype; Id rid(round_id); if(rid != GetRoundId()) { throw QRunTimeError("Not this round: " + rid.ToString() + " " + GetRoundId().ToString()); } if(_state == Shuffling) { _log.Pop(); _offline_log.Append(data, from); return; } switch(msg_type) { case BulkData: HandleBulkData(stream, from); break; case LoggedBulkData: HandleLoggedBulkData(stream, from); break; case AggregatedBulkData: HandleAggregatedBulkData(stream, from); break; default: throw QRunTimeError("Unknown message type"); } }
void BulkRound::HandleAggregatedBulkData(QDataStream &stream, const Id &from) { if(from == GetLocalId()) { return; } qDebug() << GetGroup().GetIndex(GetLocalId()) << GetLocalId().ToString() << ": received aggregated bulk data from " << GetGroup().GetIndex(from) << from.ToString(); if(GetGroup().GetLeader() != from) { throw QRunTimeError("Received aggregated bulk data from non-leader."); } if(_state != ReceivingLeaderData) { throw QRunTimeError("Not expected at this time."); } QVector<QByteArray> cleartexts; stream >> cleartexts; const QVector<Descriptor> &des = GetDescriptors(); if(cleartexts.count() != des.count()) { throw QRunTimeError("Cleartext count does not match descriptor count: " + QString::number(cleartexts.count()) + " " + QString::number(des.count())); } Hash hashalgo; for(int idx = 0; idx < cleartexts.count(); idx++) { QByteArray cleartext = cleartexts[idx]; QByteArray hash = hashalgo.ComputeHash(cleartext); if(hash != des[idx].CleartextHash()) { throw QRunTimeError("Cleartext hash does not match descriptor hash."); } if(!cleartext.isEmpty()) { PushData(GetSharedPointer(), cleartext); } } Finish(); }
void BulkRound::HandleLoggedBulkData(QDataStream &stream, const Id &from) { if(from == GetLocalId()) { return; } qDebug() << GetGroup().GetIndex(GetLocalId()) << GetLocalId().ToString() << ": received logged bulk data from " << GetGroup().GetIndex(from) << from.ToString(); if(GetGroup().GetLeader() != from) { throw QRunTimeError("Received logged bulk data from non-leader."); } if(_state != ReceivingLeaderData) { throw QRunTimeError("Not expected at this time."); } QByteArray binary_log; stream >> binary_log; Log log(binary_log); if(log.Count() != GetGroup().Count()) { throw QRunTimeError("Incorrect number of log messages."); } _state = ProcessingLeaderData; for(int idx = 0; idx < log.Count(); idx++) { const QPair<QByteArray, Id> &res = log.At(idx); try { ProcessDataBase(res.second, res.first); } catch (QRunTimeError &err) { const Id &from = res.second; qWarning() << GetGroup().GetIndex(GetLocalId()) << GetLocalId().ToString() << "leader equivocated in message from" << GetGroup().GetIndex(from) << from.ToString() << "in session / round" << GetRoundId().ToString() << "in state" << StateToString(_state) << "causing the following exception: " << err.What(); // Should end round. break; } } }