class Miner(threading.Thread): def __init__(self, world, id): super(Miner, self).__init__() self._world = world self._id = id self._dig_times = 0 self._log = Logger('miner') # self._chains = [] self._work_chain = BlockChain() self._stop = False def get_id(self): return self._id def run(self): # do dig self._log.log().debug('Starting miner') self.dig() def dig(self): var = 1 while (var == 1): self._dig_times = self._dig_times + 1 self._log.log().debug("miner[" + str(self._id) + "]: digging " + str(self._dig_times)) if (self._stop): break curr_chain = self._work_chain time.sleep(1) # 检查_work_chain是否变化了。 if (curr_chain != self._work_chain): continue content = "miner[" + str(self._id) + "]: dig[" + str( self._dig_times) + "]" preblock = self._work_chain.get_head() new_block = Block.build_new_block(preblock, content) # 需要与receive block chain互斥 self._work_chain.append(new_block) self._world.notify_block_chain(self._work_chain) def stop(self): self._stop = True def receive_block_chain(self, block_chain): # find = False # for chain in self._chains: # if (block_chain.get_head() == chain.get_head()): # find = True # # if (find == False): # self._chains.append(block_chain); # if (chain.get_len() - self._work_chain.get_len() > 1): # self._work_chain = block_chain self._log.log().debug("miner[" + str(self._id) + "]: receive a block chain ") if (block_chain.get_len() - self._work_chain.get_len() > 1): self._work_chain = block_chain
def syns_all(save_data=False): best_chain = sync_local() for peer in cnst.PEERS: peer_block_chain_url = peer + 'blockchain' try: req = requests.get(peer_block_chain_url) peer_blockchain_dict = req.json() peer_blocks = [ dict_to_object(bcDict) for bcDict in peer_blockchain_dict ] peer_chain = BlockChain() peer_chain.chainList = peer_blocks if block_chain.isValid(chainList=peer_blocks) and len( peer_chain.chainList) > len(best_chain.chainList): best_chain = peer_chain except requests.exceptions.ConnectionError as e: print(e) if save_data: best_chain.save_block_chain() return best_chain
def __init__(self, port, crypto_curve, signature_algo,start_reward, decrease_reward, local_img_path, api_addr): self.PORT = port self.CURVE = crypto_curve self.SIGNATURE_ALGORITHM = signature_algo self.DECREASE_REWAD = decrease_reward self.IMG_PATH = local_img_path self.API_ADDR = api_addr self.reward = start_reward # Start generating private & public key self._private_key = ec.generate_private_key(self.CURVE, default_backend()) self.public_key_obj = self._private_key.public_key() self.public_key = StupidPublicKey(self.public_key_obj.public_numbers().x, self.public_key_obj.public_numbers().y) self.address = self.generate_address(self.public_key) self.chain = BlockChain() self.mempool = [] self.is_mining = False self.fucking_delay = 0 self.create_fee = 5 self.img_library = {} self.own_data = [] # Create a local_img folder if not os.path.isdir(self.IMG_PATH): os.mkdir(self.IMG_PATH)
def shake_loop(self): while True: if self.txs: data = [tx.serialize() for tx in self.txs] msg = Msg(Msg.TRANSACTION_MSG, data) self.send(msg) self.txs.clear() else: log.info("shake") block_chain = BlockChain() block = block_chain.get_last_block() try: genesis_block = block_chain[0] except IndexError as e: genesis_block = None data = { "last_height": -1, "genesis_block": "" } if genesis_block: data = { "last_height": block.block_header.height, "genesis_block": genesis_block.serialize() } msg = Msg(Msg.HAND_SHAKE_MSG, data) self.send(msg) time.sleep(10)
def handle_synchronize(self, msg): # 7.10 synchronize_range = msg.get("data", 1) block_chain = BlockChain() data = [] log.info("------client handle_synchronize with range " + str(synchronize_range[0]) + " " + str(synchronize_range[1]) + "------") for height in range(synchronize_range[0], synchronize_range[1]): already_get = False for i in range(0, 2): block = None try: block = block_chain.get_block_by_height(height) except: continue if block: already_get = True break if already_get: data.append(block.serialize()) elif data: msg = Msg(Msg.SYNCHRONIZE_MSG, data) self.send(msg) return else: msg = Msg(Msg.NONE_MSG, "") self.send(msg) return msg = Msg(Msg.SYNCHRONIZE_MSG, data) self.send(msg)
def handle_get_block(self, msg): height = msg.get("data", 1) block_chain = BlockChain() block = block_chain.get_block_by_height(height) data = block.serialize() msg = Msg(Msg.GET_BLOCK_MSG, data) return msg
def handle_handshake(self, msg, conn, addr): log.info("------server handle_handshake from " + str(addr) + "------") data = msg.get("data", "") last_height = data.get("last_height", 0) log.info("------with last_height " + str(last_height) + "------") block_chain = BlockChain() block = block_chain.get_last_block() log.info('------s hand_shake ls_blo ' + str(block) + '------') if block: local_last_height = block.block_header.height else: local_last_height = -1 log.info("server local_last_height %d, last_height %d" % (local_last_height, last_height)) if local_last_height >= last_height: try: st = StopMine() log.info('------works------') if st.h < local_last_height: st.h = local_last_height log.info("------" + str(addr) + " is the highest " + str(st.h) + "------") except: log.info('------dont work------') log.info("------server handle_handshake precede------") try: genesis_block = block_chain[0] except: genesis_block = None data = {"last_height": -1, "genesis_block": ""} if genesis_block: data = { "last_height": local_last_height, "genesis_block": genesis_block.serialize() } msg = Msg(Msg.HAND_SHAKE_MSG, data) return msg elif local_last_height < last_height: try: st = StopMine() if st.h < last_height: st.h = last_height st.ip = addr log.info('------works------') log.info("------" + str(addr) + ' is the highest ' + str(st.h) + "------") except: log.info('failed to stop mine') log.info("------server handle_handshake fall behind------") start_height = 0 if local_last_height == -1 else local_last_height synchronize_range = [start_height + 1, last_height + 1] log.info("------server need synchronize range " + str(synchronize_range[0]) + " " + str(synchronize_range[1]) + "------") send_msg = Msg(Msg.SYNCHRONIZE_MSG, synchronize_range) return send_msg
def test_append_first_block(self): block_chain = BlockChain() self.assertTrue(block_chain.tail is None) first_block = Block.create_first_block() block_chain.append(first_block) self.assertTrue(block_chain.tail is not None) self.assertEqual([x for x in block_chain.read_content()], ['First Block'])
def handle_get_block(self, msg): data = msg.get("data", "") block = Block.deserialize(data) bc = BlockChain() try: bc.add_block_from_peers(block) except ValueError as e: log.info(str(e))
def __init__(self, world, id): super(Miner, self).__init__() self._world = world self._id = id self._dig_times = 0 self._log = Logger('miner') # self._chains = [] self._work_chain = BlockChain() self._stop = False
def handle_shake(self, msg): log.info("------client handle_shake from " + str(self.ip) + "------") data = msg.get("data", "") last_height = data.get("last_height", 0) log.info("------with last height " + str(last_height) + "------") block_chain = BlockChain() block = block_chain.get_last_block() log.info('------c handle_sh ls_blo ' + str(block) + '------') if block: local_last_height = block.block_header.height else: local_last_height = -1 log.info("client local_last_height %d, last_height %d" % (local_last_height, last_height)) if local_last_height > last_height: try: st = StopMine() log.info('------works------') if st.h < local_last_height: st.h = local_last_height except: log.info('------dont work------') log.info("------error shake------") log.info("client local_last_height %d, last_height %d" % (local_last_height, last_height)) send_data = [] for i in range(1, local_last_height + 1): block = None while not block: try: block = block_chain.get_block_by_height(i) time.sleep(2) except: time.sleep(2) send_data.append(block.serialize()) msg = Msg(Msg.SYNCHRONIZE_MSG, send_data) self.send(msg) log.info("------client handle_shake send synchronize msg to" + str(self.ip) + "------") elif local_last_height < last_height: try: st = StopMine() log.info('------works------') if st.h < last_height: st.h = last_height st.ip = self.ip log.info("------" + str(self.ip) + ' is the highest ' + str(st.h) + "------") except: log.info('------dont work------') start_height = 0 if local_last_height == -1 else local_last_height get_range = [start_height + 1, last_height + 1] send_msg = Msg(Msg.GET_BLOCK_MSG, get_range) self.send(send_msg) else: t = threading.Thread(target=self.shake_loop(), args=()) t.start()
def create_genesis_block(self): bc = BlockChain() w = Wallet.generate_wallet() ws = Wallets() ws[w.address] = w ws.save() tx = bc.coin_base_tx(w.address) bc.new_genesis_block(tx) return w.address
def test_new_transaction(): sender = "test sender" recipient = "test recipient" amount = 100 block_chain = BlockChain() block_chain.new_transaction(sender, recipient, amount) trans = block_chain.current_transactions assert len(trans) == 1 assert trans[-1]['sender'] == sender assert trans[-1]['recipient'] == recipient assert trans[-1]['amount'] == 100
def handle_transaction(self, msg): tx_pool = TxPool() txs = msg.get("data", {}) for tx_data in txs: tx = Transaction.deserialize(tx_data) tx_pool.add(tx) if tx_pool.is_full(): bc = BlockChain() bc.add_block(tx_pool.txs) log.info("add block") tx_pool.clear() msg = Msg(Msg.NONE_MSG, "") return msg
def handle_transaction(self, msg, conn, addr): # 7.20 log.info("------server handle_transaction------") # 7.8 tx_pool = TxPool() txs = msg.get("data", {}) for tx_data in txs: log.info("------server handle_transaction: for------") # 7.8 tx = Transaction.deserialize(tx_data) is_new = True if tx_pool.is_new(tx): # 7.20 # 7.20 log.info( "------server never get this transaction before------") bc = BlockChain() ls_bl = bc.get_last_block() if ls_bl: ls_height = ls_bl.block_header.height for i in range(0, ls_height + 1): while True: block = None try: block = bc.get_block_by_height(i) except: continue if block: break bc_txs = block._transactions if bc_txs: for transaction in bc_txs: if transaction.txid == tx.txid: log.info("------old transaction------") log.info("------the id is: " + str(tx.txid) + "------") # 7.20 is_new = False # break else: log.info("------brand new------") log.info("------the id is: " + str(tx.txid) + "------") # 7.20 if not is_new: break if is_new: tx_pool.add(tx) log.info("------server add this transaction------") log.info("------the id is: " + str(tx.txid) + "------") server1 = PeerServer() server1.broadcast_tx(tx) log.info("------server handle_transaction broadcast------") msg = Msg(Msg.NONE_MSG, "") return msg
def send(self, from_addr, to_addr, amount): bc = BlockChain() tx = bc.new_transaction(from_addr, to_addr, amount) # bc.add_block([tx]) tx_pool = TxPool() tx_pool.add(tx) try: server = PeerServer() server.broadcast_tx(tx) if tx_pool.is_full(): bc.add_block(tx_pool.txs) tx_pool.clear() except Exception as e: pass print('send %d from %s to %s' % (amount, from_addr, to_addr))
def handle_shake(self, msg): data = msg.get("data", "") last_height = data.get("last_height", 0) block_chain = BlockChain() block = block_chain.get_last_block() if block: local_last_height = block.block_header.height else: local_last_height = -1 log.info("local_last_height %d, last_height %d" %(local_last_height, last_height)) if local_last_height >= last_height: return start_height = 0 if local_last_height == -1 else local_last_height for i in range(start_height, last_height+1): send_msg = Msg(Msg.GET_BLOCK_MSG, i) self.send(send_msg)
def main(self): # initiate block chain with num of zero that we want for proof of work num_of_zero = 5 block_chain = BlockChain(num_of_zero) miner = Miner(block_chain.hash_processor, block_chain.num_of_zero) block_count = 0 while block_count < 5: transaction_list = [] # generate random transaction num_of_transaction = randint(1, 4) for i in range(num_of_transaction): from_id = randint(1, 100) to_id = randint(1, 100) amount = randint(200, 1000) transaction = Transaction(from_id, to_id, amount) transaction_list.append(transaction) # ask miner to get new block to wrap transactions # miner will do brute force in order to get the appropriate hash block = miner.get_new_block(transaction_list, block_chain.get_prev_hash()) # add to block_chain # block chain will verify the block block_chain.add_block(block) # print calculated hash value to user # to make sure right number of zero in the hash hash_val = block_chain.hash_processor.calculate_hash( block.get_hash_num()) print("block number %d" % (block_count + 1, )) print("hash value : " + str(hash_val)) print("generated block : " + str(block)) print() block_count += 1 # check mutation validation # first should be valid print(block_chain.check_is_valid()) # save current value and change the amount to new one prev_amount = block_chain.blocks[1].transaction_list[0].amount block_chain.blocks[1].transaction_list[0].amount = 100800 # check validity again, should be false print(block_chain.check_is_valid()) # change it to original value # should be valid again block_chain.blocks[1].transaction_list[0].amount = prev_amount print(block_chain.check_is_valid())
def handle_miss(self, msg): log.info("------client handle_miss------") tx_pool = TxPool() txs = msg.get("data", {}) for tx_data in txs: log.info("------server handle_miss: for------") tx = Transaction.deserialize(tx_data) is_new = True if tx_pool.is_new(tx): log.info("------client miss this transaction before------") bc = BlockChain() ls_bl = bc.get_last_block() log.info('------c handle_m ls_blo ' + str(ls_bl) + '------') if ls_bl: ls_height = ls_bl.block_header.height for i in range(0, ls_height + 1): while True: block = None try: block = bc.get_block_by_height(i) except: continue if block: break bc_txs = block._transactions if bc_txs: for transaction in bc_txs: if transaction.txid == tx.txid: log.info("------old transaction------") log.info("------the id is: " + str(tx.txid) + "------") is_new = False else: log.info("------brand new miss------") log.info("------the id is: " + str(tx.txid) + "------") if not is_new: break if is_new: tx_pool.add(tx) log.info("------client miss add this transaction------") log.info("------the id is: " + str(tx.txid) + "------") log.info("------client handle_miss broadcast------") t = threading.Thread(target=self.shake_loop(), args=()) t.start()
def handle_handshake(self, msg): block_chain = BlockChain() block = block_chain.get_last_block() try: genesis_block = block_chain[0] except IndexError as e: genesis_block = None data = { "last_height": -1, "genesis_block": "" } if genesis_block: data = { "last_height": block.block_header.height, "genesis_block": genesis_block.serialize() } msg = Msg(Msg.HAND_SHAKE_MSG, data) return msg
def handle_synchronize(self, msg): synchronize_range = msg.get("data", 1) block_chain = BlockChain() data = [] log.info("------client handle_synchronize with range " + str(synchronize_range[0]) + " " + str(synchronize_range[1]) + "------") for height in range(1, synchronize_range[1]): block = None while not block: try: block = block_chain.get_block_by_height(height) time.sleep(2) except: time.sleep(2) data.append(block.serialize()) msg = Msg(Msg.SYNCHRONIZE_MSG, data) self.send(msg)
def handle_get_block(self, msg, conn, addr): log.info("------server handle_get_block from " + str(addr) + "------") get_range = msg.get("data", 1) log.info("------with range " + str(get_range[0]) + " " + str(get_range[1]) + "------") block_chain = BlockChain() data = [] for height in range(1, get_range[1]): block = None while not block: try: block = block_chain.get_block_by_height(height) time.sleep(2) except: time.sleep(2) data.append(block.serialize()) msg = Msg(Msg.GET_BLOCK_MSG, data) log.info("------server send get_block msg" + str(data) + "------") return msg
def test_append_when_chain_is_not_empty(self): block_chain = BlockChain() first_block = Block.create_first_block() block_chain.append(first_block) next_block = Block.create_next_block(block_chain.tail.block) block_chain.append(next_block) # Get the contents of blocks in block chain in reverse order self.assertEqual([x for x in block_chain.read_content()], ['This is block - 1', 'First Block'])
def get_balance(self, addr): bc = BlockChain() balance = 0 utxo = UTXOSet() utxo.reindex(bc) utxos = utxo.find_utxo(addr) print(utxos) for fout in utxos: balance += fout.txoutput.value print('%s balance is %d' % (addr, balance)) return balance
def shake_loop(self): # log.info("------'client shake_loop'------") # 7.8 while True: log.info("------client shake_loop ip:" + self.ip + "\tport:" + str(self.port) + "------") # 7.11 tx_pool1 = TxPool() # 7.2 if self.txs: log.info("------client server has txs------") # 7.10 data = [tx.serialize() for tx in self.txs] log.info("------client serialize transaction-------") msg = Msg(Msg.TRANSACTION_MSG, data) self.send(msg) self.txs = [] # 7.21 'clear' -> '= []' elif tx_pool1.pre_txs: a = random.uniform(0, 1) if a < 0.5: log.info("------has previous transaction------") data = len(tx_pool1.pre_txs) msg = Msg(Msg.MISS_TRANSACTION_MSG, data) self.send(msg) else: log.info("shake") block_chain = BlockChain() block = block_chain.get_last_block() try: genesis_block = block_chain[0] except IndexError as e: genesis_block = None if block: last_height = block.block_header.height else: last_height = -1 data = {"last_height": -1, "genesis_block": ""} if genesis_block: data = { "last_height": last_height, "genesis_block": genesis_block.serialize() } msg = Msg(Msg.HAND_SHAKE_MSG, data) self.send(msg) else: log.info("shake") block_chain = BlockChain() block = block_chain.get_last_block() try: genesis_block = block_chain[0] except IndexError as e: genesis_block = None if block: last_height = block.block_header.height else: last_height = -1 data = {"last_height": -1, "genesis_block": ""} if genesis_block: data = { "last_height": last_height, "genesis_block": genesis_block.serialize() } msg = Msg(Msg.HAND_SHAKE_MSG, data) self.send(msg)
def handle_transaction(self, msg): log.info("------client handle_transaction------") # 7.8 data = msg.get("data", {}) tx = Transaction.deserialize(data) tx_pool = TxPool() is_new = True # 7.20 if tx_pool.is_new(tx): log.info( "------client never get this transaction before------") # 7.20 bc = BlockChain() ls_bl = bc.get_last_block() if ls_bl: ls_height = ls_bl.block_header.height for i in range(0, ls_height + 1): while True: block = None try: block = bc.get_block_by_height(i) except: continue if block: break bc_txs = block._transactions for transaction in bc_txs: if transaction.txid == tx.txid: is_new = False break if not is_new: break if is_new: tx_pool.add(tx) log.info("------client handel_transaction txpool added------" ) # 7.8 server2 = PeerServer() server2.broadcast_tx(tx) log.info("------client handle_transaction broadcast------") msg = Msg(Msg.NONE_MSG, "") # 7.23 self.send(msg) # 7.23
def handle_transaction(self, msg): log.info("------client handle_transaction------") data = msg.get("data", {}) tx = Transaction.deserialize(data) tx_pool = TxPool() is_new = True if tx_pool.is_new(tx): log.info("------client never get this transaction before------") bc = BlockChain() ls_bl = bc.get_last_block() log.info('------c handle_tran ls_blo ' + str(ls_bl) + '------') if ls_bl: ls_height = ls_bl.block_header.height for i in range(0, ls_height + 1): while True: block = None try: block = bc.get_block_by_height(i) except: continue if block: break bc_txs = block._transactions for transaction in bc_txs: if transaction.txid == tx.txid: is_new = False break if not is_new: break if is_new: tx_pool.add(tx) log.info("------client handel_transaction txpool added------") server2 = PeerServer() server2.broadcast_tx(tx) log.info("------client handle_transaction broadcast------") t = threading.Thread(target=self.shake_loop(), args=()) t.start()
def draw_extra3_1(): """写链错误率对好写链比例的影响.""" MESSAGE_POOL_SIZE = 100 NODES = 30 ROUND = 50 P_N = 0.1 STRATEGY = 1 W = 5 P_WRITE_WRONG = np.arange(0.1, 0.5001, 0.05) P_VOTE_WRONG = [0.2, 0.3, 0.4, 0.5] res = {rate: dict() for rate in P_VOTE_WRONG} for pvw in P_VOTE_WRONG: print(f'P_VOTE_WRONG rate {pvw}') for pww in P_WRITE_WRONG: tmp = [] for _ in range(5): bc = BlockChain(message_pool_size=MESSAGE_POOL_SIZE, n=NODES, p_n=P_N, rd=ROUND, strategy=STRATEGY, w=W, p_write_wrong=pww, p_vote_wrong=pvw, verbose=False) write_stat = bc.start() tmp.append(write_stat['bc_good_prob_in_append']) res[pvw][pww] = np.mean(tmp) # 绘制结果曲线 draw_plt(datas=[(res[k].keys(), res[k].values(), f'投票错误的概率={k}') for k in P_VOTE_WRONG], xlabel='领导节点发布错误区块的概率', ylabel='正确区块所占比例', mode='save', save_name='Block Chain pww & writerate')
def test_attempt_to_modify_last_block_content(self): block_chain = BlockChain() first_block = Block.create_first_block() block_chain.append(first_block) next_block = Block.create_next_block(block_chain.tail.block) block_chain.append(next_block) with self.assertRaises(AttributeError) as context: next_block.data = "Illegal modification" self.assertTrue("can't set attribute" in context.exception)
def draw_extra1_1(): """全节点转共识节点概率对上链比例的影响.""" MESSAGE_POOL_SIZE = 1000 NODES = 30 ROUND = [20, 50, 100] P_N = np.arange(0.1, 1.01, 0.1) STRATEGY = 1 W = 5 P_WRITE_WRONG = 0.2 P_VOTE_WRONG = 0.2 res = {rd: dict() for rd in ROUND} for rd in ROUND: print(f'Round {rd}') for pn in P_N: tmp = [] for _ in range(5): bc = BlockChain(message_pool_size=MESSAGE_POOL_SIZE, n=NODES, p_n=pn, rd=rd, strategy=STRATEGY, w=W, p_write_wrong=P_WRITE_WRONG, p_vote_wrong=P_VOTE_WRONG, verbose=False) write_stat = bc.start() tmp.append(write_stat['bc_good_prob']) res[rd][pn] = np.mean(tmp) # 绘制结果曲线 draw_plt(datas=[(res[k].keys(), res[k].values(), f' ={k}') for k in ROUND], xlabel='Probability of Consensus Nodes from Full Nodes', ylabel='Good Write Probability', mode='show', save_name='Block Chain p_n & goodwriterate & round')