SecureValueRecovery2/enclave/core/coretest/testingcore.cc
2023-05-05 16:25:12 -06:00

291 lines
9.1 KiB
C++

// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
#include "testingcore.h"
#include <gtest/gtest.h>
#include "util/bytes.h"
#include "replicagroup.h"
#include "testingclient.h"
namespace svr2::core::test {
TestingCore::TestingCore(ReplicaGroup& replica_group)
: replica_group_(replica_group) {
context::Context ctx;
enclaveconfig::InitConfig cfg = replica_group.get_init_config();
cfg.set_initial_timestamp_unix_secs(timer_secs_);
auto [core, err] = Core::Create(&ctx, cfg);
if (err != error::OK) {
LOG(ERROR) << "Could not create core: " << err;
CHECK(false);
}
core_ = std::move(core);
}
error::Error TestingCore::ProcessIncomingMessage() {
error::Error result = error::OK;
if (!active() || input_messages_.empty()) {
return result;
}
// send the commands and other messages to the enclave
LOG(VERBOSE) << "Core " << ID() << " processing first of "
<< input_messages_.size() << " messages";
context::Context ctx;
// take the input message
auto msg = std::move(input_messages_.front());
input_messages_.pop_front();
auto err = core_->Receive(&ctx, msg);
if (err != error::OK) {
// clear the messages and return error
env::test::SentMessages();
return err;
}
// get the responses
auto response_msgs = env::test::SentMessages();
// process according to type
peerid::PeerID to;
PeerMessage peer_msg;
for (auto& response : response_msgs) {
switch (response.inner_case()) {
case EnclaveMessage::kPeerMessage:
peer_msg = std::move(*response.mutable_peer_message());
// read who this message is *to*
to.FromString(peer_msg.peer_id());
// Now reset the peer_id in the message to our ID so the
// recipient knows who it is *from*
ID().ToString(peer_msg.mutable_peer_id());
peer_messages_out_[to].emplace_back(std::move(peer_msg));
break;
case EnclaveMessage::kH2EResponse:
h2e_responses_out_.emplace_back(response.h2e_response());
break;
default:
CHECK(false);
}
}
return error::OK;
}
error::Error TestingCore::ProcessAllIncomingMessages() {
while (!input_messages_.empty()) {
RETURN_IF_ERROR(ProcessIncomingMessage());
}
return error::OK;
}
error::Error TestingCore::ProcessNextH2EResponse() {
auto h2e_response = std::move(h2e_responses_out_.front());
h2e_responses_out_.pop_front();
auto request_id = h2e_response.request_id();
auto cl = open_client_requests_[request_id];
switch (h2e_response.inner_case()) {
case HostToEnclaveResponse::kStatus:
if (error::OK != h2e_response.status()) {
LOG(DEBUG) << ID() << " response for request " << request_id << " error: " << h2e_response.status();
return h2e_response.status();
}
break;
case HostToEnclaveResponse::kNewClientReply:
cl->HandleNewClientReply(h2e_response.new_client_reply());
break;
case HostToEnclaveResponse::kExistingClientReply:
cl->HandleExistingClientReply(h2e_response.existing_client_reply());
break;
case HostToEnclaveResponse::kGetEnclaveStatusReply:
break;
default:
CHECK(false);
}
return error::OK;
}
error::Error TestingCore::ProcessAllH2EResponses() {
while (!h2e_responses_out_.empty()) {
RETURN_IF_ERROR(ProcessNextH2EResponse());
}
return error::OK;
}
error::Error TestingCore::AddPeerMessage(PeerMessage&& peer_message) {
if (state_ == State::ACTIVE || state_ == State::PAUSED_SAVE_MSGS) {
peerid::PeerID other_id;
other_id.FromString(peer_message.peer_id());
LOG(VERBOSE) << " core " << ID() << " receiving message from " << other_id;
::svr2::UntrustedMessage req;
*req.mutable_peer_message() = std::move(peer_message);
input_messages_.emplace_back(std::move(req));
}
return error::OK;
}
error::Error TestingCore::ForwardOutgoingMessages() {
for (auto& [to, msgs] : peer_messages_out_) {
for (auto& msg : msgs) {
RETURN_IF_ERROR(replica_group_.SendMessage(to, msg));
}
}
peer_messages_out_.clear();
return error::OK;
}
error::Error TestingCore::ResetPeer(peerid::PeerID peer_id) {
LOG(VERBOSE) << "resetpeerreq " << core_->ID() << " -> " << peer_id;
UntrustedMessage msg;
auto reset_req = msg.mutable_reset_peer();
peer_id.ToString(reset_req->mutable_peer_id());
input_messages_.emplace_back(std::move(msg));
return error::OK;
}
error::Error TestingCore::PingPeer(peerid::PeerID peer_id) {
LOG(VERBOSE) << "pingreq " << core_->ID() << " -> " << peer_id;
UntrustedMessage msg;
auto host = msg.mutable_h2e_request();
host->set_request_id(next_request_id());
peer_id.ToString(host->mutable_ping_peer()->mutable_peer_id());
input_messages_.emplace_back(std::move(msg));
return error::OK;
}
error::Error TestingCore::GetEnclaveStatus() {
LOG(VERBOSE) << "getenclavestatus " << core_->ID();
UntrustedMessage msg;
auto host = msg.mutable_h2e_request();
host->set_request_id(next_request_id());
host->set_get_enclave_status(true);
input_messages_.emplace_back(std::move(msg));
return error::OK;
}
error::Error TestingCore::TimerTick() {
++timer_secs_;
LOG(VERBOSE) << "timertick " << core_->ID() << " secs: " << timer_secs_;
UntrustedMessage msg;
msg.mutable_timer_tick()->set_new_timestamp_unix_secs(timer_secs_);
input_messages_.emplace_back(std::move(msg));
return error::OK;
}
error::Error TestingCore::CreateNewRaftGroup() {
LOG(VERBOSE) << "createnewraftgroup " << core_->ID();
UntrustedMessage msg;
auto host = msg.mutable_h2e_request();
host->set_request_id(next_request_id());
host->set_create_new_raft_group(true);
input_messages_.emplace_back(std::move(msg));
return error::OK;
}
error::Error TestingCore::JoinRaft(peerid::PeerID peer_id) {
if (!peer_id.Valid()) {
return error::Peers_InvalidID;
}
LOG(VERBOSE) << "joinraftreq " << core_->ID() << " -> " << peer_id;
UntrustedMessage msg;
auto host = msg.mutable_h2e_request();
host->set_request_id(next_request_id());
auto req = host->mutable_join_raft();
peer_id.ToString(req->mutable_peer_id());
input_messages_.emplace_back(std::move(msg));
return error::OK;
}
error::Error TestingCore::RequestVoting() {
LOG(VERBOSE) << "requestvoting " << core_->ID();
UntrustedMessage msg;
auto host = msg.mutable_h2e_request();
host->set_request_id(next_request_id());
host->set_request_voting(true);
input_messages_.emplace_back(std::move(msg));
return error::OK;
}
error::Error TestingCore::Reconfigure(const enclaveconfig::EnclaveConfig& config) {
LOG(VERBOSE) << "reconfigure " << core_->ID();
config_ = config;
UntrustedMessage msg;
auto host = msg.mutable_h2e_request();
host->set_request_id(next_request_id());
host->mutable_reconfigure()->MergeFrom(config);
input_messages_.emplace_back(std::move(msg));
return error::OK;
}
error::Error TestingCore::RaftRemoval() {
LOG(VERBOSE) << "raft_removal " << core_->ID();
UntrustedMessage msg;
auto host = msg.mutable_h2e_request();
host->set_request_id(next_request_id());
host->set_request_removal(true);
input_messages_.emplace_back(std::move(msg));
return error::OK;
}
error::Error TestingCore::DeleteBackup(const std::string& client_authenticated_id) {
LOG(VERBOSE) << "deletebackup " << core_->ID();
UntrustedMessage msg;
auto host = msg.mutable_h2e_request();
host->set_request_id(next_request_id());
client::Request delete_;
delete_.mutable_delete_();
CHECK(delete_.SerializeToString(host->mutable_database_request()->mutable_request()));
host->mutable_database_request()->set_authenticated_id(client_authenticated_id);
input_messages_.emplace_back(std::move(msg));
return error::OK;
}
error::Error TestingCore::NewClientRequest(
TestingClient* client, std::string client_authenticated_id) {
LOG(VERBOSE) << "newclient " << core_->ID();
UntrustedMessage msg;
auto h2e_req = msg.mutable_h2e_request();
auto new_client_req = h2e_req->mutable_new_client();
auto request_id = next_request_id();
open_client_requests_[request_id] = client;
h2e_req->set_request_id(request_id);
new_client_req->set_client_authenticated_id(client_authenticated_id);
input_messages_.emplace_back(std::move(msg));
return error::OK;
}
// Backup or Restore
error::Error TestingCore::ExistingClientRequest(TestingClient* client,
uint64_t client_id,
std::string data) {
LOG(VERBOSE) << "existingclient " << core_->ID();
UntrustedMessage msg;
auto h2e_req = msg.mutable_h2e_request();
auto existing_client_req = h2e_req->mutable_existing_client();
auto request_id = next_request_id();
open_client_requests_[request_id] = client;
h2e_req->set_request_id(request_id);
existing_client_req->set_client_id(client_id);
existing_client_req->set_data(data);
input_messages_.emplace_back(std::move(msg));
return error::OK;
}
EnclaveReplicaStatus TestingCore::TakeExpectedEnclaveStatusReply() {
auto& h2e_response = h2e_responses_out_[0];
EXPECT_EQ(h2e_response.inner_case(), HostToEnclaveResponse::kGetEnclaveStatusReply);
auto result = std::move(h2e_response.get_enclave_status_reply());
h2e_responses_out_.pop_front();
return result;
}
}; // namespace svr2::core::test