2018-09-11 14:31:09 412浏览
在比特币公链架构解析中,就曾提到过为了实现去中介化的设计,比特币设计了一套共识协议,并通过此协议来保证系统的稳定性和防攻击性。并且我们知道,截止目前使用最广泛,也是最被大家接受的共识算法,是我们先前介绍过的POW(proofofwork)工作量证明算法。目前市值排名前二的比特币和以太坊也是采用的此算法。
from hashlib import sha256 from datetime import datetime def generate_block(oldblock, bpm, address): """ :param oldblock: :param bpm: :param address: :return: """ newblock = { "Index": oldblock["Index"] + 1, "BPM": bpm, "Timestamp": str(datetime.now()), "PrevHash": oldblock["Hash"], "Validator": address } newblock["Hash"] = calculate_hash(newblock) return newblock def calculate_hash(block): record = "".join([ str(block["Index"]), str(block["BPM"]), block["Timestamp"], block["PrevHash"] ]) return sha256(record.encode()).hexdigest() def is_block_valid(newblock, oldblock): """ :param newblock: :param oldblock: :return: """ if oldblock["Index"] + 1 != newblock["Index"]: return False if oldblock["Hash"] != newblock["PrevHash"]: return False if calculate_hash(newblock) != newblock["Hash"]: return False return True
from socketserver import BaseRequestHandler, ThreadingTCPServer def run(): # start a tcp server serv = ThreadingTCPServer(('', 9090), HandleConn) serv.serve_forever()
import threading from queue import Queue, Empty # 定义变量 block_chain = [] temp_blocks = [] candidate_blocks = Queue() # 创建队列,用于线程间通信 announcements = Queue() validators = {} My_Lock = threading.Lock() class HandleConn(BaseRequestHandler): def handle(self): print("Got connection from", self.client_address) # validator address self.request.send(b"Enter token balance:") balance = self.request.recv(8192) try: balance = int(balance) except Exception as e: print(e) t = str(datetime.now()) address = sha256(t.encode()).hexdigest() validators[address] = balance print(validators) while True: announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,), daemon=True) announce_winner_t.start() self.request.send(b"\nEnter a new BPM:") bpm = self.request.recv(8192) try: bpm = int(bpm) except Exception as e: print(e) del validators[address] break # with My_Lock: last_block = block_chain[-1] new_block = generate_block(last_block, bpm, address) if is_block_valid(new_block, last_block): print("new block is valid!") candidate_blocks.put(new_block) self.request.send(b"\nEnter a new BPM:\n") annouce_blockchain_t = threading.Thread(target=annouce_blockchain, args=(self.request,), daemon=True) annouce_blockchain_t.start()
# validator address self.request.send(b"Enter token balance:") balance = self.request.recv(8192) try: balance = int(balance) except Exception as e: print(e) t = str(datetime.now()) address = sha256(t.encode()).hexdigest() validators[address] = balance print(validators)
announce_winner_t = threading.Thread(target=annouce_winner, args=(announcements, self.request,), daemon=True) announce_winner_t.start() def annouce_winner(announcements, request): """ :param announcements: :param request: :return: """ while True: try: msg = announcements.get(block=False) request.send(msg.encode()) request.send(b'\n') except Empty: time.sleep(3) continue
self.request.send(b"\nEnter a new BPM:") bpm = self.request.recv(8192) try: bpm = int(bpm) except Exception as e: print(e) del validators[address] break # with My_Lock: last_block = block_chain[-1] new_block = generate_block(last_block, bpm, address) if is_block_valid(new_block, last_block): print("new block is valid!") candidate_blocks.put(new_block)
annouce_blockchain_t = threading.Thread(target=annouce_blockchain, args=(self.request,), daemon=True) annouce_blockchain_t.start() def annouce_blockchain(request): """ :param request: :return: """ while True: time.sleep(30) with My_Lock: output = json.dumps(block_chain) try: request.send(output.encode()) request.send(b'\n') except OSError: pass
def pick_winner(announcements): """ 选择记账人 :param announcements: :return: """ time.sleep(10) while True: with My_Lock: temp = temp_blocks lottery_pool = [] # if temp: for block in temp: if block["Validator"] not in lottery_pool: set_validators = validators k = set_validators.get(block["Validator"]) if k: for i in range(k): lottery_pool.append(block["Validator"]) lottery_winner = choice(lottery_pool) print(lottery_winner) # add block of winner to blockchain and let all the other nodes known for block in temp: if block["Validator"] == lottery_winner: with My_Lock: block_chain.append(block) # write message in queue. msg = "\n{0} 赢得了记账权利\n".format(lottery_winner) announcements.put(msg) break with My_Lock: temp_blocks.clear()
def run(): # create a genesis block t = str(datetime.now()) genesis_block = { "Index": 0, "Timestamp": t, "BPM": 0, "PrevHash": "", "Validator": "" } genesis_block["Hash"] = calculate_hash(genesis_block) print(genesis_block) block_chain.append(genesis_block) thread_canditate = threading.Thread(target=candidate, args=(candidate_blocks,), daemon=True) thread_pick = threading.Thread(target=pick_winner, args=(announcements,), daemon=True) thread_canditate.start() thread_pick.start() # start a tcp server serv = ThreadingTCPServer(('', 9090), HandleConn) serv.serve_forever() def candidate(candidate_blocks): """ :param candidate_blocks: :return: """ while True: try: candi = candidate_blocks.get(block=False) except Empty: time.sleep(5) continue temp_blocks.append(candi) if __name__ == '__main__': run()
所以,我们这里用linux自带的命令nc,不知道nc怎么用的同学可以google或者mannc
输出如同所示
下面是我这边获得的3个block信息。
【关注微信公众号获取更多学习资料】