Example #1
0
    def register(self, from_address, to_address, hash, password, edition_num, min_confirmations=6, sync=False, ownership=True):
        """
        Register an edition or master edition of a piece

        :param from_address: Federation address. All register transactions originate from the the Federation wallet
        :param to_address: Address registering the edition
        :param hash: Hash of the piece. Tuple (file_hash, file_hash_metadata)
        :param password: Federation wallet password. For signing the transaction
        :param edition_num: The number of the edition to register. User edition_num=0 to register the master edition
        :param min_confirmations: Override the number of confirmations when chosing the inputs of the transaction. Defaults to 6
        :param sync: Perform the transaction in synchronous mode, the call to the function will block until there is at
        least on confirmation on the blockchain. Defaults to False
        :param ownership: Check ownsership in the blockchain before pushing the transaction. Defaults to True
        :return: transaction id
        """
        file_hash, file_hash_metadata = hash
        path, from_address = from_address
        verb = Spoolverb(edition_num=edition_num)
        unsigned_tx = self.simple_spool_transaction(from_address,
                                                    [file_hash, file_hash_metadata, to_address],
                                                    op_return=verb.register,
                                                    min_confirmations=min_confirmations)

        signed_tx = self._t.sign_transaction(unsigned_tx, password)
        txid = self._t.push(signed_tx)
        return txid
Example #2
0
    def refill(self, from_address, to_address, nfees, ntokens, password, min_confirmations=6, sync=False):
        """
        Refill wallets with the necessary fuel to perform spool transactions

        :param from_address: Federation wallet address. Fuels the wallets with tokens and fees. All transactions to wallets
                holding a particular piece should come from the Federation wallet
        :param to_address: Wallet address that needs to perform a spool transaction
        :param nfees: Number of fees to transfer. Each fee is 10000 satoshi. Used to pay for the transactions
        :param ntokens: Number of tokens to transfer. Each token is 600 satoshi. Used to register hashes in the blockchain
        :param password: Password for the Federation wallet. Used to sign the transaction
        :param min_confirmations: Number of confirmations when chosing the inputs of the transaction. Defaults to 6
        :param sync: Perform the transaction in synchronous mode, the call to the function will block until there is at
        least on confirmation on the blockchain. Defaults to False
        :return: transaction id
        """
        path, from_address = from_address
        verb = Spoolverb()
        # nfees + 1: nfees to refill plus one fee for the refill transaction itself
        inputs = self.select_inputs(from_address, nfees + 1, ntokens, min_confirmations=min_confirmations)
        outputs = [{'address': to_address, 'value': self.TOKEN}] * ntokens
        outputs += [{'address': to_address, 'value': self.FEE}] * nfees
        outputs += [{'script': self._t._op_return_hex(verb.fuel), 'value': 0}]
        unsigned_tx = self._t.build_transaction(inputs, outputs)
        signed_tx = self._t.sign_transaction(unsigned_tx, password, path=path)
        txid = self._t.push(signed_tx)
        return txid
Example #3
0
    def loan(self, from_address, to_address, hash, password, edition_num, loan_start, loan_end, min_confirmations=6, sync=False, ownership=True):
        """
        Loan the edition

        :param from_address: Address currently holding the edition
        :param to_address: Address to loan the edition to
        :param hash: Hash of the piece. Tuple (file_hash, file_hash_metadata)
        :param password: Password for the wallet currently holding the edition. For signing the transaction
        :param edition_num: the number of the edition to unconsign
        :param loan_start: Start date for the loan. In the form YYMMDD
        :param loan_end: End date for the loan. In the form YYMMDD
        :param min_confirmations: Number of confirmations when chosing the inputs of the transaction. Defaults to 6
        :param sync: Perform the transaction in synchronous mode, the call to the function will block until there is at
        least on confirmation on the blockchain. Defaults to False
        :param ownership: Check ownsership in the blockchain before pushing the transaction. Defaults to True
        :return: transaction id
        """
        path, from_address = from_address
        file_hash, file_hash_metadata = hash
        verb = Spoolverb(edition_num=edition_num, loan_start=loan_start, loan_end=loan_end)
        unsigned_tx = self.simple_spool_transaction(from_address,
                                                    [file_hash, to_address],
                                                    op_return=verb.loan,
                                                    min_confirmations=min_confirmations)
        signed_tx = self._t.sign_transaction(unsigned_tx, password, path=path)
        txid = self._t.push(signed_tx)
        return txid
Example #4
0
    def unconsign(self, from_address, to_address, hash, password, edition_num, min_confirmations=6, sync=False, ownership=True):
        """
        Unconsign the edition

        :param from_address: Address where the edition is currently consigned
        :param to_address: Address that consigned the piece to from_address
        :param hash: Hash of the piece. Tuple (file_hash, file_hash_metadata)
        :param password: Password for the wallet currently holding the edition. For signing the transaction
        :param edition_num: the number of the edition to unconsign
        :param min_confirmations: Number of confirmations when chosing the inputs of the transaction. Defaults to 6
        :param sync: Perform the transaction in synchronous mode, the call to the function will block until there is at
        least on confirmation on the blockchain. Defaults to False
        :param ownership: Check ownsership in the blockchain before pushing the transaction. Defaults to True
        :return: transaction id
        """
        # In an unconsignment the to_address needs to be the address that created the consign transaction
        path, from_address = from_address
        file_hash, file_hash_metadata = hash
        verb = Spoolverb(edition_num=edition_num)
        unsigned_tx = self.simple_spool_transaction(from_address,
                                                    [file_hash, to_address],
                                                    op_return=verb.unconsign,
                                                    min_confirmations=min_confirmations)
        signed_tx = self._t.sign_transaction(unsigned_tx, password, path=path)
        txid = self._t.push(signed_tx)
        return txid
Example #5
0
    def check_script(vouts):
        """
        Looks into the vouts list of a transaction and returns the op_return if one exists
        :param vouts: lists of outputs of a transaction
        :return: string representation of the op_return
        """

        for vout in [v for v in vouts[::-1] if v['hex'].startswith('6a')]:
            verb = BlockchainSpider.decode_op_return(vout['hex'])
            action = Spoolverb.from_verb(verb).action
            if action in Spoolverb.supported_actions:
                return verb
        raise Exception("Invalid ascribe transaction")
Example #6
0
    def check_script(vouts):
        """
        Looks into the vouts list of a transaction and returns the op_return if one exists
        :param vouts: lists of outputs of a transaction
        :return: string representation of the op_return
        """

        for vout in [v for v in vouts[::-1] if v['hex'].startswith('6a')]:
            verb = BlockchainSpider.decode_op_return(vout['hex'])
            action = Spoolverb.from_verb(verb).action
            if action in Spoolverb.supported_actions:
                return verb
        raise Exception("Invalid ascribe transaction")
Example #7
0
    def history(self, hash):
        """
        Retrieve the ownership tree of all editions of a piece given the hash.

        Args:
            hash (str): Hash of the file to check. Can be created with the
                :class:`File` class

        Returns:
            ownsership tree of all editions of a piece

        .. note:: For now we only support searching the blockchain by
            the piece hash.

        """
        txs = self._t.get(hash, max_transactions=10000)['transactions']
        tree = defaultdict(list)
        number_editions = 0

        for tx in txs:
            _tx = self._t.get(tx['txid'])
            txid = _tx['txid']
            verb_str = BlockchainSpider.check_script(_tx['vouts'])
            verb = Spoolverb.from_verb(verb_str)
            from_address, to_address, piece_address = BlockchainSpider._get_addresses(_tx)
            timestamp_utc = _tx['time']
            action = verb.action

            edition_number = 0
            if action != 'EDITIONS':
                edition_number = verb.edition_number
            else:
                number_editions = verb.num_editions

            tree[edition_number].append({'txid': txid,
                                         'verb': verb_str,
                                         'from_address': from_address,
                                         'to_address': to_address,
                                         'piece_address': piece_address,
                                         'timestamp_utc': timestamp_utc,
                                         'action': action,
                                         'number_editions': number_editions,
                                         'edition_number': edition_number})

        # lets update the records with the number of editions of the piece since we do not know
        # this information before the EDITIONS transaction
        for edition, chain in tree.iteritems():
            [d.update({'number_editions': number_editions}) for d in chain]
        return dict(tree)
Example #8
0
    def history(self, hash):
        """
        Retrieve the ownership tree of all editions of a piece given the hash

        :param hash: Hash of the file to check. Can be created with the File class
        :return: ownsership tree of all editions of a piece
        """

        # For now we only support searching the blockchain by the piece hash
        txs = self._t.get(hash, max_transactions=10000)['transactions']
        tree = defaultdict(list)
        number_editions = 0

        for tx in txs:
            _tx = self._t.get(tx['txid'])
            txid = _tx['txid']
            verb_str = BlockchainSpider.check_script(_tx['vouts'])
            verb = Spoolverb.from_verb(verb_str)
            from_address, to_address, piece_address = BlockchainSpider._get_addresses(
                _tx)
            timestamp_utc = _tx['time']
            action = verb.action

            edition_number = 0
            if action != 'EDITIONS':
                edition_number = verb.edition_number
            else:
                number_editions = verb.num_editions

            tree[edition_number].append({
                'txid': txid,
                'verb': verb_str,
                'from_address': from_address,
                'to_address': to_address,
                'piece_address': piece_address,
                'timestamp_utc': timestamp_utc,
                'action': action,
                'number_editions': number_editions,
                'edition_number': edition_number
            })

        # lets update the records with the number of editions of the piece since we do not know
        # this information before the EDITIONS transaction
        for edition, chain in tree.iteritems():
            [d.update({'number_editions': number_editions}) for d in chain]
        return dict(tree)