diff --git a/crud/crud.cpp b/crud/crud.cpp index 1261d1d6..332eb38e 100644 --- a/crud/crud.cpp +++ b/crud/crud.cpp @@ -168,6 +168,7 @@ crud::send_response(const database_msg& request, const bzn::storage_result resul } else { + LOG(trace) << "Sending response via session"; session->send_signed_message(std::make_shared(env)); } } diff --git a/mocks/mock_node_base.hpp b/mocks/mock_node_base.hpp index c5690b4c..d0626561 100644 --- a/mocks/mock_node_base.hpp +++ b/mocks/mock_node_base.hpp @@ -38,6 +38,12 @@ class mock_node_base : public node_base { void(const boost::asio::ip::tcp::endpoint& ep, std::shared_ptr msg)); MOCK_METHOD2(multicast_signed_message, void(std::shared_ptr> eps, std::shared_ptr msg)); + MOCK_METHOD2(send_maybe_signed_message, + void(const boost::asio::ip::tcp::endpoint& ep, std::shared_ptr msg)); + MOCK_METHOD2(send_maybe_signed_message, + void(const bzn::uuid_t& uuid, std::shared_ptr msg)); + MOCK_METHOD2(multicast_maybe_signed_message, + void(std::shared_ptr> eps, std::shared_ptr msg)); }; } // namespace bzn diff --git a/mocks/mock_options_base.hpp b/mocks/mock_options_base.hpp index 03ffdec4..2184639c 100644 --- a/mocks/mock_options_base.hpp +++ b/mocks/mock_options_base.hpp @@ -86,6 +86,8 @@ class mock_options_base : public options_base { std::string()); MOCK_CONST_METHOD0(get_admission_window, size_t()); + MOCK_CONST_METHOD0(get_peer_message_signing, + bool()); }; } // namespace bzn diff --git a/mocks/smart_mock_node.cpp b/mocks/smart_mock_node.cpp index 5883ea3a..51ac9b58 100644 --- a/mocks/smart_mock_node.cpp +++ b/mocks/smart_mock_node.cpp @@ -32,12 +32,12 @@ bzn::smart_mock_node::smart_mock_node() } )); - EXPECT_CALL(*this, multicast_signed_message(_, _)).WillRepeatedly(Invoke( + EXPECT_CALL(*this, multicast_maybe_signed_message(_, _)).WillRepeatedly(Invoke( [&](auto endpoints, auto message) { for (const auto ep : *endpoints) { - this->send_signed_message(ep, message); + this->send_maybe_signed_message(ep, message); } })); } diff --git a/node/node.cpp b/node/node.cpp index 6ebd2fc8..bf0932b3 100644 --- a/node/node.cpp +++ b/node/node.cpp @@ -84,7 +84,7 @@ void node::register_error_handler(std::function error_handler) { - this->error_callback = error_handler; + this->error_callback = std::move(error_handler); } void @@ -274,6 +274,50 @@ node::send_signed_message(const bzn::uuid_t& uuid, std::shared_ptr } } +void +node::send_maybe_signed_message(const boost::asio::ip::tcp::endpoint& ep, std::shared_ptr msg) +{ + if (this->options->get_peer_message_signing()) + { + this->find_session(ep)->send_signed_message(msg); + } + else + { + msg->set_sender(this->options->get_uuid()); + msg->set_swarm_id(this->options->get_swarm_id()); + this->find_session(ep)->send_message(std::make_shared(msg->SerializeAsString())); + } +} + +void +node::multicast_maybe_signed_message(std::shared_ptr> eps, std::shared_ptr msg) +{ + this->io_context->post( + [self = shared_from_this(), msg, eps]() + { + for (const auto& ep : *eps) + { + self->send_maybe_signed_message(ep, msg); + } + }); +} + +void +node::send_maybe_signed_message(const bzn::uuid_t& uuid, std::shared_ptr msg) +{ + try + { + auto point_of_contact_address = this->pbft->get_peer_by_uuid(uuid); + boost::asio::ip::tcp::endpoint endpoint{bzn::make_endpoint(point_of_contact_address)}; + this->send_maybe_signed_message(endpoint, msg); + } + catch (const std::runtime_error& err) + { + LOG(error) << "Unable to send message to " << uuid << ": " << err.what(); + } +} + + void node::initialize_ssl_contexts() diff --git a/node/node.hpp b/node/node.hpp index 17ec0366..cfbc9f58 100644 --- a/node/node.hpp +++ b/node/node.hpp @@ -53,6 +53,12 @@ namespace bzn void send_signed_message(const bzn::uuid_t& uuid, std::shared_ptr msg) override; + void send_maybe_signed_message(const boost::asio::ip::tcp::endpoint& ep, std::shared_ptr msg) override; + + void multicast_maybe_signed_message(std::shared_ptr> eps, std::shared_ptr msg) override; + + void send_maybe_signed_message(const bzn::uuid_t& uuid, std::shared_ptr msg) override; + private: FRIEND_TEST(node, test_that_registered_message_handler_is_invoked); FRIEND_TEST(node, test_that_wrongly_signed_messages_are_dropped); diff --git a/node/node_base.hpp b/node/node_base.hpp index 2fde51de..a705534b 100644 --- a/node/node_base.hpp +++ b/node/node_base.hpp @@ -81,6 +81,30 @@ namespace bzn */ virtual void send_signed_message(const bzn::uuid_t& uuid, std::shared_ptr msg) = 0; + /** + * Send a message to a node identified by endpoint. If the sender field is empty or contains our uuid, the message will be + * signed before sending. If the sender field contains something else, an existing signature will be kept intact. + * @param ep host to send the message to + * @param msg message to send + */ + virtual void send_maybe_signed_message(const boost::asio::ip::tcp::endpoint& ep, std::shared_ptr msg) = 0; + + /** + * As send_signed_message, but send the same message to multiple recipients. The signature is computed only once + * and the whole operation is async. + * @param eps hosts to send the message to + * @param msg message to send + */ + virtual void multicast_maybe_signed_message(std::shared_ptr> eps, std::shared_ptr msg) = 0; + + /** + * Send a message to a node identified by uuid. If the sender field is empty or contains our uuid, the message will be + * signed before sending. If the sender field contains something else, an existing signature will be kept intact. + * @param uuid host to send the message to + * @param msg message to send + */ + virtual void send_maybe_signed_message(const bzn::uuid_t& uuid, std::shared_ptr msg) = 0; + }; } // bzn diff --git a/node/test/node_test.cpp b/node/test/node_test.cpp index 94c43f67..844c7b8f 100644 --- a/node/test/node_test.cpp +++ b/node/test/node_test.cpp @@ -229,7 +229,7 @@ namespace bzn auto mock_chaos = std::make_shared>(); auto mock_io_context = std::make_shared>(); auto options = std::make_shared(); - options->get_mutable_simple_options).set(bzn::option_names::CRYPTO_ENABLED_INCOMING, "true"); + options->get_mutable_simple_options().set(bzn::option_names::CRYPTO_ENABLED_INCOMING, "true"); auto monitor = std::make_shared>(); auto crypto = std::make_shared(options, monitor); auto mock_session = std::make_shared(); diff --git a/options/options.cpp b/options/options.cpp index afe035db..e08e1d14 100644 --- a/options/options.cpp +++ b/options/options.cpp @@ -287,3 +287,9 @@ options::get_admission_window() const { return this->raw_opts.get(ADMISSION_WINDOW); } + +bool +options::get_peer_message_signing() const +{ + return this->raw_opts.get(PEER_MESSAGE_SIGNING); +} \ No newline at end of file diff --git a/options/options.hpp b/options/options.hpp index 287a2366..e17dedee 100644 --- a/options/options.hpp +++ b/options/options.hpp @@ -84,6 +84,8 @@ namespace bzn size_t get_admission_window() const override; + bool get_peer_message_signing() const override; + private: size_t parse_size(const std::string& key) const; diff --git a/options/options_base.hpp b/options/options_base.hpp index 3e39248c..0f19fae0 100644 --- a/options/options_base.hpp +++ b/options/options_base.hpp @@ -245,5 +245,11 @@ namespace bzn * @return size */ virtual size_t get_admission_window() const = 0; + + /** + * Get whether we should sign/verify messages to peers + * @return true/false + */ + virtual bool get_peer_message_signing() const = 0; }; } // bzn diff --git a/options/simple_options.cpp b/options/simple_options.cpp index c2e60c8e..3afd6987 100644 --- a/options/simple_options.cpp +++ b/options/simple_options.cpp @@ -105,7 +105,10 @@ simple_options::build_options() "software stack used by swarm") (ADMISSION_WINDOW.c_str(), po::value()->default_value(30), - "admission control request window"); + "admission control request window") + (PEER_MESSAGE_SIGNING.c_str(), + po::value()->default_value(false), + "should peer messages be signed/verified"); po::options_description logging("Logging"); logging.add_options() diff --git a/options/simple_options.hpp b/options/simple_options.hpp index 95de9979..22397fa1 100644 --- a/options/simple_options.hpp +++ b/options/simple_options.hpp @@ -50,6 +50,7 @@ namespace bzn::option_names const std::string SIGNED_KEY = "signed_key"; const std::string OWNER_PUBLIC_KEY = "owner_public_key"; const std::string ADMISSION_WINDOW = "admission_window"; + const std::string PEER_MESSAGE_SIGNING = "peer_message_signing"; const std::string CHAOS_ENABLED = "chaos_testing_enabled"; const std::string CHAOS_NODE_FAILURE_SHAPE = "chaos_node_failure_shape"; diff --git a/pbft/pbft.cpp b/pbft/pbft.cpp index 5b255a66..e44395c9 100644 --- a/pbft/pbft.cpp +++ b/pbft/pbft.cpp @@ -85,8 +85,13 @@ pbft::start() this->node->register_for_message(bzn_envelope::kDatabaseResponse, std::bind(&pbft::handle_database_response_message, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); - this->node->register_for_message(bzn_envelope::kSwarmError, - std::bind(&pbft::handle_swarm_error_response_message, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); + this->node->register_for_message(bzn_envelope::kSwarmError, [weak_this = weak_from_this()](auto msg, auto session) + { + if (auto strong_this = weak_this.lock()) + { + strong_this->handle_swarm_error_response_message(msg, session); + } + }); this->node->register_error_handler([weak_this = this->weak_from_this()](const boost::asio::ip::tcp::endpoint& ep, const boost::system::error_code& ec) { @@ -194,7 +199,7 @@ pbft::handle_membership_message(const bzn_envelope& msg, std::shared_ptrcrypto->verify(msg))) + if ((!msg.sender().empty()) && this->options->get_peer_message_signing() && (!this->crypto->verify(msg))) { LOG(error) << "Dropping message with invalid signature: " << msg.ShortDebugString().substr(0, MAX_MESSAGE_SIZE); return; @@ -242,7 +247,7 @@ pbft::handle_message(const pbft_msg& msg, const bzn_envelope& original_msg) return; } - if ((!original_msg.sender().empty()) && (!this->crypto->verify(original_msg))) + if ((!original_msg.sender().empty()) && this->options->get_peer_message_signing() && (!this->crypto->verify(original_msg))) { LOG(error) << "Dropping message with invalid signature: " << original_msg.ShortDebugString().substr(0, MAX_MESSAGE_SIZE); return; @@ -317,12 +322,11 @@ pbft::send_error_response(const bzn_envelope& request_env, const std::shared_ptr bzn_envelope response; response.set_swarm_error(err.SerializeAsString()); - response.set_sender(this->uuid); response.set_timestamp(this->now()); response.set_swarm_id(this->options->get_swarm_id()); - return session->send_message(std::make_shared(response.SerializeAsString())); + session->send_message(std::make_shared(response.SerializeAsString())); } } @@ -584,7 +588,7 @@ pbft::broadcast(const bzn_envelope& msg) for (const auto& peer : *this->peers_beacon->current()) { - this->node->send_signed_message(make_endpoint(peer), msg_ptr); + this->node->send_maybe_signed_message(make_endpoint(peer), msg_ptr); } } @@ -623,7 +627,7 @@ pbft::async_signed_broadcast(std::shared_ptr msg_env) targets->emplace_back(bzn::make_endpoint(peer)); } - this->node->multicast_signed_message(std::move(targets), msg_env); + this->node->multicast_maybe_signed_message(std::move(targets), msg_env); } void @@ -1025,7 +1029,8 @@ pbft::validate_and_extract_checkpoint_hashes(const pbft_msg &viewchange_message) const bzn_envelope& envelope{viewchange_message.checkpoint_messages(i)}; checkpoint_msg checkpoint_message; - if (!this->crypto->verify(envelope) || !this->is_peer(envelope.sender()) || !checkpoint_message.ParseFromString(envelope.checkpoint_msg())) + if ((this->options->get_peer_message_signing() && !this->crypto->verify(envelope)) + || !this->is_peer(envelope.sender()) || !checkpoint_message.ParseFromString(envelope.checkpoint_msg())) { LOG (error) << "Checkpoint validation failure - unable to verify envelope"; continue; @@ -1046,7 +1051,8 @@ pbft::is_valid_prepared_proof(const prepared_proof& proof, uint64_t valid_checkp { const bzn_envelope& pre_prepare_envelope{proof.pre_prepare()}; - if (!this->is_peer(pre_prepare_envelope.sender()) || !this->crypto->verify(pre_prepare_envelope)) + if (!this->is_peer(pre_prepare_envelope.sender()) + || (this->options->get_peer_message_signing() && !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"; LOG(error) << "Sender: " << pre_prepare_envelope.sender() << " is " << (this->is_peer(pre_prepare_envelope.sender()) ? "" : "not ") << "a peer"; @@ -1065,7 +1071,8 @@ pbft::is_valid_prepared_proof(const prepared_proof& proof, uint64_t valid_checkp 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)) + if (!this->is_peer(prepare_envelope.sender()) || + (this->options->get_peer_message_signing() && !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"; @@ -1233,7 +1240,7 @@ pbft::is_valid_newview_message(const pbft_msg& theirs, const bzn_envelope& origi for (int i{0};i < theirs.pre_prepare_messages_size();++i) { - if (!this->crypto->verify(theirs.pre_prepare_messages(i))) + if (this->options->get_peer_message_signing() && !this->crypto->verify(theirs.pre_prepare_messages(i))) { LOG(error) << "is_valid_newview_message - unable to verify thier pre prepare message"; return false; @@ -1415,7 +1422,7 @@ pbft::save_checkpoint(const pbft_msg& msg) { const bzn_envelope& original_checkpoint{msg.checkpoint_messages(i)}; - if (!this->crypto->verify(original_checkpoint)) + if (this->options->get_peer_message_signing() && !this->crypto->verify(original_checkpoint)) { LOG(error) << "ignoring invalid checkpoint message"; continue; diff --git a/pbft/pbft_checkpoint_manager.cpp b/pbft/pbft_checkpoint_manager.cpp index 8a4c0021..68127121 100644 --- a/pbft/pbft_checkpoint_manager.cpp +++ b/pbft/pbft_checkpoint_manager.cpp @@ -88,7 +88,7 @@ pbft_checkpoint_manager::local_checkpoint_reached(const bzn::checkpoint_t& cp) auto msg_ptr = std::make_shared(msg); for (const auto& peer : *(this->peers_beacon->current())) { - this->node->send_signed_message(make_endpoint(peer), msg_ptr); + this->node->send_maybe_signed_message(make_endpoint(peer), msg_ptr); } if (cp.first == this->latest_local_checkpoint.value().first && cp.second != this->latest_local_checkpoint.value().second) @@ -291,7 +291,7 @@ pbft_checkpoint_manager::send_state_request() auto msg_ptr = std::make_shared(); msg_ptr->set_pbft_membership(msg.SerializeAsString()); - this->node->send_signed_message(selected_peer, msg_ptr); + this->node->send_maybe_signed_message(selected_peer, msg_ptr); } void diff --git a/pbft/test/pbft_audit_test.cpp b/pbft/test/pbft_audit_test.cpp index 3755ab76..7ceb3adb 100644 --- a/pbft/test/pbft_audit_test.cpp +++ b/pbft/test/pbft_audit_test.cpp @@ -17,9 +17,9 @@ namespace bzn::test { TEST_F(pbft_test, test_local_commit_sends_audit_messages) { - EXPECT_CALL(*mock_node, send_signed_message(A(), ResultOf(is_audit, Eq(false)))) + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), ResultOf(is_audit, Eq(false)))) .Times(AnyNumber()); - EXPECT_CALL(*mock_node, send_signed_message(A(), ResultOf(is_audit, Eq(true)))) + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), ResultOf(is_audit, Eq(true)))) .Times(Exactly(TEST_PEER_LIST.size())); this->build_pbft(); @@ -46,7 +46,7 @@ namespace bzn::test TEST_F(pbft_test, primary_sends_primary_status) { - EXPECT_CALL(*mock_node, send_signed_message(A(), ResultOf(is_audit, Eq(true)))) + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), ResultOf(is_audit, Eq(true)))) .Times(Exactly(TEST_PEER_LIST.size())); this->build_pbft(); @@ -58,7 +58,7 @@ namespace bzn::test TEST_F(pbft_test, nonprimary_does_not_send_primary_status) { - EXPECT_CALL(*mock_node, send_signed_message(A(), ResultOf(is_audit, Eq(true)))) + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), ResultOf(is_audit, Eq(true)))) .Times(Exactly(0)); this->uuid = SECOND_NODE_UUID; diff --git a/pbft/test/pbft_catchup_test.cpp b/pbft/test/pbft_catchup_test.cpp index a42bd7ed..dd1a2bd1 100644 --- a/pbft/test/pbft_catchup_test.cpp +++ b/pbft/test/pbft_catchup_test.cpp @@ -111,7 +111,7 @@ namespace bzn this->build_pbft(); // node shouldn't be sending any checkpoint messages right now - EXPECT_CALL(*mock_node, send_signed_message(A(), ResultOf(is_checkpoint, Eq(true)))) + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), ResultOf(is_checkpoint, Eq(true)))) .Times((Exactly(0))); auto nodes = TEST_PEER_LIST.begin(); @@ -124,7 +124,7 @@ namespace bzn // one more checkpoint message and the node should request state from a random node auto primary = this->pbft->get_current_primary().value(); - EXPECT_CALL(*mock_node, send_signed_message(A(), ResultOf(is_get_state, Eq(true)))) + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), ResultOf(is_get_state, Eq(true)))) .Times((Exactly(1))); bzn::peer_address_t node(*nodes++); @@ -144,7 +144,7 @@ namespace bzn } // since the node has this checkpoint it should NOT request state for it - EXPECT_CALL(*mock_node, send_signed_message(A(), ResultOf(is_get_state, Eq(true)))) + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), ResultOf(is_get_state, Eq(true)))) .Times((Exactly(0))); stabilize_checkpoint(100); EXPECT_EQ(this->cp_manager_timer_callback_count, 0u); @@ -176,7 +176,7 @@ namespace bzn // get the node to request state auto primary = this->pbft->get_current_primary().value(); - EXPECT_CALL(*mock_node, send_signed_message(A(), ResultOf(is_get_state, Eq(true)))) + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), ResultOf(is_get_state, Eq(true)))) .Times((Exactly(1))); auto nodes = TEST_PEER_LIST.begin(); @@ -210,7 +210,7 @@ namespace bzn // get the node to request state auto primary = this->pbft->get_current_primary().value(); - EXPECT_CALL(*mock_node, send_signed_message(A(), ResultOf(is_get_state, Eq(true)))) + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), ResultOf(is_get_state, Eq(true)))) .Times((Exactly(1))); auto nodes = TEST_PEER_LIST.begin(); diff --git a/pbft/test/pbft_checkpoint_tests.cpp b/pbft/test/pbft_checkpoint_tests.cpp index 359c5648..d14aa994 100644 --- a/pbft/test/pbft_checkpoint_tests.cpp +++ b/pbft/test/pbft_checkpoint_tests.cpp @@ -61,7 +61,7 @@ namespace bzn::test { for (const auto& peer : TEST_PEER_LIST) { - EXPECT_CALL(*node, send_signed_message(make_endpoint(peer), ResultOf(is_checkpoint, Eq(true)))); + EXPECT_CALL(*node, send_maybe_signed_message(make_endpoint(peer), ResultOf(is_checkpoint, Eq(true)))); } this->cp_manager->local_checkpoint_reached(this->cp); @@ -79,7 +79,7 @@ namespace bzn::test { for (const auto& peer : TEST_PEER_LIST) { - EXPECT_CALL(*node, send_signed_message(make_endpoint(peer), ResultOf(is_checkpoint, Eq(true)))); + EXPECT_CALL(*node, send_maybe_signed_message(make_endpoint(peer), ResultOf(is_checkpoint, Eq(true)))); } this->cp_manager->local_checkpoint_reached(this->cp); diff --git a/pbft/test/pbft_newview_test.cpp b/pbft/test/pbft_newview_test.cpp index aaadec47..4e6bb3c8 100644 --- a/pbft/test/pbft_newview_test.cpp +++ b/pbft/test/pbft_newview_test.cpp @@ -81,7 +81,7 @@ namespace bzn this->run_transaction_through_primary_times(2, current_sequence); bzn_envelope viewchange_envelope; - EXPECT_CALL(*mock_node, send_signed_message(A(), ResultOf(test::is_viewchange, Eq(true)))) + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), ResultOf(test::is_viewchange, Eq(true)))) .WillRepeatedly(Invoke([&](const auto & /*endpoint*/, const auto& viewchange_env) {viewchange_envelope = *viewchange_env;})); this->pbft->handle_failure(); diff --git a/pbft/test/pbft_proto_test.cpp b/pbft/test/pbft_proto_test.cpp index c1522f28..2d3387d4 100644 --- a/pbft/test/pbft_proto_test.cpp +++ b/pbft/test/pbft_proto_test.cpp @@ -37,7 +37,7 @@ namespace bzn { // after request is sent, SUT will send out pre-prepares to all nodes auto operation = std::shared_ptr(); - EXPECT_CALL(*this->mock_node, send_signed_message(A(), ResultOf(test::is_preprepare, Eq(true)))) + EXPECT_CALL(*this->mock_node, send_maybe_signed_message(A(), ResultOf(test::is_preprepare, Eq(true)))) .Times(Exactly(TEST_PEER_LIST.size())) .WillRepeatedly(Invoke([&](auto, auto wmsg) { @@ -74,7 +74,7 @@ namespace bzn pbft_proto_test::send_preprepare(uint64_t sequence, const bzn_envelope& request) { // after preprepare is sent, SUT will send out prepares to all nodes - EXPECT_CALL(*this->mock_node, send_signed_message(A(), ResultOf(test::is_prepare, Eq(true)))) + EXPECT_CALL(*this->mock_node, send_maybe_signed_message(A(), ResultOf(test::is_prepare, Eq(true)))) .Times(Exactly(TEST_PEER_LIST.size())); auto peer = *(TEST_PEER_LIST.begin()); @@ -103,7 +103,7 @@ namespace bzn pbft_proto_test::send_prepares(uint64_t sequence, const bzn::hash_t& request_hash) { // after prepares are sent, SUT will send out commits to all nodes - EXPECT_CALL(*this->mock_node, send_signed_message(A(), ResultOf(test::is_commit, Eq(true)))) + EXPECT_CALL(*this->mock_node, send_maybe_signed_message(A(), ResultOf(test::is_commit, Eq(true)))) .Times(Exactly(TEST_PEER_LIST.size())); for (const auto& peer : TEST_PEER_LIST) @@ -154,7 +154,7 @@ namespace bzn })); // after enough commits are sent, SUT will send out checkpoint message to all nodes - EXPECT_CALL(*this->mock_node, send_signed_message(A(), ResultOf(test::is_checkpoint, Eq(true)))) + EXPECT_CALL(*this->mock_node, send_maybe_signed_message(A(), ResultOf(test::is_checkpoint, Eq(true)))) .Times(Exactly(TEST_PEER_LIST.size())); } diff --git a/pbft/test/pbft_test.cpp b/pbft/test/pbft_test.cpp index a81ff896..7bb57e5d 100644 --- a/pbft/test/pbft_test.cpp +++ b/pbft/test/pbft_test.cpp @@ -34,7 +34,7 @@ namespace bzn::test TEST_F(pbft_test, test_requests_fire_preprepare) { this->build_pbft(); - EXPECT_CALL(*mock_node, send_signed_message(A(), ResultOf(is_preprepare, Eq(true)))) + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), ResultOf(is_preprepare, Eq(true)))) .Times(Exactly(TEST_PEER_LIST.size())); pbft->handle_database_message(this->request_msg, this->mock_session); @@ -71,7 +71,7 @@ namespace bzn::test TEST_F(pbft_test, test_different_requests_get_different_sequences) { this->build_pbft(); - EXPECT_CALL(*mock_node, send_signed_message(A(), _)).WillRepeatedly(Invoke(save_sequences)); + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), _)).WillRepeatedly(Invoke(save_sequences)); database_msg req, req2; req.mutable_header()->set_nonce(5); @@ -86,7 +86,7 @@ namespace bzn::test TEST_F(pbft_test, test_preprepare_triggers_prepare) { this->build_pbft(); - EXPECT_CALL(*mock_node, send_signed_message(A(), ResultOf(is_prepare, Eq(true)))) + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), ResultOf(is_prepare, Eq(true)))) .Times(Exactly(TEST_PEER_LIST.size())); this->pbft->handle_message(this->preprepare_msg, default_original_msg); @@ -95,7 +95,7 @@ namespace bzn::test TEST_F(pbft_test, test_wrong_view_preprepare_rejected) { this->build_pbft(); - EXPECT_CALL(*mock_node, send_signed_message(A(), _)).Times(Exactly(0)); + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), _)).Times(Exactly(0)); pbft_msg preprepare2(this->preprepare_msg); preprepare2.set_view(6); @@ -106,7 +106,7 @@ namespace bzn::test TEST_F(pbft_test, test_no_duplicate_prepares_same_sequence_number) { this->build_pbft(); - EXPECT_CALL(*mock_node, send_signed_message(A(), _)).Times(Exactly(TEST_PEER_LIST.size())); + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), _)).Times(Exactly(TEST_PEER_LIST.size())); pbft_msg preprepare2(this->preprepare_msg); preprepare2.set_request_hash("some other hash"); @@ -118,9 +118,9 @@ namespace bzn::test TEST_F(pbft_test, test_commit_messages_sent) { this->build_pbft(); - EXPECT_CALL(*mock_node, send_signed_message(A(), ResultOf(is_prepare, Eq(true)))) + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), ResultOf(is_prepare, Eq(true)))) .Times(Exactly(TEST_PEER_LIST.size())); - EXPECT_CALL(*mock_node, send_signed_message(A(), ResultOf(is_commit, Eq(true)))) + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), ResultOf(is_commit, Eq(true)))) .Times(Exactly(TEST_PEER_LIST.size())); this->pbft->handle_message(this->preprepare_msg, default_original_msg); @@ -343,7 +343,7 @@ namespace bzn::test const size_t reqs{5}; this->options->get_mutable_simple_options().set("admission_window", std::to_string(reqs)); this->build_pbft(); - EXPECT_CALL(*mock_node, send_signed_message(A(), ResultOf(is_preprepare, Eq(true)))) + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), ResultOf(is_preprepare, Eq(true)))) .Times(Exactly(TEST_PEER_LIST.size() * reqs)); this->request_msg.set_timestamp(now()); diff --git a/pbft/test/pbft_test_common.cpp b/pbft/test/pbft_test_common.cpp index 02748d1c..4e031f41 100644 --- a/pbft/test/pbft_test_common.cpp +++ b/pbft/test/pbft_test_common.cpp @@ -80,6 +80,9 @@ namespace bzn::test EXPECT_CALL(*(this->mock_node), register_error_handler(_)) .Times(Exactly(1)); + EXPECT_CALL(*(this->mock_node), send_maybe_signed_message(A(), _)) + .Times(AnyNumber()); + EXPECT_CALL(*(this->mock_io_context), make_unique_steady_timer()) .Times(AnyNumber()) .WillOnce( diff --git a/pbft/test/pbft_timestamp_test.cpp b/pbft/test/pbft_timestamp_test.cpp index 8762e46c..00ed062e 100644 --- a/pbft/test/pbft_timestamp_test.cpp +++ b/pbft/test/pbft_timestamp_test.cpp @@ -36,14 +36,14 @@ namespace bzn request.set_sender(TEST_NODE_UUID); // the first time we should get pre-prepare messages - EXPECT_CALL(*this->mock_node, send_signed_message(A(), ResultOf(test::is_preprepare, Eq(true)))) + EXPECT_CALL(*this->mock_node, send_maybe_signed_message(A(), ResultOf(test::is_preprepare, Eq(true)))) .Times(Exactly(TEST_PEER_LIST.size())); this->handle_request(request); auto request2 = bzn_envelope(request); // this time no pre-prepare should be issued - EXPECT_CALL(*this->mock_node, send_signed_message(A(), ResultOf(test::is_preprepare, Eq(true)))) + EXPECT_CALL(*this->mock_node, send_maybe_signed_message(A(), ResultOf(test::is_preprepare, Eq(true)))) .Times(Exactly(0)); std::shared_ptr session = std::make_shared(); EXPECT_CALL(*session, send_message(ResultOf(test::is_swarm_error, Eq(true)))); @@ -66,7 +66,7 @@ namespace bzn request.set_sender(TEST_NODE_UUID); // we should get pre-prepare messages - EXPECT_CALL(*this->mock_node, send_signed_message(A(), ResultOf(test::is_preprepare, Eq(true)))) + EXPECT_CALL(*this->mock_node, send_maybe_signed_message(A(), ResultOf(test::is_preprepare, Eq(true)))) .Times(Exactly(TEST_PEER_LIST.size())); this->handle_request(request); @@ -76,7 +76,7 @@ namespace bzn request2.set_timestamp(request2.timestamp() + 1); // again we should get pre-prepare messages - EXPECT_CALL(*this->mock_node, send_signed_message(A(), ResultOf(test::is_preprepare, Eq(true)))) + EXPECT_CALL(*this->mock_node, send_maybe_signed_message(A(), ResultOf(test::is_preprepare, Eq(true)))) .Times(Exactly(TEST_PEER_LIST.size())); this->handle_request(request2); @@ -90,7 +90,7 @@ namespace bzn request3.set_database_msg(dmsg3.SerializeAsString()); // again we should get pre-prepare messages - EXPECT_CALL(*this->mock_node, send_signed_message(A(), ResultOf(test::is_preprepare, Eq(true)))) + EXPECT_CALL(*this->mock_node, send_maybe_signed_message(A(), ResultOf(test::is_preprepare, Eq(true)))) .Times(Exactly(TEST_PEER_LIST.size())); this->handle_request(request3); } @@ -110,7 +110,7 @@ namespace bzn request.set_sender(TEST_NODE_UUID); // we should get pre-prepare messages - EXPECT_CALL(*this->mock_node, send_signed_message(A(), ResultOf(test::is_preprepare, Eq(true)))) + EXPECT_CALL(*this->mock_node, send_maybe_signed_message(A(), ResultOf(test::is_preprepare, Eq(true)))) .Times(Exactly(TEST_PEER_LIST.size())); this->handle_request(request); @@ -119,7 +119,7 @@ namespace bzn request2.set_sender(SECOND_NODE_UUID); // again we should get pre-prepare messages - EXPECT_CALL(*this->mock_node, send_signed_message(A(), ResultOf(test::is_preprepare, Eq(true)))) + EXPECT_CALL(*this->mock_node, send_maybe_signed_message(A(), ResultOf(test::is_preprepare, Eq(true)))) .Times(Exactly(TEST_PEER_LIST.size())); this->handle_request(request2); } @@ -138,7 +138,7 @@ namespace bzn request.set_sender(TEST_NODE_UUID); // we should NOT get pre-prepare messages since this is an old request - EXPECT_CALL(*this->mock_node, send_signed_message(A(), ResultOf(test::is_preprepare, Eq(true)))) + EXPECT_CALL(*this->mock_node, send_maybe_signed_message(A(), ResultOf(test::is_preprepare, Eq(true)))) .Times(Exactly(0)); std::shared_ptr session = std::make_shared(); diff --git a/pbft/test/pbft_viewchange_test.cpp b/pbft/test/pbft_viewchange_test.cpp index b69cdef3..711e0f41 100644 --- a/pbft/test/pbft_viewchange_test.cpp +++ b/pbft/test/pbft_viewchange_test.cpp @@ -133,7 +133,7 @@ namespace bzn this->run_transaction_through_primary_times(2, current_sequence); - EXPECT_CALL(*mock_node, send_signed_message(A(), ResultOf(test::is_viewchange, Eq(true)))) + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), ResultOf(test::is_viewchange, Eq(true)))) .WillRepeatedly(Invoke([&](const auto & /*endpoint*/, const auto &viewchange_env) { pbft_msg viewchange; @@ -175,7 +175,7 @@ namespace bzn this->run_transaction_through_primary_times(2, current_sequence); - EXPECT_CALL(*mock_node, send_signed_message(A(), ResultOf(test::is_viewchange, Eq(true)))) + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), ResultOf(test::is_viewchange, Eq(true)))) .WillRepeatedly(Invoke([&](const auto& /*endpoint*/, auto viewchange_env) { pbft_msg viewchange; @@ -323,8 +323,9 @@ namespace bzn { return std::move(grace_timer2); })); auto mock_options = std::make_shared(); - + EXPECT_CALL(*(mock_options), get_peer_message_signing()).Times(AnyNumber()); EXPECT_CALL(*mock_options, get_uuid()).WillRepeatedly(Invoke([](){return "uuid2";})); + EXPECT_CALL(*mock_options, get_swarm_id()).WillRepeatedly(Invoke([](){return "my_swarm";})); auto peers = static_peers_beacon_for(TEST_PEER_LIST); @@ -355,7 +356,7 @@ namespace bzn for (auto const &p : TEST_PEER_LIST) { EXPECT_CALL(*(this->mock_node), - send_signed_message(bzn::make_endpoint(p), ResultOf(test::is_viewchange, Eq(true)))) + send_maybe_signed_message(bzn::make_endpoint(p), ResultOf(test::is_viewchange, Eq(true)))) .Times(Exactly(1)) .WillRepeatedly(Invoke([&](auto, auto wmsg) { @@ -378,13 +379,13 @@ namespace bzn for (auto const &p : TEST_PEER_LIST) { - EXPECT_CALL(*mock_node2, send_signed_message(bzn::make_endpoint(p), ResultOf(test::is_newview, Eq(true)))) + EXPECT_CALL(*mock_node2, send_maybe_signed_message(bzn::make_endpoint(p), ResultOf(test::is_newview, Eq(true)))) .Times(Exactly(1)) .WillRepeatedly(Invoke([&](auto, auto wmsg) { if (p.uuid == TEST_NODE_UUID) { - EXPECT_CALL(*this->mock_node, send_signed_message(A(), ResultOf(test::is_prepare, Eq(true)))) + EXPECT_CALL(*this->mock_node, send_maybe_signed_message(A(), ResultOf(test::is_prepare, Eq(true)))) .Times(Exactly(20 * TEST_PEER_LIST.size())); pbft_msg msg; ASSERT_TRUE(msg.ParseFromString(wmsg->pbft())); @@ -394,7 +395,7 @@ namespace bzn })); } - EXPECT_CALL(*mock_node2, send_signed_message(A(), ResultOf(test::is_viewchange, Eq(true)))) + EXPECT_CALL(*mock_node2, send_maybe_signed_message(A(), ResultOf(test::is_viewchange, Eq(true)))) .Times(Exactly(TEST_PEER_LIST.size())); // get sut1 to generate viewchange message @@ -411,7 +412,7 @@ namespace bzn this->build_pbft(); bzn_envelope original_message; - EXPECT_CALL(*mock_node, send_signed_message(A(), ResultOf(test::is_viewchange, Eq(true)))).WillRepeatedly(Invoke([&](const auto & /*endpoint*/, const auto &viewchange_env) + EXPECT_CALL(*mock_node, send_maybe_signed_message(A(), ResultOf(test::is_viewchange, Eq(true)))).WillRepeatedly(Invoke([&](const auto & /*endpoint*/, const auto &viewchange_env) { original_message = *viewchange_env; })); this->run_transaction_through_primary_times(1, current_sequence);