Example #1
0
def on_ownership_editions_create(sender, instance, created, *args, **kwargs):
    if created:
        # Create bitcoin transaction
        transaction = BitcoinTransaction.editions(instance)

        # register number of editions
        tasks.editions.delay(transaction.id, util.mainAdminPassword())
Example #2
0
def on_ownership_registration_create(sender, instance, created, *args, **kwargs):
    if created:
        # Create bitcoin transaction
        transaction = BitcoinTransaction.register(instance)

        # register the edition
        tasks.register.delay(transaction.id, util.mainAdminPassword())
Example #3
0
def on_consigned_registration_create(sender, instance, created, *args, **kwargs):
    if created:
        # Create bitcoin transaction
        transaction = BitcoinTransaction.consigned_registration(instance)

        # consigned registeration of a piece
        tasks.consigned_registration.delay(transaction.id, util.mainAdminPassword())
Example #4
0
def on_ownership_piece_create(sender, instance, created, *args, **kwargs):
    if created:
        # Create bitcoin transaction
        transaction = BitcoinTransaction.register_piece(instance)

        # register piece
        tasks.register_piece.delay(transaction.id, util.mainAdminPassword())
Example #5
0
def on_unconsignment_create(sender, instance, password, *args, **kwargs):
    # Create bitcoin unconsign transaction
    unconsign = BitcoinTransaction.unconsign(instance)

    # before pushing the transaction we need to check:
    # 1. check if the edition needs migration
    # 2. the edition address is refilled

    # check if edition needs migration
    migration = check_migration(instance)
    if migration:
        instance.prev_btc_address = migration.new_btc_address
        instance.btc_tx = None
        instance.ciphertext_wif = BitcoinWallet.encoded_wif_for_path(instance, password)
        instance.save()

        # delete old btc_tx which has the wrong addresses and create a new one
        unconsign.delete()
        unconsign = BitcoinTransaction.unconsign(instance)

    # refill the edition address
    # create the transaction
    refill = BitcoinTransaction.refill(instance)
    # set the unconsign as the dependent transaction so that it is sent after the refill by the
    # transaction_monitor
    refill.dependent_tx = unconsign
    refill.save()
    tasks.refill.delay(refill.id, util.mainAdminPassword())
Example #6
0
def on_migration_created(sender, instance, created, *args, **kwargs):
    if created:
        # Create bitcoin transaction
        # we need to check if its for an edition or piece
        if instance.edition:
            transaction = BitcoinTransaction.migrate(instance)
        else:
            transaction = BitcoinTransaction.migrate_piece(instance)

        # migration of a piece or edition
        tasks.migrate.delay(transaction.id, util.mainAdminPassword())
Example #7
0
def on_loan_piece_confirmed(sender, instance, *args, **kwargs):
    # Create bitcoin consign transaction
    loan_piece = BitcoinTransaction.loan_piece(instance)

    # before pushing the transaction we need to check:
    # 1. the piece is already registered
    # 2. the piece address is refilled

    # check if edition is registered
    # unlike editions a piece is registered at the time of creation

    # refill the piece address
    # create the transaction
    refill = BitcoinTransaction.refill(instance)
    # set the loan as the dependent transaction so that it is sent after the refill by the
    # transaction_monitor
    refill.dependent_tx = loan_piece
    refill.save()
    tasks.refill.delay(refill.id, util.mainAdminPassword())
Example #8
0
def on_ownership_transfer_create(sender, instance, password, *args, **kwargs):
    # Create bitcoin transfer transaction
    transfer = BitcoinTransaction.transfer(instance)

    # if a user needs to register and there is no wallet yet no transaction will be created
    if transfer:

        # before pushing the transaction we need to check:
        # 1. the edition is already registered (because of lazy editions)
        # 2. check if an edition needs migration (due to a password change)
        # 3. the edition address is refilled

        # check if edition is registered
        registration = ownership_models.OwnershipRegistration.objects.filter(edition=instance.edition)
        if not registration:
            registration = ownership_models.OwnershipRegistration.create(edition=instance.edition,
                                                                         new_owner=instance.edition.owner)
            registration.save()

        # check if edition needs migration
        migration = check_migration(instance)
        if migration:
            instance.prev_btc_address = migration.new_btc_address
            instance.btc_tx = None
            instance.ciphertext_wif = BitcoinWallet.encoded_wif_for_path(instance, password)
            instance.save()

            # delete old btc_tx which has the wrong addresses and create a new one
            transfer.delete()
            transfer = BitcoinTransaction.transfer(instance)

        # refill the edition address
        # create the transaction
        refill = BitcoinTransaction.refill(instance)
        # set the transfer as the dependent transaction so that it is sent after the refill by the
        # transaction_monitor
        refill.dependent_tx = transfer
        refill.save()
        tasks.refill.delay(refill.id, util.mainAdminPassword())
Example #9
0
def execute_pending_actions(sender, user, *args, **kwargs):
    # check for pending actions when a user logins for the first time
    ownership_transfers = ownership_models.OwnershipTransfer.objects.filter(new_owner=user)

    for ownership_transfer in ownership_transfers:
        ownership_transfer.edition.pending_new_owner = None
        ownership_transfer.edition.owner = ownership_transfer.new_owner
        ownership_transfer.edition.save()
        ownership_transfer.save()
        acl = ActionControl.objects.get(user=ownership_transfer.prev_owner,
                                        piece=ownership_transfer.edition.parent,
                                        edition=ownership_transfer.edition)
        acl.acl_withdraw_transfer = False
        acl.acl_unshare = True
        acl.save()

        # create the transaction
        transfer = BitcoinTransaction.transfer(ownership_transfer)

        # before pushing the transaction we need to check:
        # 1. the edition is already registered (because of lazy editions)
        # 2. the edition address is refilled

        # check if edition is registered
        registration = ownership_models.OwnershipRegistration.objects.filter(edition=ownership_transfer.edition)
        if not registration:
            registration = ownership_models.OwnershipRegistration.create(edition=ownership_transfer.edition,
                                                                         new_owner=ownership_transfer.edition.owner)
            registration.save()

        # refill the edition address
        # create the transaction
        refill = BitcoinTransaction.refill(ownership_transfer)
        # set the transfer as the dependent transaction so that it is sent after the refill by the
        # transaction_monitor
        refill.dependent_tx = transfer
        refill.save()
        tasks.refill.delay(refill.id, util.mainAdminPassword())
Example #10
0
def on_loan_edition_confirmed(sender, instance, *args, **kwargs):
    # Create bitcoin consign transaction
    loan = BitcoinTransaction.loan(instance)

    # before pushing the transaction we need to check:
    # 1. the edition is already registered (because of lazy editions)
    # 2. the edition address is refilled

    # check if edition is registered
    registration = ownership_models.OwnershipRegistration.objects.filter(edition=instance.edition)
    if not registration:
        registration = ownership_models.OwnershipRegistration.create(edition=instance.edition,
                                                                     new_owner=instance.edition.owner)
        registration.save()

    # refill the edition address
    # create the transaction
    refill = BitcoinTransaction.refill(instance)
    # set the loan as the dependent transaction so that it is sent after the refill by the
    # transaction_monitor
    refill.dependent_tx = loan
    refill.save()
    tasks.refill.delay(refill.id, util.mainAdminPassword())
Example #11
0
def initialize():
    """
    Task to be performed when the app is restarted:

    1. Check unconfirmed transactions
        - We may have missed some events from blocktrail
    2. Push passed transactions
        - Maybe BTC was disabled and now we want to push past transactions
    3. Import all addresses
    """
    logger.info('Performing initialization of the bitcoin layer...')

    # import all addresses
    from bitcoin.management.commands.import_addresses import import_addresses
    import_addresses.delay()

    # this should only be done for transactions created after this code went live
    # we will remove this once we are sure that everything is ok in the database
    from_datetime = timezone.datetime.strptime('2015-11-04 10:00:00',
                                               '%Y-%m-%d %H:%M:%S')
    from_datetime = timezone.make_aware(from_datetime, timezone=timezone.utc)

    # check if we are using the mainnet or testnet
    # testnet addresses start with 'm' or 'n'
    # mainnet addrresses start with '1'
    if settings.BTC_TESTNET:
        regex = r'^([mn]|\S+?:[mn])\S+?'
    else:
        regex = r'^(1|\S+?:1)\S+?'

    # Check unconfirmed transactions
    logger.info('Checking unconfirmed transactions...')
    for tx in BitcoinTransaction.objects.filter(status=TX_UNCONFIRMED, datetime__gt=from_datetime)\
            .filter(from_address__regex=regex).order_by('datetime'):
        try:
            logger.info('Checking transaction {}'.format(tx.id))
            response = initialize.blocktrail_client.transaction(tx.tx)
            confirmations = response.get('confirmations', 0)
            if confirmations > 0:
                transaction_monitor.delay(tx.tx, confirmations)
        except blocktrail.exceptions.ObjectNotFound:
            tx.error_msg = 'Transaction not found'
            tx.status = TX_REJECTED
            tx.save()
            logger.info('Transaction {} not found.'.format(tx.tx))

    # Push passed transactions
    logger.info('Checking unpushed transactions...')
    # First we need get pending transactions in the queue and exclude them or else we are
    # going to send duplicate transactions
    tx_id_regex = r'^\((\d+),\s\S+?\)'
    tx_ids_exclude = []

    scheduled_tasks = app.control.inspect().scheduled()
    scheduled_tasks = scheduled_tasks if scheduled_tasks else {}
    active_tasks = app.control.inspect().active()
    active_tasks = active_tasks if active_tasks else {}
    reserved_tasks = app.control.inspect().reserved()
    reserved_tasks = reserved_tasks if reserved_tasks else {}
    for queue, tasks in scheduled_tasks.iteritems():
        for task in tasks:
            request = task.get('request', None)
            if request:
                match = re.match(tx_id_regex, request.get('args', ''))
                if match:
                    logger.info('Found transaction {} in the queue'.format(
                        match.groups()[0]))
                    tx_ids_exclude.append(int(match.groups()[0]))

    for queue, tasks in active_tasks.iteritems():
        for task in tasks:
            request = task.get('request', None)
            if request:
                match = re.match(tx_id_regex, request.get('args', ''))
                if match:
                    logger.info('Found transaction {} in the queue'.format(
                        match.groups()[0]))
                    tx_ids_exclude.append(int(match.groups()[0]))

    for queue, tasks in reserved_tasks.iteritems():
        for task in tasks:
            request = task.get('request', None)
            if request:
                match = re.match(tx_id_regex, request.get('args', ''))
                if match:
                    logger.info('Found transaction {} in the queue'.format(
                        match.groups()[0]))
                    tx_ids_exclude.append(int(match.groups()[0]))

    for tx in BitcoinTransaction.objects.filter(status=TX_PENDING, datetime__gt=from_datetime)\
            .filter(from_address__regex=regex).exclude(id__in=tx_ids_exclude).order_by('datetime'):

        logger.info('Pushing unpushed transaction {}'.format(tx.id))
        # Get the ownership action
        try:
            if tx.spoolverb == 'ASCRIBESPOOL01FUEL':
                action = None
            else:
                action = Ownership.objects.get(btc_tx=tx).type
        except Ownership.DoesNotExist:
            tx.error_msg = 'Ownership not found for this transaction.'
            tx.status = TX_REJECTED
            tx.save()
            logger.info('Ownership not found for transaction {}'.format(tx.tx))
        except Ownership.MultipleObjectsReturned:
            tx.error_msg = 'Multiple ownership objects returned for this transaction.'
            tx.status = TX_REJECTED
            tx.save()
            logger.info(
                'Multiple ownership objects returned for transaction {}'.
                format(tx.tx))
        else:

            if action == 'OwnershipPiece':
                register_piece.delay(tx.id, util.mainAdminPassword())
            elif action == 'OwnershipEditions':
                editions.delay(tx.id, util.mainAdminPassword())
            elif action == 'OwnershipRegistration':
                register.delay(tx.id, util.mainAdminPassword())
            elif action == 'OwnershipTransfer':
                # Transfers are trigered by refill. Once we push a refill
                # the transfer will go through
                pass
            elif action == 'Consignment':
                # Consignments are trigered by refill. Once we push a refill
                # the consignment will go through
                pass
            elif action == 'UnConsignment':
                # Unconsignments are trigered by refill. Once we push a refill
                # the unconsignment will go through
                pass
            elif action == 'Loan':
                # Loans are trigered by refill. Once we push a refill
                # the loan will go through
                pass
            elif action == 'LoanPiece':
                # Loans of pieces are trigered by refill. Once we push a refill
                # the loan of the piece will go through
                pass
            elif action == 'ConsignedRegistration':
                consigned_registration.delay(tx.id, util.mainAdminPassword())
            elif action == 'OwnershipMigration':
                migrate.delay(tx.id, util.mainAdminPassword())
            elif tx.spoolverb == 'ASCRIBESPOOL01FUEL':
                refill.delay(tx.id, util.mainAdminPassword())
Example #12
0
    def test_acl_edit_of_a_retrieved_transferred_edition(self):
        from dynamicfixtures import (
            _djroot_user,
            _alice,
            _bob,
            _bob_bitcoin_wallet,
            _registered_edition_pair_alice,
            _whitelabel_merlin,
        )
        from bitcoin import tasks
        from bitcoin.models import BitcoinTransaction, BitcoinWallet
        from ownership.models import OwnershipRegistration, OwnershipTransfer
        from util import util
        _djroot_user()
        alice, bob = _alice(), _bob()
        _bob_bitcoin_wallet()
        edition_one, edition_two = _registered_edition_pair_alice()

        # TODO Extract, and/or simplify to the essentials.
        #
        # What are the essentials?
        # - Having two editions.
        # - The two editions belong to the same piece.
        # - The piece has been registered by alice.
        # - One edition has been transferred to bob.
        # - The transferred edition should have its acl_edit set accordingly.
        #
        # So, it may very well be possible to avoid going through all the
        # transfer related operations. Waht matters is that the transferred
        # edition has its fields set like it would have if it would have been
        # transferred. Related objects, which are created and/or modified
        # during a transfer may alos need to be created.
        OwnershipRegistration.objects.create(
            edition=edition_one,
            new_owner=edition_one.owner,
            piece=edition_one.parent,
            type=OwnershipRegistration.__name__,
        )
        transfer = OwnershipTransfer(
            edition=edition_one,
            prev_owner=edition_one.owner,
            new_owner=bob,
            prev_btc_address=None,
            piece=edition_one.parent,
            type=OwnershipTransfer.__name__,
        )
        transfer.ciphertext_wif = BitcoinWallet.encoded_wif_for_path(
            transfer,
            'alice-secret',
        )
        transfer.save()
        transfer_tx = BitcoinTransaction.transfer(transfer)
        refill = BitcoinTransaction.refill(transfer)
        refill.dependent_tx = transfer_tx
        refill.save()
        tasks.refill(refill.id, util.mainAdminPassword())
        edition_one.owner = bob
        edition_one.save()
        # END of transfer

        whitelabel = _whitelabel_merlin()
        subdomain = whitelabel.subdomain
        view = MarketEditionEndpoint.as_view({'get': 'retrieve'})

        url = reverse(
            'api:whitelabel:market:edition-detail',
            kwargs={'domain_pk': subdomain, 'pk': edition_two.bitcoin_id},
        )
        factory = APIRequestFactory()
        request = factory.get(url)
        force_authenticate(request, user=alice)

        response = view(
            request, pk=edition_two.bitcoin_id, domain_pk=subdomain)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertFalse(response.data['edition']['acl']['acl_edit'])
        self.assertTrue(response.data['edition']['acl']['acl_wallet_submit'])