def nvprocess_view(self, vchange_list): for r in vchange_list: key = self.key_dict[r.inner.id] m = message.check(key, r) if m == None: return False return True
def nvprocess_prpr(self, prpr_list): for r in prpr_list: key = self.key_dict[r.inner.id] m = message.check(key, r) if m == None: return False out = self.create_request("PREP", r.inner.seq, r.inner.msg) self.broadcast_to_nodes(out) return True
def vprocess_prepare(self, vprep_dict, vpre_dict, last_checkpoint): max = 0 #[seq][id] -> req counter = {} for k1, v1 in vprep_dict.items(): if (not k1 in vpre_dict): return False, 0 dig = vpre_dict[k1].inner.msg key = self.key_dict[vpre_dict[k1].inner.id] r = message.check(key, vpre_dict[k1]) if r == None: return False, 0 for k2, v2 in v1.items(): # check sigs key = self.key_dict[v2.inner.id] r = message.check(key, v2) if r == None: return False, 0 #prepares need to be for the same digest if r.inner.msg != dig: return False if (vpre_dict[k1].inner.id == r.inner.id): return False, 0 if r.inner.seq < last_checkpoint: return False, 0 if r.inner.seq > max: max = r.inner.seq if r.inner.seq not in counter: counter[r.inner.seq] = 1 else: counter[r.inner.seq] += 1 for k in counter: if counter[k] < 2 * self.f: return False, 0 self.add_node_history(vpre_dict[k]) return True, max
def process_preprepare(self, req, fd): if req.inner.seq in self.node_message_log["PRPR"]: return None # the msg field for a preprepare should be the digest of the original client request try: client_req = request_pb2.Request() client_req.ParseFromString(req.outer) record_pbft(self.debuglog, client_req) client_key = self.key_dict[client_req.inner.id] client_req = message.check(client_key, client_req) if client_req == None or req.inner.msg != client_req.dig: print("FAILED PRPR OUTER SIGCHECK") return except: print("ERROR IN PRPR OUTER PROTOBUFF") raise if not req.inner.msg in self.active: #self.active[req.inner.msg] = (client_req, Timer(self.timeout, self.handle_timeout), fd) request_timer = Timer(self.timeout, self.handle_timeout, [client_req.dig, req.inner.view]) request_timer.daemon = True request_timer.start() self.active[client_req.dig] = (client_req, request_timer, fd) self.add_node_history(req) m = self.create_request("PREP", req.inner.seq, req.inner.msg) self.add_node_history(m) record_pbft(self.debuglog, m) self.inc_prep_dict(req.inner.msg) self.broadcast_to_nodes(m) if self.check_prepared_margin(req.inner.msg, req.inner.seq): record(self.debuglog, "PREPARED sequence number " + str(req.inner.seq)) m = self.create_request("COMM", req.inner.seq, req.inner.msg) self.broadcast_to_nodes(m) self.add_node_history(m) self.inc_comm_dict(m.inner.msg) record_pbft(self.debuglog, m) self.prepared[req.inner.seq] = req.inner.msg if self.check_committed_margin(m.inner.msg, m.inner.seq): record(self.debuglog, "COMMITTED sequence number " + str(m.inner.seq)) record_pbft(self.commitlog, m) self.execute_in_order(m)
def parse_request(self, request_bytes, fd): try: req = request_pb2.Request() req.ParseFromString(request_bytes) record_pbft(self.debuglog, req) print('req id', req.inner.id) key = self.key_dict[req.inner.id] req = message.check(key, req) if req == None: print("FAILED SIG CHECK SOMEWHERE") return except: req = None print("ERROR IN PROTOBUF TYPES") self.clean(fd) return print("got a ", req.inner.type, " request from ", req.inner.id, "VIEW", req.inner.view) if req.inner.view > self.view: if not req.inner.view in self.view_backlog: self.view_backlog = [req] else: self.view_backlog.append(req) if req.inner.view != self.view or not self.view_active: if req.inner.type != "VCHA" and req.inner.type != "NEVW" and req.inner.type != "CHKP" and req.inner.type != "REQU": print("Bad view number", "TYPE:", req.inner.type, "ID", req.inner.id, "SEQ", req.inner.seq, "VIEW", req.inner.view) return if self.in_node_history(req): pass if req.inner.type in self.request_types and not self.in_client_history( req): self.request_types[req.inner.type](req, fd) else: self.clean(fd) print("BAD MESSAGE TYPE ..." + req.inner.type + "..." + str(req.inner.id))
def process_new_view(self, req, fd): print("Received a new_view from " + str(req.inner.id)) # parse requests by type m = req.inner.msg vchange_list = [] prpr_list = [] counter = 0 while len(m) > 0: counter += 1 print("COUNTER", counter) b = m[:4] size = struct.unpack("!I", b)[0] try: r2 = request_pb2.Request() r2.ParseFromString(m[4:size + 4]) record_pbft(self.debuglog, r2) key = self.key_dict[r2.inner.id] r2 = message.check(key, r2) if r2 == None: print("FAILED SIG CHECK IN NEW VIEW") return except: r2 = None print("FAILED PROTOBUF EXTRACT IN NEW VIEW") return if r2.inner.type == "VCHA": vchange_list.append(r2) if r2.inner.type == "PRPR": prpr_list.append(r2) m = m[size + 4:] if not self.nvprocess_view(vchange_list): print("FAILED VCHANGE VALIDATION IN NEW VIEW") return if req.inner.view >= self.view: print("Old view ", self.view) self.view = req.inner.view print("New view ", self.view, "accepted") self.view_active = True self.primary = self.view % self.N self.active = {} # HACK temp = self.client_backlog self.client_backlog = [] for client_req in temp: self.process_client_request(client_req, 0) #X#X#X#X#X self.reset_message_log() self.client_message_log = {} self.prepared = {} rc2 = self.nvprocess_prpr(prpr_list) self.vc_timer.cancel() if self.view in self.view_backlog: for r in self.view_backlog[self.view]: self.request_types[r.inner.type](r, 0) del self.view_backlog[self.view] print("canceling vc_timer") return
def process_view_change(self, req, fd): print("My current view: ", self.view) print("Received a view change req from " + str(req.inner.id)) print(req.inner.view) self.add_node_history(req) new_v = req.inner.view if new_v < self.view: return if new_v == self.view and self.view_active: return if new_v % self.N == self.id: print("VC WHERE I AM LEADER") vcheck_list = [] vpre_dict = {} vprep_dict = {} m = req.inner.msg # for each chkp, prpr, prep message it contains while len(m) > 0: b = m[:4] size = struct.unpack("!I", b)[0] try: #if True: r2 = request_pb2.Request() r2.ParseFromString(m[4:size + 4]) record_pbft(self.debuglog, r2) key = self.key_dict[r2.inner.id] r2 = message.check(key, r2) if r2 == None: print("FAILED SIG CHECK IN VIEW CHANGE") return except: #else: r2 = None print("FAILED PROTOBUF EXTRACT IN VIEW CHANGE") raise return if r2.inner.type == "CHKP": vcheck_list.append(r2) if r2.inner.type == "PREP": if not r2.inner.seq in vprep_dict: vprep_dict[r2.inner.seq] = {r2.inner.id: r2} else: vprep_dict[r2.inner.seq][r2.inner.id] = r2 if r2.inner.type == "PRPR": vpre_dict[r2.inner.seq] = r2 m = m[size + 4:] rc1 = self.vprocess_checkpoints(vcheck_list, req.inner.seq) rc2, max = self.vprocess_prepare(vprep_dict, vpre_dict, req.inner.seq) if rc1 and rc2: if new_v not in self.view_dict: self.view_dict[new_v] = ([req], 0, 0) else: if not self.in_view_dict(req): self.view_dict[new_v][0].append(req) else: print("bad vc request") return if len(self.view_dict[new_v][0]) > self.f: if self.active and self.view < new_v: self.handle_timeout(0, self.view) if len(self.view_dict[new_v][0]) > 2 * self.f: self.vc_timer = Timer(self.timeout, self.handle_timeout, [req.dig, self.view]) self.vc_timer.start() print("started vc_timer") if new_v % self.N != self.id: return # set min and max if self.view_dict[new_v][1] < req.inner.seq: #self.view_dict[new_v][1] = req.inner.seq temp = self.view_dict[new_v] self.view_dict[new_v] = (temp[0], req.inner.seq, temp[2]) if self.view_dict[new_v][2] < max: #self.view_dict[new_v][2] = max temp = self.view_dict[new_v] self.view_dict[new_v] = (temp[0], temp[1], max) # proccess and send the new view request if ((not self.view_active) or new_v > self.view) and len( self.view_dict[new_v][0]) > 2 * self.f: msg = "" for i in self.view_dict[new_v][0]: msg += serialize(i) for i in range(self.view_dict[new_v][1], self.view_dict[new_v][2]): if i == 0: continue try: r = self.node_message_log["PRPR"][i][self.primary] except: continue temp = self.create_request("PRPR", i, r.inner.msg) msg += serialize(temp) out = self.create_request("NEVW", 0, msg) self.view_active = True self.primary = self.view % self.N self.active = {} self.reset_message_log() self.client_message_log = {} self.prepared = {} self.seq = self.view_dict[new_v][2] self.broadcast_to_nodes(out) temp = self.client_backlog self.client_backlog = [] for client_req in temp: self.process_client_request(client_req, 0) self.vc_timer.cancel() print("canceling vc_timer") print("Entering New view", self.view)