pbft/online.c

251 lines
7.2 KiB
C
Raw Normal View History

2025-01-25 00:01:36 -05:00
#include "online.h"
#include "hosts.h"
#include "msg.h"
#include <assert.h>
#include <openssl/sha.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern struct host *conns[1024];
extern int num_conns;
extern uint32_t curr_view;
extern uint32_t view_next_seq_num;
extern uint32_t state_machine_state;
extern struct msg_log *mlog;
extern struct msg_log *out_responses;
extern uint32_t glob_replica_index;
uint32_t small_digest(struct msg *request) {
char data[20] = {0};
char *out = malloc(32 * sizeof(char));
for (int i = 0; i < 32; i++) {
out[i] = 0;
}
data[0] = request->req_message;
((uint32_t *)data)[1] = request->option_value;
((uint64_t *)data)[1] = request->timestamp;
((uint32_t *)data)[4] = request->client_index;
SHA256((unsigned char *)data, 20, (unsigned char *)out);
uint32_t x = ((uint32_t *)out)[0];
free(out);
return x;
}
void handle_primary_recv_request(struct msg *request, struct sigpriv *privkey) {
struct msg *pre_prepare = init_msg();
uint32_t d = small_digest(request);
pre_prepare->msg_type = 1;
pre_prepare->seq = view_next_seq_num;
pre_prepare->view = curr_view;
pre_prepare->digest = d;
pre_prepare->signature = sign_msg(pre_prepare, privkey);
broadcast(conns, num_conns, parse_msg_as_packet(pre_prepare));
broadcast(conns, num_conns, parse_msg_as_packet(request));
struct msg_log *out_msg = malloc(sizeof(struct msg_log));
struct msg *o = malloc(sizeof(struct msg));
memcpy(o, request, sizeof(struct msg));
out_msg->m = o;
out_msg->next = mlog;
mlog = out_msg;
struct msg_log *out2 = malloc(sizeof(struct msg_log));
out2->m = pre_prepare;
out2->next = mlog;
mlog = out2;
}
void handle_send_prepare(struct msg *preprepare, struct sigpriv *privkey) {
struct msg *prepare = init_msg();
prepare->msg_type = 2;
prepare->seq = preprepare->seq;
prepare->view = preprepare->view;
prepare->server_index = glob_replica_index;
prepare->digest = preprepare->digest;
prepare->signature = sign_msg(prepare, privkey);
broadcast(conns, num_conns, parse_msg_as_packet(prepare));
struct msg_log *out2 = malloc(sizeof(struct msg_log));
out2->m = prepare;
out2->next = mlog;
mlog = out2;
}
void handle_send_commit(struct msg *msg, struct msg *prepare,
struct sigpriv *privkey) {
struct msg *commit = init_msg();
commit->msg_type = 3;
commit->seq = prepare->seq;
commit->view = prepare->view;
commit->server_index = glob_replica_index;
commit->digest = small_digest(msg);
commit->signature = sign_msg(commit, privkey);
broadcast(conns, num_conns, parse_msg_as_packet(commit));
struct msg_log *out2 = malloc(sizeof(struct msg_log));
out2->m = commit;
out2->next = mlog;
mlog = out2;
}
void handle_operation(struct msg *msg, struct sigpriv *privkey) {
struct msg *m = init_msg();
m->msg_type = 5;
if (msg->req_message == 0) {
state_machine_state += msg->option_value;
m->option_value = 1;
m->timestamp = msg->timestamp;
m->signature = sign_msg(m, privkey);
for (int i = 0; i < num_conns; i++) {
if ((uint32_t)conns[i]->replica_index == msg->client_index) {
send_to(conns[i], parse_msg_as_packet(m));
}
}
if (msg->client_index == glob_replica_index) {
struct msg_log *out_msg = malloc(sizeof(struct msg_log));
out_msg->m = m;
out_msg->next = out_responses;
out_responses = out_msg;
}
} else if (msg->req_message == 1) {
state_machine_state -= msg->option_value;
m->option_value = 1;
m->timestamp = msg->timestamp;
m->signature = sign_msg(m, privkey);
for (int i = 0; i < num_conns; i++) {
if ((uint32_t)conns[i]->replica_index == msg->client_index) {
send_to(conns[i], parse_msg_as_packet(m));
}
}
if (msg->client_index == glob_replica_index) {
struct msg_log *out_msg = malloc(sizeof(struct msg_log));
out_msg->m = m;
out_msg->next = out_responses;
out_responses = out_msg;
}
} else if (msg->req_message == 2) {
state_machine_state *= msg->option_value;
m->option_value = 1;
m->timestamp = msg->timestamp;
m->signature = sign_msg(m, privkey);
for (int i = 0; i < num_conns; i++) {
if ((uint32_t)conns[i]->replica_index == msg->client_index) {
send_to(conns[i], parse_msg_as_packet(m));
}
}
if (msg->client_index == glob_replica_index) {
struct msg_log *out_msg = malloc(sizeof(struct msg_log));
out_msg->m = m;
out_msg->next = out_responses;
out_responses = out_msg;
}
} else if (msg->req_message == 3) {
m->option_value = state_machine_state;
m->timestamp = msg->timestamp;
m->signature = sign_msg(m, privkey);
for (int i = 0; i < num_conns; i++) {
if ((uint32_t)conns[i]->replica_index == msg->client_index) {
send_to(conns[i], parse_msg_as_packet(m));
}
}
if (msg->client_index == glob_replica_index) {
struct msg_log *out_msg = malloc(sizeof(struct msg_log));
out_msg->m = m;
out_msg->next = out_responses;
out_responses = out_msg;
}
}
clean_msg(m);
}
bool prepared(struct msg_log *mlog, int f, struct msg *request, uint32_t view,
uint32_t seq) {
bool is_request_in = false;
bool is_preprepare_in = false;
uint8_t num_prepares = 0;
uint32_t digest_req = small_digest(request);
struct msg_log *m;
for (m = mlog; m != NULL; m = m->next) {
if (m->m->msg_type == 0 && request->msg_type == 0 &&
m->m->req_message == request->req_message &&
m->m->option_value == request->option_value &&
m->m->timestamp == request->timestamp &&
m->m->client_index == request->client_index) {
is_request_in = true;
}
if (m->m->msg_type == 1 && m->m->view == view && m->m->seq == seq &&
m->m->digest == digest_req) {
is_preprepare_in = true;
}
if (m->m->msg_type == 2 && m->m->view == view && m->m->seq == seq &&
m->m->digest == digest_req) {
num_prepares += 1;
}
}
return (is_request_in && is_preprepare_in && (num_prepares >= 2 * f));
}
bool committed_local(struct msg_log *mlog, int f, struct msg *request,
uint32_t view, uint32_t seq) {
bool is_prepared = prepared(mlog, f, request, view, seq);
uint32_t cor_seq = request->seq;
request->seq = 0;
uint32_t dg = small_digest(request);
request->seq = cor_seq;
struct msg_log *m;
uint8_t commits = 0;
for (m = mlog; m != NULL; m = m->next) {
if (m->m->msg_type == 3 && m->m->view == view && m->m->digest == dg &&
m->m->seq == request->seq) {
struct msg_log *k;
uint32_t factor = 1;
for (k = mlog; k != m; k = k->next) {
if (k->m->msg_type == 3 && k->m->view == view && k->m->digest == dg &&
k->m->seq == request->seq &&
k->m->server_index == m->m->server_index) {
factor = 0;
}
}
commits += 1 * factor;
}
}
// printf("committed? %d %d %d \n", is_prepared, commits, 2 * f + 1);
return (is_prepared && (commits >= 2 * f + 1));
}
uint32_t sign_msg(struct msg *_message, struct sigpriv *_key) { return 0; }
bool validate_signature(struct msg *_message, struct sigkey *_privkey) {
return true;
}
void *todo_key() { return NULL; }