def block_added(): import jsonpickle serialized = request.json['block'] thawed = jsonpickle.decode(serialized) active_node.block_added(thawed) _log('debug', 'Başka bir miner block problemini çözdü. Çözülen block, chain\'e eklendi.') return jsonify({'status': 'ok'})
def get_chain(): frozen = None try: import jsonpickle frozen = jsonpickle.encode(active_node.chain.blocks) except Exception as exc: _log('error', '/chain: {0}'.format(str(exc))) return jsonify({'blocks': frozen})
def connect_to_network(port): data = {'port': port} http_response = requests.post( 'http://localhost:5001/connect', json=data) if http_response.status_code == 200: _log('info', 'Blockchain ağına bağlanıldı.') else: _log('error', 'Ağa bağlanırken hata ile karşılaşıldı: {0}'.format(http_response.json()['message']))
def mine(self, pending_block, stop_mining_check, cb_block_found=None): """ Eklenmek istenen block'un merkle root hash'ini alıp, * son block'un hash'i, * eklenecek olan block'un id'si, * ve nonce değerini alarak hash'ler ve problemi çözmeye çalışır. Problemi çözdüğünde chain'e block'u ekler ve diğer node'ları haberdar eder. :param pending_block: Chain'e eklenmek istenen block. :param stop_mining_check: Node'un, mining'i durdurabilmesi içindir. :param cb_block_found: Block bulunduğunda node'u notify etmesi için bir callback. """ mine_continue = True root_hash = self.calculate_merkle(pending_block.pending_txs) last_block = self.blocks[len(self.blocks) - 1] nonce = 0 sha = hasher.sha256() root_hash_enc = str(root_hash).encode('utf-8') prv_hash_enc = str(last_block.previous_hash).encode('utf-8') block_id_enc = str(last_block.id).encode('utf-8') challenge_string = root_hash_enc + prv_hash_enc + block_id_enc sha.update(challenge_string) difficulty_indicator = ''.join( ["0" for x in range(0, self.difficulty)]) # Hardware spec simülasyonu -- BEGIN # import time # import random # performance = float(random.randrange(100, 5000)) / 100 # _log('debug', 'Sleeping: {0}'.format(str(performance))) # time.sleep(performance) # Hardware spec simülasyonu -- END while mine_continue and not stop_mining_check(): # _log('debug', 'Mining iter {0}'.format(str(nonce))) nonce_enc = str(nonce).encode('utf-8') sha.update(nonce_enc) blockhash = sha.hexdigest() if blockhash[0:self.difficulty] == difficulty_indicator: # aranan nonce bulundu! _log( 'info', 'Nonce bulundu! Nonce: {0} Block_hash: {1}'.format( str(nonce), blockhash)) mine_continue = False new_id = len(self.blocks) block_to_add = Block(id=new_id, blockhash=blockhash, previous_hash=last_block.blockhash, nonce=nonce, merkleroot=root_hash, data=pending_block.pending_txs) self.blocks.append(block_to_add) if cb_block_found: cb_block_found() nonce += 1
def connect_to_network(port, ip='localhost:', por='5001'): a='http://' b='/list' c=a+ip+por+b data = {'port': port} http_response = requests.post(c, json=data) if http_response.status_code == 200: _log('info', 'Blockchain ağına bağlanıldı.') else: _log('error', 'Ağa bağlanırken hata ile karşılaşıldı: {0}'.format(http_response.json()['message']))
def notify_nodes(last_block): nodes = get_other_nodes() for node in nodes: try: import jsonpickle if node != curr_port: frozen = jsonpickle.encode(last_block) data = {'block': frozen} requests.post( 'http://localhost:{0}/found'.format(node), json=data) except ConnectionError as conerr: _log('info', '{0} porta sahip node offline olabilir.'.format(node))
def block_found(self): """ Çalışan node block'u bulmuşsa, blockchain objesi tarafından bu metod çağırılır. """ _log('dev', 'NodeComponent.mine.block_found') if len(self.pending_blocks) > 0: self.pending_blocks.remove(self.pending_blocks[0]) elif len(self.pending_txs) > 0: self.pending_txs = [] self.mine() if self.cb_notify_nodes: self.cb_notify_nodes(self.chain.blocks[len(self.chain.blocks) - 1])
def pick_honest_chain(self, node_chains): """ Genesis block'un yaratıldığı bir ağa bağlanan node için çalıştırılır. Node, consensus sonucu, değiştirilmemiş block'u bulmaya çalışır. v0.0.1 itibari ile, sadece ilk node'dan gelen block'u doğru kabul edip almaktadır. İlerki versiyonlarda değiştirilecektir. Roadmap'e eklenmiş durumda. :param node_chains: Ağdaki tüm ağlardan alınan block'lar. """ _log('info', 'Ağdaki block\'lar toplanılarak, consensus sonrası en uygun block seçildi.') self.chain = Blockchain(difficulty=self.difficulty) self.chain.blocks = node_chains[0][1]
def load_chain(current_port, nodes=None): all_blocks = [] from requests.exceptions import ConnectionError import jsonpickle for node in nodes: try: # kendi kendisine chain sormaması için. if node != current_port: http_response = requests.get( 'http://localhost:{0}/chain'.format(node)) serialized = http_response.json()['blocks'] thawed = jsonpickle.decode(serialized) all_blocks.append((node, thawed)) except ConnectionError as conerr: _log('info', '{0} porta sahip node offline olabilir'.format(node)) active_node.load_chain(all_blocks)
def block_added(self, new_block): """ Diğer node'lardan biri, mining sonucu block eklediğinde, aktif node'un sync kalması için çağırılır. Devam etmekte olan bir mine işlemi varsa, sonlandırılır. :param new_block: Yeni eklenen block. """ _log('debug', 'node.NodeComponent.block_added') self.chain.blocks.append(new_block) if self.miner: self.stop_mining = True # Normal şartlar altında bu if bloguna ihtiyaç olmaması gerekiyor. # HTTP çalıştığımız için ve queue olmadığı için, diğer miner'lardan birisi # iki kez üst üste problemi çözerse, IndexError: list index out of range # oluşuyor. if len(self.pending_blocks) > 0: self.pending_blocks.remove(self.pending_blocks[0]) self.mine()
def exc_occurs(exc, node): if exc is ConnectionError: _log('info', '{0} porta sahip node offline olabilir.'.format(node))
def create_genesis_chain(self): """Genesis block yaratır.""" _log('info', 'Genesis! Blockchain ilk kez oluşturuldu.') self.chain = Blockchain(difficulty=self.difficulty) self.chain._generate_genesis()