def new_block(self, worker, hash, signature, block): print 'receiving new block' print worker print hash print signature print len(block) if not Patterns.validate(Patterns.WORKER, worker) or not Patterns.validate(Patterns.HASH, hash) or not Patterns.validate(Patterns.SIGNATURE, signature): print 'stuff didn"t validate' return False print 'opening temp file' with open(self.CONFIG['blocks_dir']+hash+'.temp', 'wb+') as temp: print 'got temp' temp.write(block) print 'wrote into temp' os.fsync(temp) print 'synched' del block print 'deleted' file_hash = self.CRYPTO.hash_file(temp) print 'hashed' if not self.CRYPTO.verify(Globals.NETWORK_RESOURCE_CODE, Globals.NODE_ID_PREFIX+worker, file_hash, signature, 'base64'): print 'invalid signature' os.remove(self.CONFIG['blocks_dir']+hash+'.temp') return False print 'renaming' os.rename(self.CONFIG['blocks_dir']+hash+'.temp', self.CONFIG['blocks_dir']+hash+Globals.BLOCK_EXTENSION) print 'renamed' side_thread = threading.Thread(self.BLOCK_MANAGER.register_header, hash) side_thread.start() print 'started side thread' return True
def identify(self, worker, timestamp, signature): if not Patterns.validate(Patterns.WORKER, worker) or not Patterns.validate(Patterns.TIMESTAMP, timestamp) or not Patterns.validate(Patterns.SIGNATURE, signature): return {'status': 'refused', 'error': 'bad request'} now = time.time() if timestamp > now or timestamp < now - Globals.MAXIMUM_IDENTIFICATION_DELAY: return {'status': 'refused', 'error': 'invalid timestamp'} if not self.CRYPTO.verify(Globals.NETWORK_RESOURCE_CODE, Globals.NODE_ID_PREFIX+worker, self.CONFIG['id']+str(timestamp), signature, 'base64'): return {'status': 'refused', 'error': 'invalid signature'} (sid, validity) = self.DATABASE.new_session(worker, signature) return {'status': 'accepted', 'sid': sid, 'validity': validity}
def set_worker(self, worker, timestamp, signature): print 'received broadcasting duty from worker', worker if not Patterns.validate(Patterns.WORKER, worker) or not Patterns.validate(Patterns.TIMESTAMP, str(timestamp)) or not Patterns.validate(Patterns.SIGNATURE, signature): print 'invalidated request' return False if self.CRYPTO.verify(Globals.NETWORK_RESOURCE_CODE, Globals.NODE_ID_PREFIX+worker, str(timestamp), signature, 'base64'): print 'signature validated' self.BLOCK_MANAGER.update_worker(worker, timestamp) return True print 'invalid signature' return False
def new_block(self, worker, hash, signature, block): if not Patterns.validate( Patterns.WORKER, worker) or not Patterns.validate( Patterns.HASH, hash) or not Patterns.validate( Patterns.SIGNATURE, signature): return False with open('central/' + hash + '.blk', 'wb+') as temp: temp.write(block) os.fsync(temp) del block print 'New block received from worker', worker print 'Hash:', hash print 'File Signature:', signature return True
def next_block(self, hash): if not Patterns.validate(Patterns.HASH, hash): return False (next_block, response) = self.DATABASE.next_block(hash) if response: if not self.CONFIG['synchronized']: #this other node doesn't have this block, therefore we have a more recent block, meaning we're synchronized with self.LOCK: self.CONFIG['synchronized'] = True self.BLOCK_MANAGER.synchronized(hash) return next_block return False
def new_block(self, worker, hash, signature, block): if not Patterns.validate( Patterns.WORKER, worker) or not Patterns.validate( Patterns.HASH, hash) or not Patterns.validate( Patterns.SIGNATURE, signature): return False with open(CONFIG['blocks_dir'] + hash + '.temp', 'wb+') as temp: temp.write(block) os.fsync(temp) file_hash = Crypto.hash_file(temp) del block if not Crypto.verify(Globals.NETWORK_RESOURCE_CODE, NODE_ID_PREFIX + worker, file_hash, signature, 'base64'): os.remove(CONFIG['blocks_dir'] + hash + '.temp') return False os.rename(CONFIG['blocks_dir'] + hash + '.temp', CONFIG['blocks_dir'] + hash + Globals.BLOCK_EXTENSION) self.DATABASE.new_block(hash) print 'New block received from worker', worker print 'Hash:', hash print 'File Signature:', signature return True
def get_block(self, hash): if not Patterns.validate(Patterns.HASH, hash) or not os.path.isfile(self.CONFIG['blocks_dir']+hash+Globals.BLOCK_EXTENSION): return False with open(self.CONFIG['blocks_dir']+hash+Globals.BLOCK_EXTENSION, 'rb') as block: return xmlrpclib.Binary(block.read()) return False
def register_header(self, node, hash): #fetch file try: size = os.path.getsize(self.CONFIG['blocks_dir']+hash+Globals.SIMPLIFIED_BLOCK_EXTENSION) block = open(self.CONFIG['blocks_dir']+hash+Globals.SIMPLIFIED_BLOCK_EXTENSION, 'rb') if size < psutil.virtual_memory().available / Globals.JSON_MEMORY_MULTIPLIER: #enough memory to load header block_json = json.loads(block.read()) block.close() #verify data fields previous_hash = block_json['previousBlockHash'] signature = block_json['signature'] if not Patterns.validate(Patterns.HASH, previous_hash) or not Patterns.validate(Patterns.TIMESTAMP, block_json['date']) or block_json['workerNode'] not in Globals.NODES or not Patterns.validate(Patterns.SIGNATURE, signature) or type(block_json['header']) is not dict: raise ValueError() header = block_json['header'] del block_json else: #read previous block's hash block.seek(104,0) previous_hash = block.read(64) #read block's date block.seek(9,1) timestamp = block.read(10) #read block's creator block.seek(15,1) node = block.read(1) #read block's signature block.seek(14,1) signature = '' c = '' while 1: c = block.read(1) if c == '"' or c == '': #reached end of file break signature += c #read header block.seek(11,1) header_json = '' while 1: c = block.read(1) if c == '}' or c == '': #reached end of file break header_json += c block.close() #verify data fields if not Patterns.validate(Patterns.HASH, previous_hash) or not Patterns.validate(Patterns.TIMESTAMP, timestamp) or node not in Globals.NODES or not Patterns.validate(Patterns.SIGNATURE, signature) or len(header_json) < 2 or (header_json[:1] != '{' and header_json[-1:] != '}'): raise ValueError() header = json.load(header_json) #verify block's signature message = '{"previousBlockHash":"'+previous_hash+'","date":'+timestamp+',"header":'+json.dumps(header, sort_keys=True)+'}' if not self.CRYPTO.verify(Globals.NETWORK_RESOURCE_CODE, Globals.NODE_ID_PREFIX+node, message, signature, 'base64'): raise ValueError() #save to database self.DATABASE.new_block(hash, header, previous_hash) #remove duplicates from block with self.LOCK: for b in self.blocks: b.remove_duplicates(header) self.previous_worker = node if self.check_next_worker(node, self.CONFIG['id']): self.NETWORK_MANAGER.broadcast_duty() except: print 'Invalid block received: ', hash print 'Deleting and sending a new request' to_send = '0'+'0'+hash self.NETWORK_MANAGER.new_request(NetworkCodes.GET_BLOCK, to_send)
def register_header(self, hash): #fetch file try: size = os.path.getsize(self.CONFIG['blocks_dir']+hash+Globals.BLOCK_EXTENSION) block = open(self.CONFIG['blocks_dir']+hash+Globals.BLOCK_EXTENSION, 'rb') if size < psutil.virtual_memory().available / Globals.JSON_MEMORY_MULTIPLIER: #enough memory to load header block_json = json.loads(block.read()) block.close() #verify data fields previous_hash = block_json['previousBlockHash'] signature = block_json['signature'] if not Patterns.validate(Patterns.HASH, previous_hash) or not Patterns.validate(Patterns.TIMESTAMP, block_json['date']) or block_json['workerNode'] not in Globals.NODES or not Patterns.validate(Patterns.SIGNATURE, signature) or type(block_json['header']) is not dict: raise ValueError() header = block_json['header'] del block_json else: #read this block's hash block.seek(14,0) current_hash = block.read(64) #read previous block's hash block.seek(23,1) previous_hash = block.read(64) #read block's date block.seek(9,1) timestamp = block.read(10) #read block's creator block.seek(14,1) node = block.read(1) #read block's signature block.seek(14,1) signature = '' c = '' while 1: c = block.read(1) if c == '"' or c == '': #reached end of file break signature += c #read header block.seek(11,1) header_json = '' while 1: c = block.read(1) if c == '}' or c == '': #reached end of file break header_json += c block.close() #verify data fields if hash != current_hash or not Patterns.validate(Patterns.HASH, previous_hash) or not Patterns.validate(Patterns.TIMESTAMP, timestamp) or node not in Globals.NODES or not Patterns.validate(Patterns.SIGNATURE, signature) or len(header_json) < 2 or (header_json[:1] != '{' and header_json[-1:] != '}'): raise ValueError() header = json.load(header_json) #verify block's signature message = '{"previousBlockHash":"'+previous_hash+'","date":'+str(timestamp)+',"header":'+json.dumps(header, sort_keys=True)+'}' if not self.CRYPTO.verify(Globals.NETWORK_RESOURCE_CODE, Globals.NODE_ID_PREFIX+node, message, signature, 'base64'): raise ValueError() #save to database self.DATABASE.new_block(hash) #remove duplicates from block with self.LOCK: for b in self.blocks: b.remove_duplicates(header) except: print 'Invalid block received: ', hash print 'Deleting and sending a new request' block = self.RPC_MANAGER.nodes[self.RPC_MANAGER.random_node()].get_block(hash) if block: with open(self.CONFIG['blocks_dir']+hash+'.temp', 'wb') as temp: temp.write(block.data) os.fsync(temp) del block #register header synchronously os.rename(self.CONFIG['blocks_dir']+hash+'.temp', self.CONFIG['blocks_dir']+hash+Globals.BLOCK_EXTENSION) self.BLOCK_MANAGER.register_header(hash)