def send_res_proof_to_clients(): output("Olympus: Res proofs for clients") for client_id in client_res_shuttle: if (not check_client_ready(client_id)): continue output("Olympus: Checking res proofs for client", client_id) res_stats = client_res_shuttle[client_id] result_hash_list=[] result_digest="" result="" result_proof={} for tup in res_stats: slot_id=tup[1] orig_stat=verify_signed_msg(rep_pub_keys[tup[2]], tup[0]) if (orig_stat): result = orig_stat['result'] res_op = orig_stat['op'] res_slot = orig_stat['slot_id'] result_digest = create_hash_and_encode_msg(result).digest result_hash_list.append(orig_stat['digest']) output("Olympus: Client: ",client_id,"Got result ",result,"from rep",tup[2], "at slot" , tup[1]) output("Olympus: Client: ",client_id,"Orig_res_stat: result ",result,"from rep",tup[2], "at slot" , res_slot, "and op", res_op) if (len(result_hash_list) == (int(nreplicas/2) + 1) and (len(set(result_hash_list)) == 1) and (result_digest == result_hash_list[0])): output("Olympus: Res proof Validated and Sending res proofs to client",client_id) result_proof['result_statements'] = result_hash_list send(('olymp_res_proof', result_proof, result, longest_slot_len + slot_id), to=client_config[client_id]) else: output("Olympus: Did not find a quorum of result proof for client", client_id)
def validate_result_proof(result_proof): output("Replica", myreplica_id, " :Trying to validate result proof") result_statements = result_proof['result_statements'] result = result_proof['result'] result_hash = create_hash_and_encode_msg(result).digest op_list = [] for index, rstat in enumerate(result_statements): #output (">>",index) sender_public_key_hex = rep_pub_keys[index] orig_stat = verify_signed_msg(sender_public_key_hex, rstat) if (orig_stat): #output ("Replica", myreplica_id, " :Verified signature of replica ", index) op_list.append(orig_stat['op']) if ((result == orig_stat['result']) and (result_hash == orig_stat['digest'])): continue else: output( "Replica", myreplica_id, " :result proof error, validation mismatch for sender ", index) return None else: output( "Replica", myreplica_id, " :result proof error, vCould not verify id of sender ", index) return None if (len(set(op_list)) != 1): output("Replica", myreplica_id, " :Invald operation in result proof") return None else: return 1
def validate_order_proof(order_proof, next_slot_id, sender_id): output("Olympus: Trying to validate order proof for rep", sender_id, "at slot ", next_slot_id) order_statements = order_proof['order_statements'] if (len(order_statements) != (sender_id+1)): output ("Olympus :Length of order proof not correct") return None operation = order_proof['op'] slot_id = order_proof['slot_id'] if (slot_id != next_slot_id): output("Olympus: Unexpected slot id in history from replica", sender_id) return None #output("slot_id", slot_id, "op:", operation) for index, ostat in enumerate(order_statements): #output (">>",index, ostat) sender_public_key_hex = rep_pub_keys[index] orig_stat=verify_signed_msg(sender_public_key_hex, ostat) if(orig_stat): #output ("Olympus: Verified signature of replica ", index) #output("validated order proof, type orig_stat", type(orig_stat), "sid", orig_stat['slot_id'], "op",orig_stat['op']) if ((slot_id == orig_stat['slot_id']) and (operation == orig_stat['op'])): continue else: output ("Olympus: Order Proof validation mismatch for replica ", index, "from sender", sender_id) return None else: output ("Olympus: Order Proof validation Could not verify id of replica ", index, "from sender", sender_id) return None return (slot_id, operation)
def receive(msg=('wedge_req', signed_wedge_msg)): output("\n\n") output("Replica", myreplica_id, " :Got wedge req from Olympus") wedge_req_msg_num += 1 failure = super().check_for_failures(-1, 'wedge_req', wedge_req_msg_num, rep_fail_triggers) if failure and any( x in failure for x in ["sleep", "crash", "extra_op", "drop", "increment_slot"]): pending_fail = apply_immediate_failure(mydict, failure, False) if (pending_fail == "drop"): return elif (failure): output("Replica", myreplica_id, " :Found failure", failure, "for wedge_req at msg num ", wedge_req_msg_num) super().update_relevant_failure(failure, "wedge_req", -1, wedge_req_msg_num, pending_failures) orig_msg = verify_signed_msg(olymp_config['pub_keys'], signed_wedge_msg) if orig_msg: send_hist = copy.deepcopy(history) mode = 2 if (len(pending_failures['wedge_msg']) != 0): next_failure = pending_failures['wedge_msg'].pop(0) output("Replica", myreplica_id, "next_fail", next_failure) if ("truncate_history" in next_failure[0]): p1 = re.search("(?<=\().*(?=\))", next_failure[0]) pair = p1.group() tr_len = int(pair.strip()) output("Replica", myreplica_id, " :Found failure truncate hist with len", tr_len) if (tr_len <= len(send_hist)): for i in range(0, tr_len): send_hist.pop() output("Replica", myreplica_id, " :Sending history with hist_len", len(send_hist)) send(('wedge_resp', myreplica_id, send_hist), to=olymp_config['config']) else: output("Replica", myreplica_id, " :Could not verify Olympus identity")
def receive(msg=('client_result_pkg', result, replica_id, signed_result_client, client_req_id, slot_id)): output("Client: ", myclient_id, " :Got result proof pkg from replica", replica_id) sender_public_key_hex = rep_pub_keys[ replica_id] # this cannot be a fn call, this is stored somewhere. orig_res_client = verify_signed_msg(sender_public_key_hex, signed_result_client) if not (orig_res_client): output("Client: ", myclient_id, " :Could NOT verify the identity of replica", replica_id) else: output("Client: ", myclient_id, " :verified sign of replica", replica_id) result_proof = orig_res_client['result_proof'] #maybe use slot_id and replica_id too? num_valid_replicas = validate_result_proof(result_proof, result) if not (num_valid_replicas): output("Client: ", myclient_id, " :Could NOT validate result proof for req_id", client_req_id) output("Client: ", myclient_id, "Notifying Olympus") #what to do now? else: #handle multiple responses for same req output("Client: ", myclient_id, " :Validated result proof from replica,", replica_id, "for req_id", client_req_id, "at slot_id", slot_id, "result", result) if ((client_req_id in valid_result_proofs) and (not valid_result_proofs[client_req_id])): output("Client: ", myclient_id, " :Accepted Res proof from replica,", replica_id, " for req_id", client_req_id, "with result", result, "and slot", slot_id, "for op", pending_op) valid_result_proofs[client_req_id] = True rep_res[slot_id] = result exp_res[client_req_id]['slot'] = slot_id else: output("Client: ", myclient_id, "already got result proof for req_id", client_req_id) return
def validate_result_proof(result_proof, result): output("Client: ", myclient_id, ":trying to validate result proof") result_statements = result_proof['result_statements'] #result = result_proof['result'] result_hash = create_hash_and_encode_msg(result).digest valid_reps = 0 op_list = [] shift = 0 if len((result_statements)) < nreplicas: output("Client: ", myclient_id, "Truncated res_proof of size ", len((result_statements))) shit = 1 for index, rstat in enumerate(result_statements): #output (">>",index) sender_public_key_hex = rep_pub_keys[index + shift] orig_stat = verify_signed_msg(sender_public_key_hex, rstat) if (orig_stat): #output ("Client", myclient_id, " :Verified signature of replica ", index) op_list.append(orig_stat['op']) if ((result_hash == orig_stat['digest'])): valid_reps += 1 continue else: output("Client: ", myclient_id, "Result proof error: mismatch for sender ", index) continue else: output("Client: ", myclient_id, "Result proof error: Could not verify id of sender ", index) continue if (len(set(op_list)) != 1): output("Client: ", myclient_id, "Invalid operation in result proof") is_op_invalid = True if (valid_reps >= (int(nreplicas / 2) + 1)): output("Client: ", myclient_id, "Got ", valid_reps, "valid results") return valid_reps else: return 0
def validate_order_proof(order_proof, next_slot_id, operation): output("Replica", myreplica_id, " :Trying to validate order proof") order_statements = order_proof['order_statements'] if (len(order_statements) != (myreplica_id)): output("Replica", myreplica_id, " :Length of order proof not correct") return (None, next_slot_id) expected_slot = next_slot_id slot_id = order_proof['slot_id'] if (slot_id != expected_slot): output("Replica", myreplica_id, " :OP validation did not expect this slot_id; exp:", expected_slot, "got ", slot_id) return (None, next_slot_id) for index, ostat in enumerate(order_statements): #output (">>",index, ostat) sender_public_key_hex = rep_pub_keys[index] orig_stat = verify_signed_msg(sender_public_key_hex, ostat) if (orig_stat): #output ("Replica", myreplica_id, " :Verified signature of replica ", index) #output("validated order proof, type orig_stat", type(orig_stat), "sid", orig_stat['slot_id'], "op",orig_stat['op']) if ((slot_id == orig_stat['slot_id']) and (operation == orig_stat['op'])): continue else: output("Replica: ", myreplica_id, "Order Proof validation mismatch for sender ", index) return (None, next_slot_id) else: output( "Replica: ", myreplica_id, "Order Proof validation Could not verify id of sender ", index) return (None, next_slot_id) next_slot_id += 1 return (1, next_slot_id)
def inject_failure(order_proof, result_proof, next_failure): output("Checking pending faiures for replica", myreplica_id) nreplicas = len(rep_config) trigger = next_failure[1] if "change_result" in next_failure[0]: output( "Replica", myreplica_id, " : { Trigger :", trigger, " : failure <change_result> } injected in result_shuttle_pkg") result_msg_hash = create_hash_and_encode_msg("OK") sender_public_key_hex = rep_pub_keys[myreplica_id] myindex = myreplica_id if (len(result_proof['result_statements']) < nreplicas): output( "Replica", myreplica_id, " : Changing result and btw, someone already dropped Head's result statement" ) myindex = myreplica_id - 1 orig_rstat = verify_signed_msg( sender_public_key_hex, result_proof['result_statements'][myindex]) if (orig_rstat): orig_rstat['digest'] = result_msg_hash.digest signed_result_stat = generate_signed_msg( orig_rstat, my_priv_key) result_proof['result_statements'][myindex] = signed_result_stat else: output("FAILED TO INJECT FAILURE : COuld not verify sign of ", myindex) elif "drop_result_stmt" in next_failure[0]: #is nullifying better than omitting output( "Replica", myreplica_id, " : { Trigger", trigger, " : failure <drop_result_stmt> } injected in result_shuttle_pkg" ) if (len(result_proof['result_statements']) < nreplicas): output( "Replica", myreplica_id, " : Someone already dropped Head's result statement, ignoring" ) else: output("Replica", myreplica_id, " : Dropping head res statement") del (result_proof['result_statements'][0]) elif "change_operation" in next_failure[0]: output( "Replica", myreplica_id, " : { Trigger", trigger, " : failure <change_operation> } injected in fwd_shuttle_pkg") sender_public_key_hex = rep_pub_keys[myreplica_id] orig_ostat = verify_signed_msg( sender_public_key_hex, order_proof['order_statements'][myreplica_id]) orig_rstat = verify_signed_msg( sender_public_key_hex, result_proof['result_statements'][myreplica_id]) if (orig_ostat and orig_rstat): orig_ostat['op'] = "get(x)" orig_rstat['op'] = "get(x)" signed_order_stat = generate_signed_msg( orig_ostat, my_priv_key) signed_result_stat = generate_signed_msg( orig_rstat, my_priv_key) order_proof['order_statements'][ myreplica_id] = signed_order_stat result_proof['result_statements'][ myreplica_id] = signed_result_stat else: output("Replica", myreplica_id, " : Invalid sign on order or rstat; order stat", orig_ostat, "result_stat", orig_rstat) elif "invalid_order_sig" in next_failure[0]: orig_ostat = order_proof['order_statements'][myreplica_id] invalid_ostat = gen_invalid_sign_msg(orig_ostat) order_proof['order_statements'][myreplica_id] = invalid_ostat output( "Replica", myreplica_id, " : { Trigger", trigger, " : failure <invalid_order_sig> } injected in fwd_shuttle_pkg") elif "invalid_result_sig" in next_failure[0]: myindex = myreplica_id if ((len(result_proof['result_statements']) < nreplicas) and am_I_tail): output( "Replica", myreplica_id, " : Invalidating result stat and btw, someone already dropped Head's result statement" ) myindex = myreplica_id - 1 orig_rstat = result_proof['result_statements'][myindex] invalid_rstat = gen_invalid_sign_msg(orig_rstat) result_proof['result_statements'][myindex] = invalid_rstat output( "Replica", myreplica_id, " : { Trigger", trigger, " : failure <invalid_result_sig> } injected in res_shuttle_pkg" )
def receive(msg=('client_op_req', signed_client_msg, client_id, client_req_id)): output("\n\n") if (mode == 2): output("Replica", myreplica_id, " :Client req in immutable mode, ignored") return TIMEOUT = mytimeout output("Replica", myreplica_id, " :Client_op request from client", client_id, "with req_id", client_req_id, "potential slot_id", next_slot_id) client_msg[client_id]['num_client_req'] += 1 failure = super().check_for_failures( client_id, 'client_req', client_msg[client_id]['num_client_req'], rep_fail_triggers) if failure and any( x in failure for x in ["sleep", "crash", "extra_op", "drop", "increment_slot"]): pending_fail = apply_immediate_failure(mydict, failure, False) if (pending_fail == "drop"): return elif (failure): output("Replica", myreplica_id, " :Found failure", failure, "for client", client_id, "at msg_num ", client_msg[client_id]['num_client_req']) super().update_relevant_failure( failure, 'client_request', client_id, client_msg[client_id]['num_client_req'], pending_failures) sender_public_key_hex = client_pub_keys[client_id] #0 is the client orig_client_msg = verify_signed_msg(sender_public_key_hex, signed_client_msg) if not (orig_client_msg): output("Replica", myreplica_id, " :Could NOT verify the identity of msg from client") return else: output("Replica", myreplica_id, " :Verified sign of client", client_id) is_retransmit = orig_client_msg['is_retransmit'] operation = orig_client_msg['operation'] if (is_retransmit): output("Replica", myreplica_id, " :This is a retransmitted request client-id", client_id, "with req", client_req_id) #do I have this result cached? key = (client_id, client_req_id) key = str(key) if (key in res_proof_cache): output("Replica", myreplica_id, " :Found cached result for", client_id, "with req id", client_req_id) result_proof = res_proof_cache[key]['cached_result_proof'] result = res_proof_cache[key]['cached_result'] order_proof = {} if (len(pending_failures['res_shuttle']) != 0): next_failure = pending_failures['res_shuttle'].pop(0) super().inject_failure(order_proof, result_proof, next_failure) send_shuttle = {'result_proof': result_proof} signed_send_shuttle = generate_signed_msg( send_shuttle, my_priv_key) send(('client_result_pkg', result, myreplica_id, signed_send_shuttle, client_req_id, longest_slot_len + req_slot_map[key]), to=client_config[client_id]) elif (not am_I_head): output("Replica", myreplica_id, " :Cache lookup for req", client_req_id, "from", client_id, "failed, Sending fwd req to head") send(('rep_fwd_req', operation, myreplica_id, client_id, client_req_id, signed_client_msg), to=rep_config[0]) exp_val = client_msg[client_id]['num_valid_res_shutl'] + 1 #wait for timer to expire or a res_shuttle to arrive, is the check correct #would it be good to check for specific req id output("Replica", myreplica_id, " :Starting timer waiting for (", client_req_id, client_id, ") to arrive") if (await (client_msg[client_id]['num_valid_res_shutl'] == exp_val)): result_proof = res_proof_cache[key][ 'cached_result_proof'] result = res_proof_cache[key]['cached_result'] order_proof = {} if (len(pending_failures['res_shuttle']) != 0): next_failure = pending_failures['res_shuttle'].pop( 0) super().inject_failure(order_proof, result_proof, next_failure) send_shuttle = {'result_proof': result_proof} signed_send_shuttle = generate_signed_msg( send_shuttle, my_priv_key) output("Replica", myreplica_id, " :Res proof arrived and sending to client ", client_id) if (not am_I_tail): #tail must have sent anyway send(('client_result_pkg', result, myreplica_id, signed_send_shuttle, client_req_id, longest_slot_len + req_slot_map[key]), to=client_config[client_id]) elif timeout(TIMEOUT): output( "Replica", myreplica_id, " :Timed out and Complaining to Olympus for req-id", client_req_id, "from client", client_id) send(('reconfig_req', myreplica_id, True), to=olymp_config['config']) elif (am_I_head): #head has ordered this operation output("Replica", myreplica_id, " or HEAD could not find (", client_id, client_req_id, ") in cache") handle_retransmitted_req(key, operation, myreplica_id, client_id, client_req_id, signed_client_msg) else: output("Replica", myreplica_id, " :Client_req got operation", operation) if (pending_slot_failure and am_I_head): output("Replica", myreplica_id, " :slot failure injected") next_slot_id += 1 pending_slot_failure = False is_result = 0 order_proof = {} key = (client_id, client_req_id) slot_key = str(key) #have an if check here? order_proof['slot_id'] = next_slot_id req_slot_map[slot_key] = next_slot_id next_slot_id += 1 order_proof['op'] = operation result_proof = {} result = apply_operation(mydict, operation) order_proof['order_statements'] = [] result_proof['result_statements'] = [] #result_proof['slot_id'] = [] send_shuttle = super().create_new_shuttle( order_proof, result_proof, myreplica_id, is_result, result, my_priv_key, operation) history.append(copy.deepcopy(order_proof)) recent_client_req_map.appendleft(client_id) signed_res_stat_map[client_id] = (copy.deepcopy( result_proof['result_statements'][-1]), copy.deepcopy( order_proof['slot_id']), myreplica_id) ''' if (am_I_head): if (dummy_msg_num == 4): return else: dummy_msg_num +=1 ''' if (len(pending_failures['fwd_shuttle']) != 0): next_failure = pending_failures['fwd_shuttle'].pop(0) super().inject_failure(order_proof, result_proof, next_failure) signed_new_fwd_shuttle = generate_signed_msg( send_shuttle, my_priv_key) send_to_correct_replica(rep_config, myreplica_id, signed_new_fwd_shuttle, result, is_result, client_id, client_req_id, send_shuttle, signed_client_msg)
def receive(msg=('signed_result_shuttle_pkg', replica_id, signed_res_shuttle, client_id, client_req_id)): output("\n\n") if (mode == 2): output("Replica", myreplica_id, " :Client req in immutable mode, ignored") return output("Replica", myreplica_id, " :Res_shuttle_pkg from replica", replica_id, "for client", client_id, "and req", client_req_id) sender_public_key_hex = rep_pub_keys[replica_id] client_msg[client_id]['num_res_shutl'] += 1 failure = super().check_for_failures( client_id, 'res_shutl', client_msg[client_id]['num_res_shutl'], rep_fail_triggers) if failure and any( x in failure for x in ["sleep", "crash", "extra_op", "drop", "increment_slot"]): pending_fail = apply_immediate_failure(mydict, failure, False) if (pending_fail == "drop"): return elif (failure): output("Replica", myreplica_id, " :Found failure", failure, "for client", client_id, "at msg_num ", client_msg[client_id]['num_res_shutl']) super().update_relevant_failure( failure, "result_shuttle", client_id, client_msg[client_id]['num_res_shutl'], pending_failures) orig_res_shuttle = verify_signed_msg(sender_public_key_hex, signed_res_shuttle) if not (orig_res_shuttle): output("Replica", myreplica_id, " :Could NOT verify the identity of ", replica_id) else: output("Replica", myreplica_id, " :Validated identity of ", replica_id) result_proof = orig_res_shuttle['result_proof'] order_proof = orig_res_shuttle['order_proof'] is_result = orig_res_shuttle['is_result'] if not (super().validate_result_proof(result_proof)): output("Replica", myreplica_id, " :Could NOT validate result proof") output("Replica", myreplica_id, " :Complaining to olympus") #what to do here else: client_msg[client_id]['num_valid_res_shutl'] += 1 cache_result_shuttle(result_proof, client_id, client_req_id) output("Replica", myreplica_id, " :Validated result proof") if (not am_I_head and (len(pending_failures['res_shuttle']) != 0)): next_failure = pending_failures['res_shuttle'].pop(0) super().inject_failure(order_proof, result_proof, next_failure) send_shuttle = { 'is_result': is_result, 'order_proof': order_proof, 'result_proof': result_proof } signed_new_res_shuttle = generate_signed_msg( send_shuttle, my_priv_key) result = result_proof['result'] if (signed_new_res_shuttle): send_to_correct_replica(rep_config, myreplica_id, signed_new_res_shuttle, result, is_result, client_id, client_req_id, send_shuttle, "") else: output("Replica", myreplica_id, " :Error in res shuttle")
def receive(msg=('signed_fwd_shuttle_pkg', replica_id, signed_fwd_shuttle, client_id, client_req_id, signed_client_msg)): if (mode == 2): output("Replica", myreplica_id, " :Client req in immutable mode, ignored") return output("\n\n") output("Replica", myreplica_id, " :Fwd_shuttle_pkg from replica", replica_id, "for client", client_id, "and req-id", client_req_id, "potential slot", next_slot_id) sender_public_key_hex = rep_pub_keys[replica_id] orig_fwd_shuttle = verify_signed_msg(sender_public_key_hex, signed_fwd_shuttle) client_public_key_hex = client_pub_keys[client_id] orig_client_msg = verify_signed_msg(client_public_key_hex, signed_client_msg) client_msg[client_id]['num_fwd_shutl'] += 1 failure = super().check_for_failures( client_id, 'fwd_shutl', client_msg[client_id]['num_fwd_shutl'], rep_fail_triggers) if failure and any( x in failure for x in ["sleep", "crash", "extra_op", "drop", "increment_slot"]): pending_fail = apply_immediate_failure(mydict, failure, False) if (pending_fail == "drop"): return elif (failure): output("Replica", myreplica_id, " :Found fwd_shutl failure", failure, "for client", client_id, "at msg num ", client_msg[client_id]['num_fwd_shutl']) super().update_relevant_failure( failure, "shuttle", client_id, client_msg[client_id]['num_fwd_shutl'], pending_failures) if (not orig_client_msg): output("Replica", myreplica_id, " :Could not verify signed client msg") return else: operation = orig_client_msg['operation'] if not (orig_fwd_shuttle): output("Replica", myreplica_id, " :fwd_pkg Could NOT verify the identity of msg from ", replica_id) return else: #orig_fwd_shuttle is of type Shuttle output("Replica", myreplica_id, " :verified sign of replica", replica_id) is_result = orig_fwd_shuttle['is_result'] order_proof = orig_fwd_shuttle['order_proof'] result_proof = orig_fwd_shuttle['result_proof'] #maybe use slot_id and replica_id too? (is_op_valid, next_slot_id) = super().validate_order_proof( order_proof, next_slot_id, operation) if not (is_op_valid): output("Replica", myreplica_id, " :Could NOT validate order proof") output("Replica", myreplica_id, " :Complaining to olympus") #what to do now? else: output("Replica", myreplica_id, " :validated order proof") output("Replica", myreplica_id, " : Slot_id", order_proof['slot_id'], "operation", operation) key = (client_id, client_req_id) key = str(key) req_slot_map[key] = order_proof['slot_id'] if (operation == "get(x)"): output("something went very wrong") #fail_var=-1 result = apply_operation(mydict, operation) if (am_I_tail): is_result = 1 else: is_result = 0 send_shuttle = super().create_new_shuttle( order_proof, result_proof, myreplica_id, is_result, result, my_priv_key, operation) if (am_I_tail): client_msg[client_id]['num_valid_res_shutl'] += 1 cache_result_shuttle(result_proof, client_id, client_req_id) history.append(copy.deepcopy(order_proof)) recent_client_req_map.appendleft(client_id) signed_res_stat_map[client_id] = ( copy.deepcopy(result_proof['result_statements'][-1]), copy.deepcopy(order_proof['slot_id']), myreplica_id, ) if (not am_I_tail and (len(pending_failures['fwd_shuttle']) != 0)): next_failure = pending_failures['fwd_shuttle'].pop(0) super().inject_failure(order_proof, result_proof, next_failure) if (am_I_tail and (len(pending_failures['res_shuttle']) != 0)): next_failure = pending_failures['res_shuttle'].pop(0) super().inject_failure(order_proof, result_proof, next_failure) signed_new_fwd_shuttle = generate_signed_msg( send_shuttle, my_priv_key) if (signed_new_fwd_shuttle): send_to_correct_replica(rep_config, myreplica_id, signed_new_fwd_shuttle, result, is_result, client_id, client_req_id, send_shuttle, signed_client_msg) else: output("Fwd: replica", myreplica_id, " :Error in fwd shuttle")