def can_register(self): # 1. The master piece needs to be registered # 2. The number of editions needs to be registered # 3. The edition_number should not have been registered yet # 4. TODO The root address owns the piece # right now we cannot do this because we only receive the leaf address # when registering an edition chain = BlockchainSpider.chain(self._tree, 0) # edition 0 should only have two transactions: REGISTER and EDITIONS if len(chain) == 0: self.reason = 'Master edition not yet registered' return False chain = BlockchainSpider.strip_loan(chain) number_editions = chain[0]['number_editions'] if number_editions == 0: self.reason = 'Number of editions not yet registered' return False if self.edition_number > number_editions: self.reason = 'You can only register {} editions. You are trying to register edition {}'.format(number_editions, self.edition_number) return False if self.edition_number in self._tree: self.reason = 'Edition number {} is already registerd in the blockchain'. format(self.edition_number) return False return True
def can_register(self): # 1. The master piece needs to be registered # 2. The number of editions needs to be registered # 3. The edition_number should not have been registered yet # 4. TODO The root address owns the piece # right now we cannot do this because we only receive the leaf address # when registering an edition chain = BlockchainSpider.chain(self._tree, 0) # edition 0 should only have two transactions: REGISTER and EDITIONS if len(chain) == 0: self.reason = 'Master edition not yet registered' return False chain = BlockchainSpider.strip_loan(chain) number_editions = chain[0]['number_editions'] if number_editions == 0: self.reason = 'Number of editions not yet registered' return False if self.edition_number > number_editions: self.reason = 'You can only register {} editions. You are trying to register edition {}'.format( number_editions, self.edition_number) return False if self.edition_number in self._tree: self.reason = 'Edition number {} is already registerd in the blockchain'.format( self.edition_number) return False return True
def can_transfer(self): # 1. The address needs to own the edition chain = BlockchainSpider.chain(self._tree, self.edition_number) if len(chain) == 0: self.reason = 'The edition number {} does not exist in the blockchain'.format(self.edition_number) return False chain = BlockchainSpider.strip_loan(chain) to_address = chain[-1]['to_address'] if to_address != self.address: self.reason = 'Address {} does not own the edition number {}'.format(self.address, self.edition_number) return False return True
def can_editions(self): # in order to register the number of editions: # 1. There needs to a least one transaction for the piece_address (the registration of the master edition) # 2. a piece with address piece_address needs to be registered with ASCRIBESPOOL01REGISTER0 (master edition) # 3. the number of editions should have not been set yet (no tx with verb ASCRIBESPOOLEDITIONS) chain = BlockchainSpider.chain(self._tree, 0) if len(chain) == 0: self.reason = 'Master edition not yet registered' return False number_editions = chain[0]['number_editions'] if number_editions != 0: self.reason = 'Number of editions was already registered for this piece' return False return True
def can_transfer(self): # 1. The address needs to own the edition chain = BlockchainSpider.chain(self._tree, self.edition_number) if len(chain) == 0: self.reason = 'The edition number {} does not exist in the blockchain'.format( self.edition_number) return False chain = BlockchainSpider.strip_loan(chain) to_address = chain[-1]['to_address'] if to_address != self.address: self.reason = 'Address {} does not own the edition number {}'.format( self.address, self.edition_number) return False return True
def can_unconsign(self): # 1. If the last transaction is a consign of the edition to the user chain = BlockchainSpider.chain(self._tree, self.edition_number) if len(chain) == 0: self.reason = 'Master edition not yet registered' return False chain = BlockchainSpider.strip_loan(chain) action = chain[-1]['action'] piece_address = chain[-1]['piece_address'] edition_number = chain[-1]['edition_number'] to_address = chain[-1]['to_address'] if action != 'CONSIGN' or piece_address != self.piece_address or edition_number != self.edition_number or to_address != self.address: self.reason = 'Edition number {} is not consigned to {}'.format(self.edition_number, self.address) return False return True
def can_unconsign(self): # 1. If the last transaction is a consign of the edition to the user chain = BlockchainSpider.chain(self._tree, self.edition_number) if len(chain) == 0: self.reason = 'Master edition not yet registered' return False chain = BlockchainSpider.strip_loan(chain) action = chain[-1]['action'] piece_address = chain[-1]['piece_address'] edition_number = chain[-1]['edition_number'] to_address = chain[-1]['to_address'] if action != 'CONSIGN' or piece_address != self.piece_address or edition_number != self.edition_number or to_address != self.address: self.reason = 'Edition number {} is not consigned to {}'.format( self.edition_number, self.address) return False return True
def wrapper(*args, **kwargs): sync = kwargs.get('sync', False) ownsership = kwargs.get('ownership', False) name = f.__name__ testnet = args[0].testnet t = args[0]._t from_address = args[1][1] to_address = args[2] password = args[4] # TODO remove, as it is not used # a piece has no edition number if name not in ['register_piece', 'consigned_registration']: edition_number = args[5] hash = '' if name not in ['refill', 'refill_main_wallet']: hash = args[3][0] # check ownership if ownsership: if name == 'register' and edition_number == 0: ow = Ownership(to_address, hash, edition_number, testnet=testnet) if not ow.can_register_master: raise OwnershipError(ow.reason) elif name == 'register' and edition_number != 0: ow = Ownership(to_address, hash, edition_number, testnet=testnet) if not ow.can_register: raise OwnershipError(ow.reason) elif name == 'editions': ow = Ownership(to_address, hash, edition_number, testnet=testnet) if not ow.can_editions: raise OwnershipError(ow.reason) elif name == 'transfer' or name == 'consign' or name == 'loan': ow = Ownership(from_address, hash, edition_number, testnet=testnet) if not ow.can_transfer: raise OwnershipError(ow.reason) elif name == 'unconsign': ow = Ownership(from_address, hash, edition_number, testnet=testnet) if not ow.can_unconsign: raise OwnershipError(ow.reason) # check the to address chain = BlockchainSpider.chain(ow._tree, edition_number) chain_from_address = chain[-1]['from_address'] if chain_from_address != to_address: raise OwnershipError('You can only unconsign to {}'.format(chain_from_address)) # do a synchronous transaction if sync: txid = f(*args, **kwargs) # lets give it some time for the transaction to reach the network confirmations = 0 timeout = TIMEOUT while not confirmations: # lets do a simple exponential backoff. Transactions may take some time to be picked up by some # services try: confirmations = t.get(txid).get('confirmations', 0) timeout = TIMEOUT except Exception as e: if e.message.find('code: 404') != -1: timeout *= 2 if timeout > MAX_TIMEOUT: raise else: raise time.sleep(timeout) return txid else: return f(*args, **kwargs)
def wrapper(*args, **kwargs): sync = kwargs.get('sync', False) ownsership = kwargs.get('ownership', False) name = f.__name__ testnet = args[0].testnet t = args[0]._t from_address = args[1][1] to_address = args[2] password = args[4] # a piece has no edition number if name not in ['register_piece', 'consigned_registration']: edition_number = args[5] hash = '' if name not in ['refill', 'refill_main_wallet']: hash = args[3][0] # check ownership if ownsership: if name == 'register' and edition_number == 0: ow = Ownership(to_address, hash, edition_number, testnet=testnet) if not ow.can_register_master: raise OwnershipError(ow.reason) elif name == 'register' and edition_number != 0: ow = Ownership(to_address, hash, edition_number, testnet=testnet) if not ow.can_register: raise OwnershipError(ow.reason) elif name == 'editions': ow = Ownership(to_address, hash, edition_number, testnet=testnet) if not ow.can_editions: raise OwnershipError(ow.reason) elif name == 'transfer' or name == 'consign' or name == 'loan': ow = Ownership(from_address, hash, edition_number, testnet=testnet) if not ow.can_transfer: raise OwnershipError(ow.reason) elif name == 'unconsign': ow = Ownership(from_address, hash, edition_number, testnet=testnet) if not ow.can_unconsign: raise OwnershipError(ow.reason) # check the to address chain = BlockchainSpider.chain(ow._tree, edition_number) chain_from_address = chain[-1]['from_address'] if chain_from_address != to_address: raise OwnershipError('You can only unconsign to {}'.format(chain_from_address)) # do a synchronous transaction if sync: txid = f(*args, **kwargs) # lets give it some time for the transaction to reach the network confirmations = 0 timeout = TIMEOUT while not confirmations: # lets do a simple exponential backoff. Transactions may take some time to be picked up by some # services try: confirmations = t.get(txid).get('confirmations', 0) timeout = TIMEOUT except Exception as e: if e.message.find('code: 404') != -1: timeout *= 2 if timeout > MAX_TIMEOUT: raise else: raise time.sleep(timeout) return txid else: return f(*args, **kwargs)