def __init__(self): Mongo.init() latest_block = BU.get_latest_block() if latest_block: self.latest_block = Block.from_dict(latest_block) else: self.insert_genesis() self.verify_existing_blockchain()
def post_block(): block = Block.from_dict(request.json) block.verify() my_latest_block = BU.get_latest_block() if my_latest_block[0].get('index') - block.index == 1: block.save() return '{"status": "ok"}' else: return '{"status": "error"}', 400
def sync(self): #top down syncing self.latest_block = Block.from_dict(BU.get_latest_block()) self.remove_pending_transactions_now_in_chain() latest_consensus = self.get_latest_consensus_block() if latest_consensus: print latest_consensus.index, "latest consensus_block" # check for difference between blockchain and consensus table heights if self.latest_block.index == latest_consensus.index: self.log('up to date, height: ' + str(latest_consensus.index)) return records = Mongo.db.consensus.find({ 'index': latest_consensus.index, 'block.version': BU.get_version_for_height(latest_consensus.index) }) for record in sorted(records, key=lambda x: int(x['block']['target'], 16)): block = Block.from_dict(record['block']) peer = Peer.from_string(record['peer']) print self.latest_block.hash, block.prev_hash, self.latest_block.index, ( block.index - 1) try: self.integrate_block_with_existing_chain( block, peer, self.existing_blockchain) except AboveTargetException as e: pass except ForkException as e: self.retrace(block, peer) except IndexError as e: self.retrace(block, peer) else: self.log('no consensus data... none.') return
def rank_consenesus_blocks(self): # rank is based on target, total chain difficulty, and chain validity records = self.get_consensus_blocks_by_index(self.latest_block.index + 1) lowest = self.lowest ranks = [] for record in records: peer = Peer.from_string(record['peer']) block = Block.from_dict(record['block']) target = int(record['block']['hash'], 16) if target < lowest: ranks.append({'target': target, 'block': block, 'peer': peer}) return sorted(ranks, key=lambda x: x['target'])
def get_previous_consensus_block_from_remote(self, block, peer): try: url = 'http://' + peer.to_string( ) + '/get-block?hash=' + block.prev_hash print 'getting block', url res = requests.get(url, timeout=3) print 'response code: ', res.status_code new_block = Block.from_dict(json.loads(res.content)) if int(new_block.version) == BU.get_version_for_height( new_block.index): return new_block else: return None except: return None
def get_previous_consensus_block_from_local(self, block, peer): #table cleanup new_block = Mongo.db.consensus.find_one({ 'block.hash': block.prev_hash, 'block.index': (block.index - 1), 'block.version': BU.get_version_for_height((block.index - 1)) }) if new_block: new_block = Block.from_dict(new_block['block']) if int(new_block.version) == BU.get_version_for_height( new_block.index): return new_block else: return None return None
def on_newblock(self, data): #print("new block ", data) config = app.config['yada_config'] mongo = app.config['yada_mongo'] try: peer = Peer.from_string(request.json.get('peer')) block = Block.from_dict(data) if block.index == 0: return if int(block.version) != BU().get_version_for_height(block.index): print('rejected old version %s from %s' % (block.version, peer)) return mongo.db.consensus.update({ 'index': block.to_dict().get('index'), 'id': block.to_dict().get('id'), 'peer': peer.to_string() }, { 'block': block.to_dict(), 'index': block.to_dict().get('index'), 'id': block.to_dict().get('id'), 'peer': peer.to_string() }, upsert=True) except Exception as e: print("block is bad") raise e except Exception as e: print("block is bad") raise e try: if 'regnet' not in config.network: requests.post( 'https://yadacoin.io/peers', json.dumps({ 'host': config.peer_host, 'port': config.peer_port }), headers={ "Content-Type": "application/json" } ) except: print('ERROR: failed to get peers, exiting...')
import sys import json import time from base64 import b64encode from yadacoin import Config, BU, Block, Mongo with open('config/config.json') as f: config = Config.from_dict(json.loads(f.read())) iteration = 0 config.max_duration = 100000000 config.grace = 10 config.block_version = '1' mongo = Mongo(config) start = time.time() genesis_block = Block.mine([], config.public_key, config.private_key, config.max_duration) end = time.time() print genesis_block.to_json()
def newblock(data): #print("new block ", data) try: peer = request.json.get('peer') incoming_block = Block.from_dict(data) if incoming_block.index == 0: return if int(incoming_block.version) != BU.get_version_for_height( incoming_block.index): print 'rejected old version %s from %s' % ( incoming_block.version, peer) return except Exception as e: print "block is bad" print e except BaseException as e: print "block is bad" print e try: dup_check = Mongo.db.consensus.find({ 'id': incoming_block.signature, 'peer': peer, 'block.version': BU.get_version_for_height(incoming_block.index) }) if dup_check.count(): return "dup" Mongo.db.consensus.update( { 'block': incoming_block.to_dict(), 'index': incoming_block.to_dict().get('index'), 'id': incoming_block.to_dict().get('id'), 'peer': peer }, { 'block': incoming_block.to_dict(), 'index': incoming_block.to_dict().get('index'), 'id': incoming_block.to_dict().get('id'), 'peer': peer }, upsert=True) # before inserting, we need to check it's chain # search consensus for prevHash of incoming block. #prev_blocks_check = Mongo.db.blocks.find({'hash': incoming_block.prev_hash}) #if prev_blocks_check.count(): # 1. if we have it, then insert it. # Mongo.db.consensus.insert({ # 'block': incoming_block.to_dict(), # 'index': incoming_block.to_dict().get('index'), # 'id': incoming_block.to_dict().get('id'), # 'peer': peer}) #else: # 2 scenarios # 1. the 3 is late to the game # 2. 1 and 2 do not find prev_hash from 3 and # we have a fork # the consensus has the previous block to the incoming block but it's not in the block chain # we need to do the chain compare routine here and decide if we're going with the blockchain # belongs to the incoming block, or stay with our existing one #retrace(incoming_block, db, peer) # return except Exception as e: print e except BaseException as e: print e
def retrace(self, block, peer): self.log("retracing...") blocks = [] blocks.append(block) while 1: 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: previous_consensus_block = self.get_previous_consensus_block_from_remote( block, peer) if previous_consensus_block and previous_consensus_block.index + 1 == block.index: block = previous_consensus_block blocks.append(block) self.insert_consensus_block(block, peer) 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 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 prev_blocks_check = Mongo.db.blocks.find_one({ 'hash': block.prev_hash, 'index': block.index - 1 }) if prev_blocks_check: prev_blocks_check = Block.from_dict(prev_blocks_check) print prev_blocks_check.hash, prev_blocks_check.index missing_blocks = Mongo.db.blocks.find( {'index': { '$lte': prev_blocks_check.index }}) for missing_block in missing_blocks: blocks.append(Block.from_dict(missing_block)) # 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 self.existing_blockchain = Blockchain( [x for x in Mongo.db.blocks.find({})]) blockchain = Blockchain([x for x in blocks]) # 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 inbound_difficulty_average = ( blockchain.get_difficulty() / blockchain.get_highest_block_height()) if self.existing_blockchain.get_highest_block_height() == 0: existing_difficulty_average = inbound_difficulty_average + 1 else: existing_difficulty_average = ( self.existing_blockchain.get_difficulty() / self.existing_blockchain.get_highest_block_height()) if blockchain.get_highest_block_height() > self.existing_blockchain.get_highest_block_height() \ and inbound_difficulty_average < existing_difficulty_average: for block in sorted(blockchain.blocks, key=lambda x: x.index): try: if block.index == 0: continue self.integrate_block_with_existing_chain( block, peer, blockchain) except ForkException as e: return except AboveTargetException as e: return print "Replaced chain with incoming" return else: print "Incoming chain lost", blockchain.get_difficulty( ), self.existing_blockchain.get_difficulty( ), blockchain.get_highest_block_height( ), self.existing_blockchain.get_highest_block_height() 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: print "zero index reached" return print "doesn't follow any known chain" # throwing out the block for now return
def get_latest_consensus_block(self): latests = self.get_latest_consensus_blocks() for latest in latests: if int(latest['block']['version']) == BU.get_version_for_height( latest['block']['index']): return Block.from_dict(latest['block'])