def broadcast_block(self, block): Peers.init(self.config, self.mongo, self.config.network) Peer.save_my_peer(self.config, self.mongo, self.config.network) print '\r\nCandidate submitted for index:', block.index print '\r\nTransactions:' for x in block.transactions: print x.transaction_signature self.mongo.db.consensus.insert({'peer': 'me', 'index': block.index, 'id': block.signature, 'block': block.to_dict()}) print '\r\nSent block to:' for peer in Peers.peers: if peer.is_me: continue try: block_dict = block.to_dict() block_dict['peer'] = Peers.my_peer requests.post( 'http://{peer}/newblock'.format( peer=peer.host + ":" + str(peer.port) ), json=block_dict, timeout=3, headers={'Connection':'close'} ) print peer.host + ":" + str(peer.port) except Exception as e: print e peer.report()
def refresh(self): Peers.init(self.config, self.mongo, self.config.network) block = BU.get_latest_block(self.config, self.mongo) if block: block = Block.from_dict(self.config, self.mongo, block) self.height = block.index + 1 else: genesis_block = BlockFactory.get_genesis_block(self.config, self.mongo) genesis_block.save() self.mongo.db.consensus.insert({ 'block': genesis_block.to_dict(), 'peer': 'me', 'id': genesis_block.signature, 'index': 0 }) block = Block.from_dict(self.config, self.mongo, BU.get_latest_block(self.config, self.mongo)) self.height = block.index try: self.block_factory = BlockFactory( config=self.config, mongo=self.mongo, transactions=self.get_pending_transactions(), public_key=self.config.public_key, private_key=self.config.private_key, index=self.height, version=BU.get_version_for_height(self.height)) self.set_target(int(self.block_factory.block.time)) if not self.block_factory.block.special_min: self.set_target_from_last_non_special_min(block) self.block_factory.block.header = BlockFactory.generate_header(self.block_factory.block) except Exception as e: raise e
def run(cls, config, mongo, to, value): Peers.init(config, mongo, config.network) try: transaction = TransactionFactory( config, mongo, fee=0.01, public_key=config.public_key, private_key=config.private_key, outputs=[Output(to=to, value=value)]) except NotEnoughMoneyException as e: print "not enough money yet" return except: raise try: transaction.transaction.verify() except: print 'transaction failed' TU.save(transaction.transaction) print 'Transaction generated successfully. Sending:', value, 'To:', to for peer in Peers.peers: try: socketIO = SocketIO(peer.host, peer.port, wait_for_connection=False) chat_namespace = socketIO.define(ChatNamespace, '/chat') chat_namespace.emit('newtransaction', transaction.transaction.to_dict()) socketIO.disconnect() print 'Sent to:', peer.host, peer.port except Exception as e: print e
def search_network_for_new(self): Peers.init(self.config, self.mongo, self.config.network) for peer in Peers.peers: try: if self.debug: print 'requesting %s from %s' % (self.latest_block.index + 1, peer.to_string()) try: result = requests.get('http://{peer}/get-blocks?start_index={start_index}&end_index={end_index}'.format( peer=str(peer.to_string()), start_index=int(self.latest_block.index) + 1, end_index=int(self.latest_block.index) + 1000 ), timeout=1) except Exception as e: raise e try: blocks = json.loads(result.content) except ValueError: continue for block in blocks: block = Block.from_dict(self.config, self.mongo, block) if block.index == (self.existing_blockchain.blocks[-1].index + 1): self.insert_consensus_block(block, peer) self.import_block({'peer': peer.to_string(), 'block': block.to_dict(), 'extra_blocks': blocks}) except Exception as e: if self.debug: print e
def refresh(self): Peers.init(self.config, self.mongo, self.config.network) if self.config.network == 'mainnet': max_block_time = 600 elif self.config.network == 'testnet': max_block_time = 10 block = BU.get_latest_block(self.config, self.mongo) if block: block = Block.from_dict(self.config, self.mongo, block) self.height = block.index + 1 else: genesis_block = BlockFactory.get_genesis_block( self.config, self.mongo) genesis_block.save() self.mongo.db.consensus.insert({ 'block': genesis_block.to_dict(), 'peer': 'me', 'id': genesis_block.signature, 'index': 0 }) block = Block.from_dict( self.config, self.mongo, BU.get_latest_block(self.config, self.mongo)) self.height = block.index try: if self.height > 0: last_time = block.time special_min = False max_target = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff if self.height > 0: time_elapsed_since_last_block = int( time.time()) - int(last_time) # special min case if time_elapsed_since_last_block > max_block_time: target = max_target special_min = True self.target = BlockFactory.get_target( self.config, self.mongo, self.height, last_time, block, Blockchain(self.config, self.mongo, [x for x in BU.get_blocks(self.config, self.mongo)])) self.block_factory = BlockFactory( config=self.config, mongo=self.mongo, transactions=self.get_pending_transactions(), public_key=self.config.public_key, private_key=self.config.private_key, index=self.height, version=BU.get_version_for_height(self.height)) self.block_factory.block.special_min = special_min self.block_factory.block.target = self.target self.block_factory.header = BlockFactory.generate_header( self.block_factory.block) except Exception as e: raise
def broadcast(self): Peers.init(self.config, self.mongo, self.config.network) for peer in Peers.peers: try: socketIO = SocketIO(peer.host, peer.port, wait_for_connection=False) chat_namespace = socketIO.define(ChatNamespace, '/chat') chat_namespace.emit('new-fastgraph-transaction', self.to_dict()) socketIO.wait(seconds=1) chat_namespace.disconnect() except Exception as e: print e pass
def broadcast_block(self, block): Peers.init(self.config, self.mongo, self.config.network) dup_test = self.mongo.db.consensus.find_one({ 'peer': 'me', 'index': block.index, 'block.version': BU.get_version_for_height(block.index) }) if not dup_test: print '\r\nCandidate submitted for index:', block.index print '\r\nTransactions:' for x in block.transactions: print x.transaction_signature self.mongo.db.consensus.insert({ 'peer': 'me', 'index': block.index, 'id': block.signature, 'block': block.to_dict() }) print '\r\nSent block to:' for peer in Peers.peers: if peer.is_me: continue try: block_dict = block.to_dict() block_dict['peer'] = Peers.my_peer requests.post('http://{peer}/newblock'.format( peer=peer.host + ":" + str(peer.port)), json=block_dict, timeout=3, headers={'Connection': 'close'}) print peer.host + ":" + str(peer.port) except Exception as e: print e try: print 'reporting bad peer' if self.config.network == 'mainnet': url = 'https://yadacoin.io/peers' elif self.config.network == 'testnet': url = 'http://yadacoin.io:8888/peers' requests.post(url, json={ 'host': peer.host, 'port': str(peer.port), 'failed': True }, timeout=3, headers={'Connection': 'close'}) except: print 'failed to report bad peer' pass
def do_payout(self): network = getattr(self.config, 'network', None) if network: Peers.init(self.config, self.mongo, network) else: Peers.init(self.config, self.mongo) # first check which blocks we won. # then determine if we have already paid out # they must be 6 blocks deep latest_block = Block.from_dict(self.config, self.mongo, BU.get_latest_block(self.config, self.mongo)) won_blocks = self.mongo.db.blocks.find({'transactions.outputs.to': self.config.address}).sort([('index', 1)]) for won_block in won_blocks: won_block = Block.from_dict(self.config, self.mongo, won_block) if (won_block.index + 6) <= latest_block.index: self.do_payout_for_block(won_block)
def run(cls, config, mongo, to, value): Peers.init(config, mongo, config.network) try: transaction = TransactionFactory(config, mongo, block_height=BU.get_latest_block( config, mongo)['index'], fee=0.01, public_key=config.public_key, private_key=config.private_key, outputs=[{ 'to': to, 'value': value }]) except NotEnoughMoneyException as e: print "not enough money yet" return except: raise try: transaction.transaction.verify() except: print 'transaction failed' TU.save(config, mongo, transaction.transaction) print 'Transaction generated successfully. Sending:', value, 'To:', to for peer in Peers.peers: try: with SocketIO(peer.host, peer.port, ChatNamespace, wait_for_connection=False) as socketIO: chat_namespace = socketIO.define(ChatNamespace, '/chat') chat_namespace.emit('newtransaction', transaction.transaction.to_dict()) socketIO.disconnect() print 'Sent to:', peer.host, peer.port except Exception as e: print e
def retrace(self, block, peer): if self.debug: self.log("retracing...") blocks = [] blocks.append(block) while 1: if self.debug: self.log(block.hash) self.log(block.index) # get the previous block from either the consensus collection in mongo # or attempt to get the block from the remote peer previous_consensus_block = self.get_previous_consensus_block_from_local(block, peer) if previous_consensus_block: block = previous_consensus_block blocks.append(block) else: if peer.is_me: self.mongo.db.consensus.update({'peer': peer.to_string(), 'index': {'$gte': block.index}}, {'$set': {'ignore': True}}, multi=True) return try: previous_consensus_block = self.get_previous_consensus_block_from_remote(block, peer) except BadPeerException as e: self.mongo.db.consensus.update({'peer': peer.to_string(), 'index': {'$gte': block.index}}, {'$set': {'ignore': True}}, multi=True) except: pass if previous_consensus_block and previous_consensus_block.index + 1 == block.index: block = previous_consensus_block blocks.append(block) try: self.insert_consensus_block(block, peer) except Exception as e: if self.debug: print e # we should do something here to keep it from looping on this failed block else: # identify missing and prune # if the pruned chain is still longer, we'll take it if previous_consensus_block: block = previous_consensus_block blocks = [block] else: return if self.debug: print 'attempting sync at', block.prev_hash # if they do have it, query our consensus collection for prevHash of that block, repeat 1 and 2 until index 1 if self.existing_blockchain.blocks[block.index - 1].hash == block.prev_hash: prev_blocks_check = self.existing_blockchain.blocks[block.index - 1] if self.debug: print prev_blocks_check.hash, prev_blocks_check.index blocks = sorted(blocks, key=lambda x: x.index) block_for_next = blocks[-1] while 1: next_block = self.get_next_consensus_block_from_local(block_for_next) if next_block: blocks.append(next_block) block_for_next = next_block else: break Peers.init(self.config, self.mongo, self.config.network) for peer in Peers.peers: while 1: try: if self.debug: print 'requesting %s from %s' % (block_for_next.index + 1, peer.to_string()) result = requests.get('http://{peer}/get-blocks?start_index={start_index}&end_index={end_index}'.format( peer=peer.to_string(), start_index=block_for_next.index + 1, end_index=block_for_next.index + 100 ), timeout=1) remote_blocks = [Block.from_dict(self.config, self.mongo, x) for x in json.loads(result.content)] break_out = False for remote_block in remote_blocks: if remote_block.prev_hash == block_for_next.hash: blocks.append(remote_block) block_for_next = remote_block else: break_out = True break if break_out: break except Exception as e: if self.debug: print e break # if we have it in our blockchain, then we've hit the fork point # now we have to loop through the current block array and build a blockchain # then we compare the block height and difficulty of the two chains # replace our current chain if necessary by removing them from the database # then looping though our new chain, inserting the new blocks def subchain_gen(existing_blocks, addon_blocks, gen_block): for x in existing_blocks[:addon_blocks[0].index]: if x.index < gen_block.index: yield x for x in addon_blocks: yield x # If the block height is equal, we throw out the inbound chain, it muse be greater # If the block height is lower, we throw it out # if the block height is heigher, we compare the difficulty of the entire chain existing_difficulty = self.get_difficulty(self.existing_blockchain.blocks) inbound_difficulty = self.get_difficulty(subchain_gen(self.existing_blockchain.blocks, blocks, block)) if (blocks[-1].index >= self.existing_blockchain.blocks[-1].index and inbound_difficulty >= existing_difficulty): for block in blocks: try: if block.index == 0: continue self.integrate_block_with_existing_chain(block) if self.debug: print 'inserted ', block.index except ForkException as e: back_one_block = block while 1: back_one_block = self.mongo.db.consensus.find_one({'block.hash': back_one_block.prev_hash}) if back_one_block: back_one_block = Block.from_dict(self.config, self.mongo, back_one_block['block']) try: result = self.integrate_block_with_existing_chain(back_one_block) if result: self.integrate_block_with_existing_chain(block) break except ForkException as e: pass else: return except AboveTargetException as e: return except IndexError as e: return if self.debug: print "Replaced chain with incoming" return else: if not peer.is_me: if self.debug: print ( "Incoming chain lost", inbound_difficulty, existing_difficulty, blocks[-1].index, self.existing_blockchain.blocks[-1].index ) for block in blocks: self.mongo.db.consensus.update({'block.hash': block.hash}, {'$set': {'ignore': True}}, multi=True) return # lets go down the hash path to see where prevHash is in our blockchain, hopefully before the genesis block # we need some way of making sure we have all previous blocks until we hit a block with prevHash in our main blockchain #there is no else, we just loop again # if we get to index 1 and prev hash doesn't match the genesis, throw out the chain and black list the peer # if we get a fork point, prevHash is found in our consensus or genesis, then we compare the current # blockchain against the proposed chain. if block.index == 0: if self.debug: print "zero index reached" return if self.debug: print "doesn't follow any known chain" # throwing out the block for now return