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())
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())
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())
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())
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())
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())
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())
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())
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())
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())
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())
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'])