def on_receive(receiver, type, msg_hash, N): if type == 'block': res = accept_block(receiver, msg_hash, N) else: res = accept_vote(receiver, msg_hash) return if res: is_in_attack_chain = get_block_field(msg_hash, 'is_in_attack_chain') dep = get_field(receiver, is_in_attack_chain, 'dependencies') if int(msg_hash) in dep.keys(): dep = get_field(receiver, is_in_attack_chain, 'dependencies') for child_hash in dep[int(msg_hash)][0]: on_receive(receiver, 'block', child_hash, N) for child_hash in dep[int(msg_hash)][1]: on_receive(receiver, 'vote', child_hash, N) # print("miner " + str(receiver) + " deletes " + \ # str(str(hash) +":" + str(dep[int(hash)])) + "from its dependencies") del dep[int(msg_hash)] #print("删除依赖") update_field(receiver, is_in_attack_chain, 'dependencies', dep)
def maybe_vote_last_checkpoint(miner, hash, is_in_attack_chain, N): target_block = hash #参数是str类型的 source_block = get_field(miner, is_in_attack_chain, 'highest_justified_checkpoint') #target_block_epoch是int型的数据,而vote表中target_epoch也是int型 target_block_epoch = get_block_field(target_block, 'epoch') miner_current_epoch = get_field(miner, is_in_attack_chain, 'current_epoch') if target_block_epoch > miner_current_epoch: miner_current_epoch = target_block_epoch #pdb.set_trace() update_field(miner, is_in_attack_chain, 'current_epoch', miner_current_epoch) if is_ancestor(miner, source_block, target_block, is_in_attack_chain): hash = random.randint(1, 10**30) sender = miner source_block_epoch = get_block_field(source_block, 'epoch') sql_vote = "insert into vote values("\ + "'" + str(hash) + "',"\ + str(sender) + ","\ + "'" + str(source_block) + "',"\ + "'" + str(target_block) + "',"\ + str(source_block_epoch) + ","\ + str(target_block_epoch) + ","\ + str(is_in_attack_chain) + ");" chain = 'attack' if is_in_attack_chain else 'honest' sql_broadcast = broadcast(chain, hash, (N + 1) * Block_Proposal_Time, miner, 'vote') db = pymysql.connect("localhost", "root", "root", "attack_casper") cur = db.cursor() cur.execute(sql_vote) cur.execute(sql_broadcast) db.commit() cur.close() db.close()
def miner_view(miner_id): blocks = [] if miner_id in miners['attacker']: processed = get_field(miner_id, 0, 'processed') for block_hash in processed: blocks.append(str(block_hash)) processed = get_field(miner_id, 1, 'processed') for block_hash in processed: blocks.append(str(block_hash)) else: processed = get_field(miner_id, 0, 'processed') for block_hash in processed: blocks.append(str(block_hash)) blocks = str(blocks) blocks = blocks.replace("[", "(") blocks = blocks.replace("]", ")") sql_get_block_info = "select hash, pre_hash, is_in_attack_chain, type, height"\ " from block where hash in " + blocks + " ;" db = pymysql.connect("localhost", "root", "root", "attack_casper") cur = db.cursor() cur.execute(sql_get_block_info) result = cur.fetchall() db.commit() cur.close() db.close() G = nx.DiGraph() for item in result: hash = item[0] pre_hash = item[1] height = item[4] G.add_node(hash, object=[item[3], height]) #item[3]是字符串类型,type if hash != pre_hash: G.add_edge(hash, pre_hash, object=item[2]) #item[2]是int型,is_in_attack_chain return G
def check_head(receiver, hash, is_in_attack_chain): highest_justified_checkpoint_hash = get_field( receiver, is_in_attack_chain, 'highest_justified_checkpoint') tail_membership = get_field(receiver, is_in_attack_chain, 'tail_membership') #print("观察is_ancestor函数") if is_ancestor(receiver, highest_justified_checkpoint_hash, \ tail_membership[int(hash)], is_in_attack_chain): update_field(receiver, is_in_attack_chain, 'head', hash) else: print('Wrong chain, reset the chain to be a descendant of the ' 'highest justified checkpoint.') max_height = get_block_field(highest_justified_checkpoint_hash, 'height') max_descendant = highest_justified_checkpoint_hash tails = get_field(receiver, is_in_attack_chain, 'tails') for _hash in tails: if is_ancestor(receiver, highest_justified_checkpoint_hash, _hash, is_in_attack_chain): new_height = get_block_field(tails[_hash], 'height') if new_height > max_height: max_descendant = tails[_hash] update_field(receiver, is_in_attack_chain, 'head', max_descendant)
def get_checkpoint_parent(receiver, is_in_attack_chain, hash): sql_block_info = "select height, pre_hash from block where hash = '" + str( hash) + "';" db = pymysql.connect("localhost", "root", "root", "attack_casper") cur = db.cursor() cur.execute(sql_block_info) res = cur.fetchall() db.commit() cur.close() db.close() height = res[0][0] pre_hash = res[0][1] tail_membership = get_field(receiver, is_in_attack_chain, 'tail_membership') #print("观察height 和 tail_membership[pre_hash]的值为多少") if height == 0: return None return tail_membership[int(pre_hash)]
def accept_vote(receiver, hash): source_hash = int(get_vote_field(hash, 'source_hash')) #是str转int target_hash = int(get_vote_field(hash, 'target_hash')) is_in_attack_chain = get_block_field(target_hash, 'is_in_attack_chain') processed = get_field(receiver, is_in_attack_chain, 'processed') #pdb.set_trace() if source_hash not in processed: dep = get_field(receiver, is_in_attack_chain, 'dependencies') if source_hash not in dep.keys(): dep[source_hash] = [[], []] #依赖分为两种,一种是区块,一种是vote,第一个list记录 dep[source_hash][1].append(int(hash)) update_field(receiver, is_in_attack_chain, 'dependencies', dep) return False justified = get_field(receiver, is_in_attack_chain, 'justified') if source_hash not in justified: return False if target_hash not in processed: dep = get_field(receiver, is_in_attack_chain, 'dependencies') if target_hash not in dep.keys(): dep[target_hash] = [[], []] #依赖分为两种,一种是区块,一种是vote,第一个list记录 dep[target_hash][1].append(int(hash)) update_field(receiver, is_in_attack_chain, 'dependencies', dep) return False if not is_ancestor(receiver, source_hash, target_hash, is_in_attack_chain): return False #TODO:增加一个vote的sender是否属于volidator验证集合的判断,毫无必要 sender = get_vote_field(hash, 'sender') votes = get_field(receiver, is_in_attack_chain, 'votes') if sender not in votes: votes[sender] = [] target_epoch = get_vote_field(hash, 'target_epoch') source_epoch = get_vote_field(hash, 'source_epoch') for past_vote_hash in votes[sender]: past_target_epoch = get_vote_field(past_vote_hash, 'target_epoch') if past_target_epoch == target_epoch: print("miner %d got slashed! " % sender) deposit = get_field(receiver, is_in_attack_chain, 'deposit') deposit[sender] = 0 update_field(receiver, is_in_attack_chain, 'deposit', deposit) #stake = get_field(receiver, is_in_attack_chain, 'stake') #需要更新deposit和stake return False past_source_epoch = get_vote_field(past_vote_hash, 'source_epoch') if (past_source_epoch < source_epoch and past_target_epoch > target_epoch)\ or (past_source_epoch > source_epoch and past_target_epoch < target_epoch): print("miner %d got slashed! " % sender) deposit = get_field(receiver, is_in_attack_chain, 'deposit') deposit[sender] = 0 update_field(receiver, is_in_attack_chain, 'deposit', deposit) return False votes[sender].append(int(hash)) update_field(receiver, is_in_attack_chain, 'votes', votes) print(f"miner %d accept the vote of hash {hash}" % receiver) deposit = get_field(receiver, is_in_attack_chain, 'deposit') vote_count = get_field(receiver, is_in_attack_chain, 'vote_count') if source_hash not in vote_count: vote_count[source_hash] = {} vote_count[source_hash][target_hash] = \ vote_count[source_hash].get(target_hash, 0) + deposit[sender] update_field(receiver, is_in_attack_chain, 'vote_count', vote_count) total = 0 for key in deposit.keys(): total += deposit[key] if vote_count[source_hash][target_hash] >= (total * 2) / 3: justified = get_field(receiver, is_in_attack_chain, 'justified') justified.append(target_hash) update_field(receiver, is_in_attack_chain, 'justified', justified) highest_justified_checkpoint = get_field( receiver, is_in_attack_chain, 'highest_justified_checkpoint') highest_justified_epoch = get_block_field(highest_justified_checkpoint, 'epoch') if target_epoch > highest_justified_epoch: highest_justified_checkpoint = target_hash update_field(receiver, is_in_attack_chain, 'highest_justified_checkpoint', target_hash) if target_epoch - source_epoch == 1: finalized = get_field(receiver, is_in_attack_chain, 'finalized') finalized.append(source_hash) update_field(receiver, is_in_attack_chain, 'finalized', finalized) return True
def accept_block(receiver, hash, N): sql_get_block_info = "select pre_hash, is_in_attack_chain, height from "\ + "block where hash = '" + str(hash) +"';" db = pymysql.connect("localhost", "root", "root", "attack_casper") cursor = db.cursor() cursor.execute(sql_get_block_info) res_info = cursor.fetchall() db.commit() cursor.close() db.close() pre_hash = int(res_info[0][0]) is_in_attack_chain = res_info[0][1] height = res_info[0][2] processed = get_field(receiver, is_in_attack_chain, 'processed') dep = get_field(receiver, is_in_attack_chain, 'dependencies') if pre_hash not in processed: if pre_hash not in dep.keys(): dep[pre_hash] = [[], []] #依赖分为两种,一种是区块,一种是vote,第一个list记录 dep[pre_hash][0].append(int(hash)) update_field(receiver, is_in_attack_chain, 'dependencies', dep) return print(f"miner %d accept the block of hash {hash}" % receiver) processed = processed + (int(hash), ) #pdb.set_trace() update_field(receiver, is_in_attack_chain, 'processed', processed) tail_membership = get_field(receiver, is_in_attack_chain, 'tail_membership') tails = get_field(receiver, is_in_attack_chain, 'tails') if height % EPOCH_SIZE == 0: tail_membership[int(hash)] = int(hash) tails[int(hash)] = int(hash) update_field(receiver, is_in_attack_chain, 'tail_membership', tail_membership) update_field(receiver, is_in_attack_chain, 'tails', tails) if receiver in validator: maybe_vote_last_checkpoint(receiver, hash, is_in_attack_chain, N) else: tail_membership[int(hash)] = tail_membership[pre_hash] update_field(receiver, is_in_attack_chain, 'tail_membership', tail_membership) sql_get_height = "select height from block where hash = '"\ + str(tails[tail_membership[int(hash)]]) + "';" db = pymysql.connect("localhost", "root", "root", "attack_casper") cur = db.cursor() cur.execute(sql_get_height) tail_height = cur.fetchall()[0][0] db.commit() cur.close() db.close() if height > tail_height: tails[tail_membership[int(hash)]] = int(hash) update_field(receiver, is_in_attack_chain, 'tails', tails) check_head(receiver, hash, is_in_attack_chain) return True