def masternode_validate_registration_ticket(data, *args, **kwargs): # parse inputs artist_pk = kwargs.get('sender_id') mn_ticket_logger.info( 'Masternode validate regticket, data: {}'.format(data)) regticket_serialized, regticket_signature_serialized = data regticket = RegistrationTicket(serialized=regticket_serialized) signed_regticket = Signature(serialized=regticket_signature_serialized) require_true(signed_regticket.pastelid == regticket.author) signed_regticket.validate(regticket) # validate registration ticket regticket.validate() upload_code = uuid.uuid4().bytes # TODO: clean upload code and regticket from local db when ticket was placed on the blockchain # TODO: clean upload code and regticket from local db if they're old enough MASTERNODE_DB.connect(reuse_if_open=True) Regticket.create(regticket=regticket_serialized, upload_code=upload_code, created=datetime.now(), artists_signature_ticket=regticket_signature_serialized, artist_pk=artist_pk, image_hash=regticket.imagedata_hash) return upload_code
def masternode_mn1_confirm(data, *args, **kwargs): # parse inputs artist_pk, image_hash, serialized_signature = data sender_id = kwargs.get('sender_id') MASTERNODE_DB.connect(reuse_if_open=True) mn_ticket_logger.info( 'masternode_mn1_confirm: received confirmation from {}'.format( sender_id)) regticket_db_set = Regticket.select().where( Regticket.artist_pk == artist_pk, Regticket.image_hash == image_hash) if len(regticket_db_set) == 0: raise Exception( 'Regticket not found for given artist ID and image hash') if len(regticket_db_set) > 2: regticket_db = regticket_db_set[-1] Regticket.delete().where(Regticket.id < regticket_db.id) else: regticket_db = regticket_db_set[0] if regticket_db.is_valid_mn1 is None: # first confirmation has came regticket_db.is_valid_mn1 = True regticket_db.mn1_pk = sender_id regticket_db.mn1_serialized_signature = serialized_signature regticket_db.save() else: if regticket_db.is_valid_mn2 is None: if regticket_db.mn1_pk == sender_id: raise Exception( 'I already have confirmation from this masternode') # second confirmation has came regticket_db.is_valid_mn2 = True regticket_db.mn2_pk = sender_id regticket_db.mn2_serialized_signature = serialized_signature regticket_db.save() regticket = RegistrationTicket(serialized=regticket_db.regticket) # store image and thumbnail in chunkstorage masternode_place_image_data_in_chunkstorage( regticket, regticket_db.image_data) txid = regticket_db.write_to_blockchain() return txid else: raise Exception('All 2 confirmations received for a given ticket') mn_ticket_logger.info('Confirmation from MN received') return 'Validation passed'
async def masternode_validate_txid_upload_code_image(data, *args, **kwargs): burn_10_txid, upload_code = data try: regticket_db = Regticket.get(upload_code=upload_code) except DoesNotExist: mn_ticket_logger.exception( 'Upload code {} not found in DB'.format(upload_code)) raise ValueError('Given upload code was issued by someone else...') is_valid, errors = await is_burn_tx_valid(regticket_db, burn_10_txid) if not is_valid: raise ValueError(errors) regticket = RegistrationTicket(serialized=regticket_db.regticket) # TODO: perform duplication check if get_nsfw_detector().is_nsfw(regticket_db.image_data): raise ValueError( "Image is NSFW, score: %s" % get_nsfw_detector().get_score(regticket_db.image_data)) # if we're on mn1 or mn2: if regticket_db.localfee is None: mn0 = get_masternode_ordering(regticket.blocknum)[0] # Send confirmation to MN0 mn_signed_regticket = generate_signed_ticket(regticket) # TODO: run task and return without waiting for result (as if it was in Celery) # TODO: handle errors/exceptions response = await mn0.call_masternode( "REGTICKET_MN1_CONFIRM_REQ", "REGTICKET_MN1_CONFIRM_RESP", [ regticket.author, regticket.imagedata_hash, mn_signed_regticket.serialize() ]) # We return success status cause validation on this node has passed. However exception may happen when # calling mn0 - need to handle it somehow (or better - schedule async task). return response else: return 'Validation passed'
def masternode_image_upload_request_mn0(data, *args, **kwargs): # parse inputs upload_code = data['upload_code'] image_data = data['image_data'] mn_ticket_logger.info( 'Masternode image upload received, upload_code: {}'.format( upload_code)) sender_id = kwargs.get('sender_id') MASTERNODE_DB.connect(reuse_if_open=True) try: regticket_db = Regticket.get(upload_code=upload_code) regticket = RegistrationTicket(serialized=regticket_db.regticket) if regticket.author != sender_id: raise Exception( 'Given upload code was created by other public key') mn_ticket_logger.info( 'Given upload code exists with required public key') except DoesNotExist: mn_ticket_logger.exception( 'Given upload code DOES NOT exists with required public key') raise result = get_blockchain_connection().getlocalfee() fee = result['localfee'] regticket_db.image_data = image_data regticket_db.localfee = fee regticket_db.save() return fee
def regticket_status(data, *args, **kwargs): # verify identity - return status only to regticket creator sender_id = kwargs.get('sender_id') upload_code = data.get('upload_code') MASTERNODE_DB.connect(reuse_if_open=True) try: regticket_db = Regticket.get(artist_pk=sender_id, upload_code=upload_code) except DoesNotExist: raise Exception( 'Given upload code DOES NOT exists with required public key') return {'status': regticket_db.status, 'error': regticket_db.error}
def masternode_image_upload_request(self, data, *args, **kwargs): # parse inputs upload_code = data['upload_code'] image_data = data['image_data'] mn_ticket_logger.info( 'Masternode image upload received, upload_code: {}'.format( upload_code)) sender_id = kwargs.get('sender_id') db.connect(reuse_if_open=True) try: regticket_db = Regticket.get(upload_code=upload_code) regticket = RegistrationTicket(serialized=regticket_db.regticket) if regticket.author != sender_id: raise Exception( 'Given upload code was created by other public key') mn_ticket_logger.info( 'Given upload code exists with required public key') except DoesNotExist: mn_ticket_logger.warn( 'Given upload code DOES NOT exists with required public key') raise regticket_db.image_data = image_data regticket_db.save()
def masternode_mn0_confirm(self, data, *args, **kwargs): # parse inputs artist_pk, image_hash, serialized_signature = data sender_id = kwargs.get('sender_id') db.connect(reuse_if_open=True) mn_ticket_logger.info( 'masternode_mn0_confirm: received confirmation from {}'.format( sender_id)) try: # Verify that given upload_code exists # !!!! - regticket with same artists_pk and image_hash may already exists regticket_db_set = Regticket.select().where( Regticket.artist_pk == artist_pk, Regticket.image_hash == image_hash) if len(regticket_db_set) == 0: raise Exception( 'Regticket not found for given artist ID and image hash') if len(regticket_db_set) > 2: regticket_db = regticket_db_set[-1] Regticket.delete().where(Regticket.id < regticket_db.id) else: regticket_db = regticket_db_set[0] if regticket_db.is_valid_mn1 is None: # first confirmation has came regticket_db.is_valid_mn1 = True regticket_db.mn1_pk = sender_id regticket_db.mn1_serialized_signature = serialized_signature regticket_db.save() else: if regticket_db.is_valid_mn2 is None: if regticket_db.mn1_pk == sender_id: raise Exception( 'I already have confirmation from this masternode') # second confirmation has came regticket_db.is_valid_mn2 = True regticket_db.mn2_pk = sender_id regticket_db.mn2_serialized_signature = serialized_signature regticket_db.save() regticket = RegistrationTicket( serialized=regticket_db.regticket) current_block = self.__chainwrapper.get_last_block_number() # verify if confirmation receive for 5 blocks or less from regticket creation. if current_block - regticket.blocknum > 5: regticket_db.status = REGTICKET_STATUS_ERROR error_msg = 'Second confirmation received too late - current block {}, regticket block: {}'. \ format(current_block, regticket.blocknum) regticket_db.error = error_msg raise Exception(error_msg) # Tcreate final ticket final_ticket = generate_final_regticket( regticket, Signature( serialized=regticket_db.artists_signature_ticket), (Signature( dictionary={ "signature": pastel_id_write_signature_on_data_func( regticket_db.regticket, self.__priv, self.__pub), "pubkey": self.__pub }), Signature( serialized=regticket_db.mn1_serialized_signature), Signature( serialized=regticket_db.mn2_serialized_signature) )) # write final ticket into blockchain # TODO: process errors txid = self.__chainwrapper.store_ticket(final_ticket) mn_ticket_logger.warn( 'Final ticket is stored, txid: {}'.format(txid)) return txid # TODO: store image into chunkstorage - later, when activation happens # TODO: extract all this into separate function else: raise Exception( 'All 2 confirmations received for a given ticket') except DoesNotExist: mn_ticket_logger.warn( 'Given upload code DOES NOT exists with required public key') raise Exception( 'Given upload code DOES NOT exists with required public key') mn_ticket_logger.info('Confirmation from MN received') return 'Ok'