def mine(self): try: all_txs = self.unconfirmed_transaction.copy() last_block = self.last_chain() new_block = Block(index=last_block.index + 1, previous_hash=last_block.block_hash) removing_txs = list() for tx in all_txs: if new_block.add_transaction(tx): removing_txs.append(tx) else: break if new_block.start_find_pow(lambda: self.last_chain()): self.synchronization() if self.add_block(new_block, True): for tx in removing_txs: self.unconfirmed_transaction.remove(tx) else: print('cannot add block in chain') else: print('not find block hash') except: print_exception('Blockchain.mine') Thread(target=self.mine).start()
def load_database(self, callback): try: print( '################ RESTORE BLOCKS IN DATABASE ################') files = [ v for v in os.listdir(DATABASE_DIRS) if v.endswith('.json') ] files.sort() for file in files: with open('{}/{}'.format(DATABASE_DIRS, file), 'r') as file_json: block_json = json.load(file_json) block = Block.parse(block_json) self.add_block(block, False) print('################ RESTORE SUCCESS ################\n\n') print('################ DOWNLOAD BLOCKS IN NODES ################') self.synchronization() print('################ DOWNLOAD SUCCESS ################\n\n') except: print_exception('Blockchain.load_database') callback()
def send_block(self, node, block_json, callback=None): try: resp = http.post('{}/{}'.format(node, 'node&add_new_block'), json=block_json) if callback: callback(resp.ok and 'S' == resp.text) except: print_exception("Blockchain.send_block")
def save_block_database(cls, block): try: file_name = cls.generate_block_file_name(block.index) if not os.path.exists(DATABASE_DIRS): os.makedirs(DATABASE_DIRS) with open('{}/{}'.format(DATABASE_DIRS, file_name), 'w') as file_json: json.dump(block.to_json(with_dumps=False), file_json) except: print_exception('Blockchain.save_block_database')
def verify(self): try: hash_sha256 = SHA256.new() hash_sha256.update(self.tx_hash.encode('utf-8')) signature = base64.standard_b64decode( self.__signature_b64.encode('utf-8')) public_key = RSA.import_key( base64.standard_b64decode( self.__public_key_b64.encode('utf-8')), 'PEM') pkcs1_15.new(public_key).verify(hash_sha256, signature) return True except: print_exception('QueueTransaction.verify') return False
def proof_of_work(self): try: for tx in self.__transaction: if not tx.verify(): return False transaction_list = [tx.tx_hash for tx in self.__transaction] data_block = json.dumps([ self.index, self.previous_hash, self.difficulty, transaction_list, self.timestamp, self.nonce ]) block_hash = sha256(data_block.encode('utf-8')).hexdigest() return block_hash.startswith('0' * self.difficulty) except: print_exception('Block.proof_of_work') return False
def synchronization(self): if len(NODES) == 0: return last_block = self.last_chain() large_node = '' large_block = None for nod in NODES: try: response = http.get('{}/{}'.format(nod, 'node&load_last_block')) if response.ok: node_last_block = Block.parse(json.loads(response.text)) if not large_block or large_block.index < node_last_block.index: large_block = node_last_block large_node = nod except: print_exception('Blockchain.synchronization') try: if large_block and large_block.index > last_block.index: self.load_all_blocks(large_node) except: print_exception("Blockchain.synchronization.load_all_blocks")