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

Commit

Permalink
KEP-823 Remove Full Request from Saved and Retransmitted Pre-prepares
Browse files Browse the repository at this point in the history
  • Loading branch information
rnistuk authored and rnistuk committed Jun 17, 2019
1 parent 5db9ceb commit 7d5bd77
Show file tree
Hide file tree
Showing 12 changed files with 390 additions and 202 deletions.
2 changes: 1 addition & 1 deletion node/test/session_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ namespace bzn
io2->shutdown();
}

TEST_F(session_test2, additional_shutdown_handlers_can_be_added_to_session)
TEST_F(session_test2, DISABLED_additional_shutdown_handlers_can_be_added_to_session)
{
auto io2 = std::make_shared<bzn::asio::smart_mock_io>();

Expand Down
3 changes: 3 additions & 0 deletions pbft/operations/pbft_persistent_operation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ pbft_persistent_operation::record_request(const bzn_envelope& encoded_request)
case storage_result::exists:
LOG(debug) << "ignoring record of request for operation " << bzn::bytes_to_debug_string(this->prefix) << " because we already have one";
break;
case storage_result::value_too_large:
LOG(debug) << "request too large to store: " << encoded_request.SerializeAsString().size() << " bytes, " << bzn::bytes_to_debug_string(this->prefix);
break;
default:
throw std::runtime_error("failed to write request for operation " + bzn::bytes_to_debug_string(this->prefix));
}
Expand Down
222 changes: 170 additions & 52 deletions pbft/pbft.cpp

Large diffs are not rendered by default.

9 changes: 7 additions & 2 deletions pbft/pbft.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ namespace bzn
class pbft_test_database_response_is_forwarded_to_session_Test;
class pbft_test_add_session_to_sessions_waiting_can_add_a_session_and_shutdown_handler_removes_session_from_sessions_waiting_Test;
class pbft_test_pbft_wrap_message_sets_swarm_id_Test;
class pbft_test_ensure_save_all_requests_records_requests_Test;
}

using request_hash_t = std::string;
Expand Down Expand Up @@ -208,7 +209,7 @@ namespace bzn
bool move_to_new_configuration(const hash_t& config_hash, uint64_t view);
bool proposed_config_is_acceptable(std::shared_ptr<pbft_configuration> config);

void maybe_record_request(const pbft_msg& msg, const std::shared_ptr<pbft_operation>& op);
void maybe_record_request(const pbft_msg& msg, const bzn_envelope& env, const std::shared_ptr<pbft_operation>& op);

timestamp_t now() const;
bool already_seen_request(const bzn_envelope& msg, const request_hash_t& hash) const;
Expand All @@ -218,7 +219,7 @@ namespace bzn

// VIEWCHANGE/NEWVIEW Helper methods
void initiate_viewchange();
pbft_msg make_viewchange(uint64_t new_view, uint64_t n, const std::unordered_map<bzn::uuid_t, std::string>& stable_checkpoint_proof, const std::map<uint64_t, std::shared_ptr<bzn::pbft_operation>>& prepared_operations);
std::shared_ptr<bzn_envelope> make_viewchange(uint64_t new_view, uint64_t n, const std::unordered_map<bzn::uuid_t, std::string>& stable_checkpoint_proof, const std::map<uint64_t, std::shared_ptr<bzn::pbft_operation>>& prepared_operations);
pbft_msg make_newview(uint64_t new_view_index, const std::map<uuid_t,bzn_envelope>& viewchange_envelopes_from_senders, const std::map<uint64_t, bzn_envelope>& pre_prepare_messages) const;
pbft_msg build_newview(uint64_t new_view, const std::map<uuid_t,bzn_envelope>& viewchange_envelopes_from_senders) const;
std::map<bzn::checkpoint_t , std::set<bzn::uuid_t>> validate_and_extract_checkpoint_hashes(const pbft_msg &viewchange_message) const;
Expand All @@ -229,6 +230,9 @@ namespace bzn

void add_session_to_sessions_waiting(const std::string &msg_hash, std::shared_ptr<bzn::session_base> session);

std::map<bzn::hash_t, int> map_request_to_hash(const bzn_envelope& original_msg);
void save_all_requests(const pbft_msg& msg, const bzn_envelope& original_msg);

std::shared_ptr<bzn::storage_base> storage;

// Using 1 as first value here to distinguish from default value of 0 in protobuf
Expand Down Expand Up @@ -304,6 +308,7 @@ namespace bzn
FRIEND_TEST(bzn::test::pbft_test, database_response_is_forwarded_to_session);
FRIEND_TEST(bzn::test::pbft_test, add_session_to_sessions_waiting_can_add_a_session_and_shutdown_handler_removes_session_from_sessions_waiting);
FRIEND_TEST(bzn::test::pbft_test, pbft_wrap_message_sets_swarm_id);
FRIEND_TEST(bzn::test::pbft_test, ensure_save_all_requests_records_requests);

friend class pbft_proto_test;
friend class pbft_join_leave_test;
Expand Down
3 changes: 1 addition & 2 deletions pbft/test/pbft_audit_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,9 @@ namespace bzn::test
this->build_pbft();
this->pbft->set_audit_enabled(true);

bzn_envelope dummy_original_msg;
pbft_msg preprepare = pbft_msg(this->preprepare_msg);
preprepare.set_sequence(1);
this->pbft->handle_message(preprepare, dummy_original_msg);
this->pbft->handle_message(preprepare, this->default_original_msg);

for (const auto& peer : TEST_PEER_LIST)
{
Expand Down
27 changes: 23 additions & 4 deletions pbft/test/pbft_join_leave_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,21 @@ namespace bzn

MATCHER_P(message_has_req_with_correct_type, req_type, "")
{
// note: arg is a bzn_envelope
auto pmsg = extract_pbft_msg_option(*arg);
if (pmsg)
if (pmsg->has_request())
{
return pmsg->request().payload_case() == req_type;
}
else if (arg->piggybacked_requests_size())
{
if (pmsg->has_request())
for (int i{0}; i < arg->piggybacked_requests_size(); ++i)
{
return pmsg->request().payload_case() == req_type;
const auto request{arg->piggybacked_requests(i)};
if (request.payload_case() == req_type)
{
return true;
}
}
}
return false;
Expand All @@ -85,6 +94,7 @@ namespace bzn
class pbft_join_leave_test : public pbft_test
{
protected:

pbft_msg
send_new_config_preprepare(std::shared_ptr<bzn::pbft> pbft, std::shared_ptr<bzn::mock_node_base> mock_node,
const bzn::pbft_configuration &config)
Expand All @@ -97,6 +107,7 @@ namespace bzn
preprepare.set_view(1);
preprepare.set_sequence(1);
preprepare.set_type(PBFT_MSG_PREPREPARE);
preprepare.set_request_type(pbft_request_type::PBFT_REQUEST_INTERNAL);
preprepare.mutable_request()->set_pbft_internal_request(cfg_msg.SerializeAsString());

auto monitor = std::make_shared<NiceMock<bzn::mock_monitor>>();
Expand All @@ -109,7 +120,9 @@ namespace bzn
{
EXPECT_CALL(*(mock_node),
send_signed_message(bzn::make_endpoint(p),
AllOf(message_has_correct_req_hash(expect_hash), message_has_correct_pbft_type(PBFT_MSG_PREPARE))))
AllOf(
message_has_correct_req_hash(expect_hash) ,
message_has_correct_pbft_type(PBFT_MSG_PREPARE))))
.Times(Exactly(1));
}

Expand Down Expand Up @@ -379,6 +392,7 @@ namespace bzn
.WillOnce(Invoke([&](){return std::move(new_config_timer2);}))
.WillOnce(Invoke([&](){return std::move(join_retry_timer2);}));
EXPECT_CALL(*mock_io_context2, post(_)).WillRepeatedly(Invoke([](auto func){boost::asio::post(func);}));
EXPECT_CALL(*mock_options, get_swarm_id()).WillRepeatedly(Return("swarm_id"));
EXPECT_CALL(*mock_options, get_uuid()).WillRepeatedly(Return("uuid2"));
EXPECT_CALL(*mock_options, get_simple_options()).WillRepeatedly(ReturnRef(this->options->get_simple_options()));
auto monitor = std::make_shared<NiceMock<bzn::mock_monitor>>();
Expand Down Expand Up @@ -502,6 +516,7 @@ namespace bzn
.WillOnce(Invoke([&](){return std::move(new_config_timer3);}))
.WillOnce(Invoke([&](){return std::move(join_retry_timer3);}));
EXPECT_CALL(*mock_io_context3, post(_)).WillRepeatedly(Invoke([](auto func){boost::asio::post(func);}));
EXPECT_CALL(*mock_options3, get_swarm_id()).WillRepeatedly(Return("swarm_id"));
EXPECT_CALL(*mock_options3, get_uuid()).WillRepeatedly(Return("uuid3"));
EXPECT_CALL(*mock_options3, get_simple_options()).WillRepeatedly(ReturnRef(this->options->get_simple_options()));
auto pbft3 = std::make_shared<bzn::pbft>(mock_node3, mock_io_context3, TEST_PEER_LIST, mock_options3, mock_service3,
Expand All @@ -511,6 +526,9 @@ namespace bzn

// simulate that the new pbft has just joined the swarm and is waiting for a new_view
this->set_swarm_status_waiting(pbft3);
EXPECT_CALL(*(mock_node3),
send_signed_message(A<const boost::asio::ip::tcp::endpoint&>(), ResultOf(test::is_prepare, Eq(true))))
.Times(Exactly(TEST_PEER_LIST.size() + 1));
this->handle_newview(pbft3, *newview_env);
EXPECT_TRUE(this->is_in_swarm(pbft3));

Expand Down Expand Up @@ -590,6 +608,7 @@ namespace bzn

auto wmsg2 = wrap_pbft_msg(prepare);
wmsg2.set_sender(p.uuid);
(*wmsg2.add_piggybacked_requests()) = *envelope;
this->handle_prepare(prepare, wmsg2);
}));
}
Expand Down
20 changes: 18 additions & 2 deletions pbft/test/pbft_proto_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@

using namespace ::testing;

namespace
{
uint64_t MAX_REQUEST_SIZE{249 * 1024};
}

namespace bzn
{
using namespace test;
Expand Down Expand Up @@ -51,7 +56,9 @@ namespace bzn
bzn_envelope request;
database_msg dmsg;
dmsg.mutable_create()->set_key(std::string("key_" + std::to_string(++this->index)));
dmsg.mutable_create()->set_value(std::string("value_" + std::to_string(this->index)));

dmsg.mutable_create()->set_value(std::string(MAX_REQUEST_SIZE, 'a'));

request.set_database_msg(dmsg.SerializeAsString());
request.set_timestamp(this->now());
request.set_sender(this->pbft->get_uuid());
Expand All @@ -75,9 +82,18 @@ namespace bzn
preprepare.set_view(this->view);
preprepare.set_sequence(sequence);
preprepare.set_type(PBFT_MSG_PREPREPARE);
preprepare.set_allocated_request(new bzn_envelope(request));

if (request.payload_case() == bzn_envelope::kPbftInternalRequest)
{
preprepare.set_allocated_request(new bzn_envelope(request));
}

preprepare.set_request_hash(this->pbft->crypto->hash(request));
auto wmsg = wrap_pbft_msg(preprepare, peer.uuid);
if (request.payload_case() != bzn_envelope::kPbftInternalRequest)
{
*wmsg.add_piggybacked_requests() = request;
}
pbft->handle_message(preprepare, wmsg);
}

Expand Down
59 changes: 59 additions & 0 deletions pbft/test/pbft_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,4 +308,63 @@ namespace bzn::test

this->send_commits(1, 1, hash);
}


TEST_F(pbft_test, bzn_envelope_has_repeated_request_body_field)
{
// My goal here is to generate a bzn_envelope and ensure that it has the repeated request_body field
EXPECT_CALL(*mock_node, send_signed_message(A<const boost::asio::ip::tcp::endpoint&>(), A<std::shared_ptr<bzn_envelope>>())).Times(1).WillRepeatedly(Invoke(
[&](auto /*ep*/, auto msg)
{
EXPECT_EQ( 0, msg->piggybacked_requests_size());
auto piggybacked_requests = msg->mutable_piggybacked_requests();
EXPECT_TRUE(piggybacked_requests->empty());

bzn_envelope env;
*(msg->add_piggybacked_requests()) = env;
*(msg->add_piggybacked_requests()) = env;

EXPECT_FALSE(piggybacked_requests->empty());
EXPECT_EQ( 2, msg->piggybacked_requests_size());
}));

this->uuid = SECOND_NODE_UUID;
this->build_pbft();
EXPECT_FALSE(pbft->is_primary());

pbft->handle_database_message(this->request_msg, this->mock_session);
}


TEST_F(pbft_test, ensure_save_all_requests_records_requests)
{
EXPECT_CALL(*mock_node, send_signed_message(A<const boost::asio::ip::tcp::endpoint&>(), A<std::shared_ptr<bzn_envelope>>())).Times(1).WillRepeatedly(Invoke(
[&](auto /*ep*/, auto msg)
{
EXPECT_EQ( 0, msg->piggybacked_requests_size());
auto piggybacked_requests = msg->mutable_piggybacked_requests();
EXPECT_TRUE(piggybacked_requests->empty());

bzn_envelope env;
pbft_msg d_msg;
env.set_pbft(d_msg.SerializeAsString());

*(msg->add_piggybacked_requests()) = env;

d_msg.set_view(3);
env.set_pbft(d_msg.SerializeAsString());

*(msg->add_piggybacked_requests()) = env;

auto hash_to_env = this->pbft->map_request_to_hash(*msg);

EXPECT_FALSE(piggybacked_requests->empty());
EXPECT_EQ( 2u, hash_to_env.size());
}));

this->uuid = SECOND_NODE_UUID;
this->build_pbft();

this->pbft->handle_database_message(this->request_msg, this->mock_session);
}
}
7 changes: 4 additions & 3 deletions pbft/test/pbft_test_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,9 @@ namespace bzn::test
preprepare_msg.set_type(PBFT_MSG_PREPREPARE);
preprepare_msg.set_sequence(19);
preprepare_msg.set_view(1);
preprepare_msg.set_allocated_request(new bzn_envelope(this->request_msg));

preprepare_msg.set_request_hash(this->crypto->hash(this->request_msg));
*(this->default_original_msg.add_piggybacked_requests()) = this->request_msg;
}

void
Expand Down Expand Up @@ -194,12 +195,12 @@ namespace bzn::test
preprepare.set_request_hash(req_hash);
preprepare.set_type(PBFT_MSG_PREPREPARE);

bzn_envelope original;
if (request)
{
preprepare.set_allocated_request(new bzn_envelope(*request));
(*original.add_piggybacked_requests()) = *request;
}

bzn_envelope original;
original.set_pbft(preprepare.SerializeAsString());

this->pbft->handle_message(preprepare, original);
Expand Down
Loading

0 comments on commit 7d5bd77

Please sign in to comment.