Skip to content
This repository has been archived by the owner on Mar 3, 2020. It is now read-only.

Commit

Permalink
KEP-882: small refactor in pbft
Browse files Browse the repository at this point in the history
  • Loading branch information
isabelsavannah committed Mar 27, 2019
1 parent cb7ebe2 commit 5ffd762
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 49 deletions.
108 changes: 59 additions & 49 deletions pbft/pbft.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1208,6 +1208,63 @@ pbft::validate_and_extract_checkpoint_hashes(const pbft_msg &viewchange_message)
return retval;
}

bool
pbft::is_valid_prepared_proof(const prepared_proof& proof, uint64_t valid_checkpoint_sequence) const
{
const bzn_envelope& pre_prepare_envelope{proof.pre_prepare()};

if (!this->is_peer(pre_prepare_envelope.sender()) || !this->crypto->verify(pre_prepare_envelope))
{
LOG(error) << "is_valid_prepared_proof - a pre prepare message has a bad envelope, or the sender is not in the peers list";
return false;
}

pbft_msg preprepare_message;
if (!preprepare_message.ParseFromString(pre_prepare_envelope.pbft()) || (preprepare_message.sequence() <= valid_checkpoint_sequence)
|| preprepare_message.type() != PBFT_MSG_PREPREPARE)
{
LOG(error) << "is_valid_prepared_proof - a pre prepare message has an invalid sequence number, or is malformed";
return false;
}

std::set<uuid_t> senders;
for (int j{0}; j < proof.prepare_size(); ++j)
{
bzn_envelope prepare_envelope{proof.prepare(j)};
if (!this->is_peer(prepare_envelope.sender()) || !this->crypto->verify(prepare_envelope))
{
LOG(error) << "is_valid_prepared_proof - a prepare message has a bad envelope, "
"the sender may not be in the peer list, or the envelope failed cryptographic verification";
return false;
}

// does the sequence number, view number and hash match those of the pre prepare
pbft_msg prepare_msg;
if (!prepare_msg.ParseFromString(prepare_envelope.pbft()) || prepare_msg.type() != PBFT_MSG_PREPARE)
{
LOG(error) << "is_valid_prepared_proof - a prepare message is invalid";
return false;
}

if (preprepare_message.sequence() != prepare_msg.sequence() || preprepare_message.view() != prepare_msg.view()
|| preprepare_message.request_hash() != prepare_msg.request_hash())
{
LOG(error) << "is_valid_prepared_proof - a pre prepare message has mismatched sequence, view or request hash";
return false;
}

senders.insert(prepare_envelope.sender());
}

if (senders.size() < 2 * this->max_faulty_nodes() + 1)
{
LOG(error) << "is_valid_prepared_proof - not enough prepares in a prepared_proof";
return false;
}

return true;
}

bool
pbft::is_valid_viewchange_message(const pbft_msg& viewchange_message, const bzn_envelope& original_msg) const
{
Expand Down Expand Up @@ -1243,58 +1300,11 @@ pbft::is_valid_viewchange_message(const pbft_msg& viewchange_message, const bzn_
return false;
}

// TODO: (see KEP-882) Refactor this block into a new method - Isabel: should extract a validate_prepared_proof method
// all the the prepared proofs are valid (contains a pre prepare and 2f+1 mathcin prepares)
for (int i{0}; i < viewchange_message.prepared_proofs_size(); ++i)
{
const bzn_envelope& pre_prepare_envelope{viewchange_message.prepared_proofs(i).pre_prepare()};

if (!this->is_peer(pre_prepare_envelope.sender()) || !this->crypto->verify(pre_prepare_envelope))
{
LOG(error) << "is_valid_viewchange_message - a pre prepare message has a bad envelope, or the sender is not in the peers list";
return false;
}

pbft_msg preprepare_message;
if (!preprepare_message.ParseFromString(pre_prepare_envelope.pbft()) || (preprepare_message.sequence() <= valid_checkpoint_sequence)
|| preprepare_message.type() != PBFT_MSG_PREPREPARE)
{
LOG(error) << "is_valid_viewchange_message - a pre prepare message has an invalid sequence number, or is malformed";
return false;
}

std::set<uuid_t> senders;
for (int j{0}; j < viewchange_message.prepared_proofs(i).prepare_size(); ++j)
{
bzn_envelope prepare_envelope{viewchange_message.prepared_proofs(i).prepare(j)};
if (!this->is_peer(prepare_envelope.sender()) || !this->crypto->verify(prepare_envelope))
{
LOG(error) << "is_valid_viewchange_message - a prepare message has a bad envelope, "
"the sender may not be in the peer list, or the envelope failed cryptographic verification";
return false;
}

// does the sequence number, view number and hash match those of the pre prepare
pbft_msg prepare_msg;
if (!prepare_msg.ParseFromString(prepare_envelope.pbft()) || prepare_msg.type() != PBFT_MSG_PREPARE)
{
LOG(error) << "is_valid_viewchange_message - a prepare message is invalid";
return false;
}

if (preprepare_message.sequence() != prepare_msg.sequence() || preprepare_message.view() != prepare_msg.view()
|| preprepare_message.request_hash() != prepare_msg.request_hash())
{
LOG(error) << "is_valid_viewchange_message - a pre prepare message has mismatched sequence, view or request hash";
return false;
}

senders.insert(prepare_envelope.sender());
}

if (senders.size() < 2 * this->max_faulty_nodes() + 1)
{
LOG(error) << "is_valid_viewchange_message - not enough prepares in a prepared_proof";
if (!this->is_valid_prepared_proof(viewchange_message.prepared_proofs(i), valid_checkpoint_sequence)){
LOG(error) << "is_valid_viewchange_message - prepared proof is invalid";
return false;
}
}
Expand Down
2 changes: 2 additions & 0 deletions pbft/pbft.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ namespace bzn

bool is_valid_newview_message(const pbft_msg& theirs, const bzn_envelope& original_theirs) const;

bool is_valid_prepared_proof(const prepared_proof& proof, uint64_t valid_checkpoint_sequence) const;

std::shared_ptr<bzn::node_base> get_node();

const peer_address_t& get_peer_by_uuid(const std::string& uuid) const override;
Expand Down

0 comments on commit 5ffd762

Please sign in to comment.