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}
示例#6
0
 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()
示例#7
0
    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'