Ejemplo n.º 1
0
    def test_get_owned_ids_single_tx_single_output(self, b, user_sk, user_pk,
                                                   alice):
        from bigchaindb.common import crypto
        from bigchaindb.common.transaction import TransactionLink
        from bigchaindb.models import Transaction

        user2_sk, user2_pk = crypto.generate_key_pair()

        tx = Transaction.create([alice.public_key], [([user_pk], 1)])
        tx = tx.sign([alice.private_key])
        block = b.create_block([tx])
        b.write_block(block)

        owned_inputs_user1 = b.get_owned_ids(user_pk)
        owned_inputs_user2 = b.get_owned_ids(user2_pk)
        assert owned_inputs_user1 == [TransactionLink(tx.id, 0)]
        assert owned_inputs_user2 == []

        tx = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)],
                                  asset_id=tx.id)
        tx = tx.sign([user_sk])
        block = b.create_block([tx])
        b.write_block(block)

        owned_inputs_user1 = b.get_owned_ids(user_pk)
        owned_inputs_user2 = b.get_owned_ids(user2_pk)
        assert owned_inputs_user1 == []
        assert owned_inputs_user2 == [TransactionLink(tx.id, 0)]
Ejemplo n.º 2
0
def test_transaction_link_deserialization_with_empty_payload():
    from bigchaindb.common.transaction import TransactionLink

    expected = TransactionLink()
    tx_link = TransactionLink.from_dict(None)

    assert tx_link == expected
Ejemplo n.º 3
0
def test_get_outputs_by_public_key(b, user_pk, user2_pk, blockdata):
    blocks, _ = blockdata
    assert b.fastquery.get_outputs_by_public_key(user_pk) == [
        TransactionLink(blocks[1]['block']['transactions'][0]['id'], 0)
    ]
    assert b.fastquery.get_outputs_by_public_key(user2_pk) == [
        TransactionLink(blocks[0]['block']['transactions'][0]['id'], 0)
    ]
Ejemplo n.º 4
0
def test_cast_transaction_link_to_boolean():
    from bigchaindb.common.transaction import TransactionLink

    assert bool(TransactionLink()) is False
    assert bool(TransactionLink('a', None)) is False
    assert bool(TransactionLink(None, 'b')) is False
    assert bool(TransactionLink('a', 'b')) is True
    assert bool(TransactionLink(False, False)) is True
Ejemplo n.º 5
0
def test_get_outputs_by_public_key(b, user_pk, user2_pk, txns):
    assert b.fastquery.get_outputs_by_public_key(user_pk) == [
        TransactionLink(txns[1].id, 0),
        TransactionLink(txns[2].id, 0)
    ]
    assert b.fastquery.get_outputs_by_public_key(user2_pk) == [
        TransactionLink(txns[0].id, 0),
        TransactionLink(txns[2].id, 1),
    ]
Ejemplo n.º 6
0
def test_transaction_link_serialization():
    from bigchaindb.common.transaction import TransactionLink

    tx_id = 'a transaction id'
    expected = {
        'transaction_id': tx_id,
        'output_index': 0,
    }
    tx_link = TransactionLink(tx_id, 0)

    assert tx_link.to_dict() == expected
Ejemplo n.º 7
0
def test_get_outputs_filtered_only_spent():
    from bigchaindb.common.transaction import TransactionLink
    from bigchaindb.lib import BigchainDB
    go = 'bigchaindb.fastquery.FastQuery.get_outputs_by_public_key'
    with patch(go) as get_outputs:
        get_outputs.return_value = [TransactionLink('a', 1),
                                    TransactionLink('b', 2)]
        fs = 'bigchaindb.fastquery.FastQuery.filter_unspent_outputs'
        with patch(fs) as filter_spent:
            filter_spent.return_value = [TransactionLink('b', 2)]
            out = BigchainDB().get_outputs_filtered('abc', spent=True)
    get_outputs.assert_called_once_with('abc')
    assert out == [TransactionLink('b', 2)]
Ejemplo n.º 8
0
def test_get_outputs_filtered(filter_spent, filter_unspent):
    from bigchaindb.common.transaction import TransactionLink
    from bigchaindb.lib import BigchainDB

    go = 'bigchaindb.fastquery.FastQuery.get_outputs_by_public_key'
    with patch(go) as get_outputs:
        get_outputs.return_value = [TransactionLink('a', 1),
                                    TransactionLink('b', 2)]
        out = BigchainDB().get_outputs_filtered('abc')
    get_outputs.assert_called_once_with('abc')
    filter_spent.assert_not_called()
    filter_unspent.assert_not_called()
    assert out == get_outputs.return_value
Ejemplo n.º 9
0
def test_transaction_link_eq():
    from bigchaindb.common.transaction import TransactionLink

    assert TransactionLink(1, 2) == TransactionLink(1, 2)
    assert TransactionLink(2, 2) != TransactionLink(1, 2)
    assert TransactionLink(1, 1) != TransactionLink(1, 2)
    assert TransactionLink(2, 1) != TransactionLink(1, 2)
Ejemplo n.º 10
0
    def get_owned_ids(self, owner):
        """Retrieve a list of `txid`s that can be used as inputs.

        Args:
            owner (str): base58 encoded public key.

        Returns:
            :obj:`list` of TransactionLink: list of `txid`s and `cid`s
            pointing to another transaction's condition
        """

        # get all transactions in which owner is in the `owners_after` list
        response = self.connection.run(
            r.table('bigchain', read_mode=self.read_mode).concat_map(
                lambda doc: doc['block']['transactions']).filter(
                    lambda tx: tx['transaction']['conditions'].contains(
                        lambda c: c['owners_after'].contains(owner))))
        owned = []

        for tx in response:
            # disregard transactions from invalid blocks
            validity = self.get_blocks_status_containing_tx(tx['id'])
            if Bigchain.BLOCK_VALID not in validity.values():
                if Bigchain.BLOCK_UNDECIDED not in validity.values():
                    continue

            # NOTE: It's OK to not serialize the transaction here, as we do not
            #       use it after the execution of this function.
            # a transaction can contain multiple outputs (conditions) so we need to iterate over all of them
            # to get a list of outputs available to spend
            for index, cond in enumerate(tx['transaction']['conditions']):
                # for simple signature conditions there are no subfulfillments
                # check if the owner is in the condition `owners_after`
                if len(cond['owners_after']) == 1:
                    if cond['condition']['details']['public_key'] == owner:
                        tx_link = TransactionLink(tx['id'], index)
                else:
                    # for transactions with multiple `owners_after` there will be several subfulfillments nested
                    # in the condition. We need to iterate the subfulfillments to make sure there is a
                    # subfulfillment for `owner`
                    if util.condition_details_has_owner(
                            cond['condition']['details'], owner):
                        tx_link = TransactionLink(tx['id'], index)
                # check if input was already spent
                if not self.get_spent(tx_link.txid, tx_link.cid):
                    owned.append(tx_link)

        return owned
Ejemplo n.º 11
0
def transfer_utx(user_output, user2_output, utx):
    from bigchaindb.common.transaction import (Input, TransactionLink,
                                               Transaction)
    user_output = user_output.to_dict()
    input = Input(utx.outputs[0].fulfillment, user_output['public_keys'],
                  TransactionLink(utx.id, 0))
    return Transaction('TRANSFER', {'id': utx.id}, [input], [user2_output])
    def test_get_owned_ids_multiple_owners(self, b, user_sk, user_pk, alice):
        from bigchaindb.common import crypto
        from bigchaindb.common.transaction import TransactionLink
        from bigchaindb.models import Transaction

        user2_sk, user2_pk = crypto.generate_key_pair()
        user3_sk, user3_pk = crypto.generate_key_pair()

        tx = Transaction.create([alice.public_key], [([user_pk, user2_pk], 1)])
        tx = tx.sign([alice.private_key])

        b.store_bulk_transactions([tx])

        owned_inputs_user1 = b.fastquery.get_outputs_by_public_key(user_pk)
        owned_inputs_user2 = b.fastquery.get_outputs_by_public_key(user_pk)
        expected_owned_inputs_user1 = [TransactionLink(tx.id, 0)]

        assert owned_inputs_user1 == owned_inputs_user2
        assert owned_inputs_user1 == expected_owned_inputs_user1

        tx = Transaction.transfer(tx.to_inputs(), [([user3_pk], 1)],
                                  asset_id=tx.id)
        tx = tx.sign([user_sk, user2_sk])
        b.store_bulk_transactions([tx])

        owned_inputs_user1 = b.fastquery.get_outputs_by_public_key(user_pk)
        owned_inputs_user2 = b.fastquery.get_outputs_by_public_key(user2_pk)
        spent_user1 = b.get_spent(tx.id, 0)

        assert owned_inputs_user1 == owned_inputs_user2
        assert not spent_user1
Ejemplo n.º 13
0
    def test_non_create_input_not_found(self, b, user_pk, signed_transfer_tx):
        from bigchaindb.common.exceptions import InputDoesNotExist
        from bigchaindb.common.transaction import TransactionLink

        signed_transfer_tx.inputs[0].fulfills = TransactionLink('c', 0)
        with pytest.raises(InputDoesNotExist):
            b.validate_transaction(signed_transfer_tx)
Ejemplo n.º 14
0
def test_transaction_link_to_uri():
    from bigchaindb.common.transaction import TransactionLink

    expected = 'path/transactions/abc/outputs/0'
    tx_link = TransactionLink('abc', 0).to_uri('path')

    assert expected == tx_link
Ejemplo n.º 15
0
def test_multiple_input_validation_of_transfer_tx(user_input, user_output,
                                                  user_priv, user2_pub,
                                                  user2_priv, user3_pub,
                                                  user3_priv,
                                                  asset_definition):
    from bigchaindb.common.transaction import (Transaction, TransactionLink,
                                               Input, Output)
    from cryptoconditions import Ed25519Sha256
    from .utils import validate_transaction_model

    tx = Transaction(Transaction.CREATE, asset_definition, [user_input],
                     [user_output, deepcopy(user_output)])
    tx.sign([user_priv])

    inputs = [
        Input(cond.fulfillment, cond.public_keys,
              TransactionLink(tx.id, index))
        for index, cond in enumerate(tx.outputs)
    ]
    outputs = [
        Output(Ed25519Sha256(public_key=b58decode(user3_pub)), [user3_pub]),
        Output(Ed25519Sha256(public_key=b58decode(user3_pub)), [user3_pub])
    ]
    transfer_tx = Transaction('TRANSFER', {'id': tx.id}, inputs, outputs)
    transfer_tx = transfer_tx.sign([user_priv])

    assert transfer_tx.inputs_valid(tx.outputs) is True

    validate_transaction_model(tx)
Ejemplo n.º 16
0
def test_transaction_link_empty_to_uri():
    from bigchaindb.common.transaction import TransactionLink

    expected = None
    tx_link = TransactionLink().to_uri()

    assert expected == tx_link
Ejemplo n.º 17
0
 def get_outputs_by_public_key(self, public_key):
     """Get outputs for a public key"""
     txs = list(query.get_owned_ids(self.connection, public_key))
     return [TransactionLink(tx['id'], index)
             for tx in txs
             for index, output in enumerate(tx['outputs'])
             if condition_details_has_owner(output['condition']['details'],
                                            public_key)]
Ejemplo n.º 18
0
def prepare_transfer(inputs, outputs, metadata=None):
    """Create an instance of a :class:`~.Output`.

    Args:
        inputs (list of
                    (dict):
                        {
                            'tx': <(bigchaindb.common.transactionTransaction):
                                    input transaction, can differ but must have same asset id>,
                            'output': <(int): output index of tx>
                        }
                )
        outputs (list of
                    (dict):
                        {
                            'condition': <(cryptoconditions.Condition): output condition>,
                            'public_keys': <(optional list of base58): for indexing defaults to `None`>,
                            'amount': <(int): defaults to `1`>
                        }
                )
        metadata (dict)
    Raises:
        TypeError: if `public_keys` is not instance of `list`.
            """
    from bigchaindb.common.transaction import (Input, Output, TransactionLink)

    from bigchaindb.models import Transaction

    from cryptoconditions import (Fulfillment, Condition)

    asset = inputs[0]['tx']['asset']
    asset = {'id': asset['id'] if 'id' in asset else inputs[0]['tx']['id']}

    _inputs, _outputs = [], []

    for _input in inputs:

        _output = _input['tx']['outputs'][_input['output']]
        _inputs.append(
            Input(fulfillment=Condition.from_uri(_output['condition']['uri']),
                  owners_before=_output['public_keys'],
                  fulfills=TransactionLink(txid=_input['tx']['id'],
                                           output=_input['output'])))

    for output in outputs:
        _outputs.append(
            Output(fulfillment=output['condition'],
                   public_keys=output['public_keys']
                   if "public_keys" in output else [],
                   amount=output['amount'] if "amount" in output else 1))

    return Transaction(
        operation='TRANSFER',
        asset=asset,
        inputs=_inputs,
        outputs=_outputs,
        metadata=metadata,
    )
Ejemplo n.º 19
0
    def test_get_owned_ids_single_tx_single_output_invalid_block(self, b,
                                                                 user_sk,
                                                                 user_pk,
                                                                 genesis_block,
                                                                 alice):
        from bigchaindb.common import crypto
        from bigchaindb.common.transaction import TransactionLink
        from bigchaindb.models import Transaction

        user2_sk, user2_pk = crypto.generate_key_pair()

        tx = Transaction.create([alice.public_key], [([user_pk], 1)])
        tx = tx.sign([alice.private_key])
        block = b.create_block([tx])
        b.write_block(block)

        # vote the block VALID
        vote = b.vote(block.id, genesis_block.id, True)
        b.write_vote(vote)

        owned_inputs_user1 = b.get_owned_ids(user_pk)
        owned_inputs_user2 = b.get_owned_ids(user2_pk)
        assert owned_inputs_user1 == [TransactionLink(tx.id, 0)]
        assert owned_inputs_user2 == []

        # NOTE: The transaction itself is valid, still will mark the block
        #       as invalid to mock the behavior.
        tx_invalid = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)],
                                          asset_id=tx.id)
        tx_invalid = tx_invalid.sign([user_sk])
        block = b.create_block([tx_invalid])
        b.write_block(block)

        # vote the block invalid
        vote = b.vote(block.id, b.get_last_voted_block().id, False)
        b.write_vote(vote)

        owned_inputs_user1 = b.get_owned_ids(user_pk)
        owned_inputs_user2 = b.get_owned_ids(user2_pk)

        # should be the same as before (note tx, not tx_invalid)
        assert owned_inputs_user1 == [TransactionLink(tx.id, 0)]
        assert owned_inputs_user2 == []
Ejemplo n.º 20
0
 def get_outputs_by_public_key(self, public_key):
     """
     Get outputs for a public key
     """
     res = list(query.get_owned_ids(self.connection, public_key))
     txs = [tx for _, tx in self.filter_valid_items(res)]
     return [
         TransactionLink(tx['id'], index) for tx in txs
         for index, output in enumerate(tx['outputs'])
         if output_has_owner(output, public_key)
     ]
Ejemplo n.º 21
0
    def test_get_owned_ids_single_tx_multiple_outputs(self, b, user_sk,
                                                      user_pk, alice):
        from bigchaindb.common import crypto
        from bigchaindb.common.transaction import TransactionLink
        from bigchaindb.models import Transaction

        user2_sk, user2_pk = crypto.generate_key_pair()

        # create divisible asset
        tx_create = Transaction.create([alice.public_key], [([user_pk], 1),
                                                            ([user_pk], 1)])
        tx_create_signed = tx_create.sign([alice.private_key])
        block = b.create_block([tx_create_signed])
        b.write_block(block)

        # get input
        owned_inputs_user1 = b.get_owned_ids(user_pk)
        owned_inputs_user2 = b.get_owned_ids(user2_pk)

        expected_owned_inputs_user1 = [
            TransactionLink(tx_create.id, 0),
            TransactionLink(tx_create.id, 1)
        ]
        assert owned_inputs_user1 == expected_owned_inputs_user1
        assert owned_inputs_user2 == []

        # transfer divisible asset divided in two outputs
        tx_transfer = Transaction.transfer(tx_create.to_inputs(),
                                           [([user2_pk], 1), ([user2_pk], 1)],
                                           asset_id=tx_create.id)
        tx_transfer_signed = tx_transfer.sign([user_sk])
        block = b.create_block([tx_transfer_signed])
        b.write_block(block)

        owned_inputs_user1 = b.get_owned_ids(user_pk)
        owned_inputs_user2 = b.get_owned_ids(user2_pk)
        assert owned_inputs_user1 == []
        assert owned_inputs_user2 == [
            TransactionLink(tx_transfer.id, 0),
            TransactionLink(tx_transfer.id, 1)
        ]
Ejemplo n.º 22
0
    def get_outputs(self, owner):
        """Retrieve a list of links to transaction outputs for a given public
           key.

        Args:
            owner (str): base58 encoded public key.

        Returns:
            :obj:`list` of TransactionLink: list of ``txid`` s and ``output`` s
            pointing to another transaction's condition
        """
        # get all transactions in which owner is in the `owners_after` list
        response = backend.query.get_owned_ids(self.connection, owner)
        links = []

        for tx in response:
            # disregard transactions from invalid blocks
            validity = self.get_blocks_status_containing_tx(tx['id'])
            if Bigchain.BLOCK_VALID not in validity.values():
                if Bigchain.BLOCK_UNDECIDED not in validity.values():
                    continue

            # NOTE: It's OK to not serialize the transaction here, as we do not
            # use it after the execution of this function.
            # a transaction can contain multiple outputs so we need to iterate over all of them
            # to get a list of outputs available to spend
            for index, output in enumerate(tx['outputs']):
                # for simple signature conditions there are no subfulfillments
                # check if the owner is in the condition `owners_after`
                if len(output['public_keys']) == 1:
                    if output['condition']['details']['public_key'] == owner:
                        tx_link = TransactionLink(tx['id'], index)
                else:
                    # for transactions with multiple `public_keys` there will be several subfulfillments nested
                    # in the condition. We need to iterate the subfulfillments to make sure there is a
                    # subfulfillment for `owner`
                    if utils.condition_details_has_owner(
                            output['condition']['details'], owner):
                        tx_link = TransactionLink(tx['id'], index)
                links.append(tx_link)
        return links
Ejemplo n.º 23
0
    def filter_unspent_outputs(self, outputs):
        """Remove outputs that have not been spent

        Args:
            outputs: list of TransactionLink
        """
        links = [o.to_dict() for o in outputs]
        txs = list(query.get_spending_transactions(self.connection, links))
        spends = {TransactionLink.from_dict(input_['fulfills'])
                  for tx in txs
                  for input_ in tx['inputs']}
        return [ff for ff in outputs if ff in spends]
Ejemplo n.º 24
0
    def filter_unspent_outputs(self, outputs):
        """Remove outputs that have not been spent

        Args:
            outputs: list of TransactionLink
        """
        links = [o.to_dict() for o in outputs]
        txs = list(query.get_spending_transactions(self.connection, links))
        spends = {TransactionLink.from_dict(input_['fulfills'])
                  for tx in txs
                  for input_ in tx['inputs']}
        return [ff for ff in outputs if ff in spends]
Ejemplo n.º 25
0
    def filter_spent_outputs(self, outputs):
        """Remove outputs that have been spent

        Args:
            outputs: list of TransactionLink
        """
        links = [o.to_dict() for o in outputs]
        res = query.get_spending_transactions(self.connection, links)
        txs = [tx for _, tx in self.filter_valid_items(res)]
        spends = {TransactionLink.from_dict(input_['fulfills'])
                  for tx in txs
                  for input_ in tx['inputs']}
        return [ff for ff in outputs if ff not in spends]
    def test_non_create_input_not_found(self, b, user_pk):
        from cryptoconditions import Ed25519Sha256
        from bigchaindb.common.exceptions import InputDoesNotExist
        from bigchaindb.common.transaction import Input, TransactionLink
        from bigchaindb.models import Transaction

        # Create an input for a non existing transaction
        input = Input(Ed25519Sha256(public_key=b58decode(user_pk)), [user_pk],
                      TransactionLink('somethingsomething', 0))
        tx = Transaction.transfer([input], [([user_pk], 1)],
                                  asset_id='mock_asset_link')
        with pytest.raises(InputDoesNotExist):
            tx.validate(b)
Ejemplo n.º 27
0
    def filter_spent_outputs(self, outputs):
        """Remove outputs that have been spent

        Args:
            outputs: list of TransactionLink
        """
        links = [o.to_dict() for o in outputs]
        res = query.get_spending_transactions(self.connection, links)
        txs = [tx for _, tx in self.filter_valid_items(res)]
        spends = {
            TransactionLink.from_dict(input_['fulfills'])
            for tx in txs for input_ in tx['inputs']
        }
        return [ff for ff in outputs if ff not in spends]
Ejemplo n.º 28
0
    def get_outputs(self, owner):
        """Retrieve a list of links to transaction outputs for a given public
           key.

        Args:
            owner (str): base58 encoded public key.

        Returns:
            :obj:`list` of TransactionLink: list of ``txid`` s and ``output`` s
            pointing to another transaction's condition
        """
        # get all transactions in which owner is in the `owners_after` list
        response = backend.query.get_owned_ids(self.connection, owner)
        return [
            TransactionLink(tx['id'], index)
            for tx in response
            if not self.is_tx_strictly_in_invalid_block(tx['id'])
            for index, output in enumerate(tx['outputs'])
            if utils.output_has_owner(output, owner)
        ]
Ejemplo n.º 29
0
def prepare_transfer_transaction(*,
                                 inputs,
                                 recipients,
                                 asset,
                                 metadata=None):
    """
    Prepares a ``"TRANSFER"`` transaction payload, ready to be
    fulfilled.

    Args:
        inputs (:obj:`dict` | :obj:`list` | :obj:`tuple`): One or more
            inputs holding the condition(s) that this transaction
            intends to fulfill. Each input is expected to be a
            :obj:`dict`.
        recipients (:obj:`str` | :obj:`list` | :obj:`tuple`): One or
            more public keys representing the new recipients(s) of the
            asset being transferred.
        asset (:obj:`dict`): A single-key dictionary holding the ``id``
            of the asset being transferred with this transaction.
        metadata (:obj:`dict`): Metadata associated with the
            transaction. Defaults to ``None``.

    Returns:
        dict: The prepared ``"TRANSFER"`` transaction.

    .. important::

        * ``asset`` MUST be in the form of::

            {
                'id': '<Asset ID (i.e. TX ID of its CREATE transaction)>'
            }

    Example:

        .. todo:: Replace this section with docs.

        In case it may not be clear what an input should look like, say
        Alice (public key: ``'3Cxh1eKZk3Wp9KGBWFS7iVde465UvqUKnEqTg2MW4wNf'``)
        wishes to transfer an asset over to Bob
        (public key: ``'EcRawy3Y22eAUSS94vLF8BVJi62wbqbD9iSUSUNU9wAA'``).
        Let the asset creation transaction payload be denoted by
        ``tx``::

            # noqa E501
            >>> tx
            {'id': '57cff2b9490468bdb6d4767a1b07905fdbe18d638d9c7783f639b4b2bc165c39',
             'transaction': {'asset': {'data': {'msg': 'Hello BigchainDB!'},
               'id': '57cff2b9490468bdb6d4767a1b07905fdbe18d638d9c7783f639b4b2bc165c39'},
              'conditions': [{'amount': 1,
                'cid': 0,
                'condition': {'details': {'bitmask': 32,
                  'public_key': '3Cxh1eKZk3Wp9KGBWFS7iVde465UvqUKnEqTg2MW4wNf',
                  'signature': None,
                  'type': 'fulfillment',
                  'type_id': 4},
                 'uri': 'cc:4:20:IMe7QSL5xRAYIlXon76ZonWktR0NI02M8rAG1bN-ugg:96'},
                'owners_after': ['3Cxh1eKZk3Wp9KGBWFS7iVde465UvqUKnEqTg2MW4wNf']}],
              'fulfillments': [{'fid': 0,
                'fulfillment': 'cf:4:IMe7QSL5xRAYIlXon76ZonWktR0NI02M8rAG1bN-ughA8-9lUJYc_LGAB_NtyTPCCV58LfMcNZ9-0PUB6m1y_6pgTbCOQFBEeDtm_nC293CbpZjziwq7j3skrzS-OiAI',
                'input': None,
                'owners_before': ['3Cxh1eKZk3Wp9KGBWFS7iVde465UvqUKnEqTg2MW4wNf']}],
              'metadata': None,
              'operation': 'CREATE',
              'timestamp': '1479393278'},
             'version': 1}


        Then, the input may be constructed in this way::

            cid = 0
            condition = tx['transaction']['conditions'][cid]
            input_ = {
                'fulfillment': condition['condition']['details'],
                'input': {
                    'cid': cid,
                    'txid': tx['id'],
                },
                'owners_before': condition['owners_after'],
            }

        Displaying the input on the prompt would look like::

            >>> input_
            {'fulfillment': {'bitmask': 32,
              'public_key': '3Cxh1eKZk3Wp9KGBWFS7iVde465UvqUKnEqTg2MW4wNf',
              'signature': None,
              'type': 'fulfillment',
              'type_id': 4},
             'input': {'cid': 0,
              'txid': '57cff2b9490468bdb6d4767a1b07905fdbe18d638d9c7783f639b4b2bc165c39'},
             'owners_before': ['3Cxh1eKZk3Wp9KGBWFS7iVde465UvqUKnEqTg2MW4wNf']}


        To prepare the transfer:

        >>> prepare_transfer_transaction(
        ...     inputs=input_,
        ...     recipients='EcRawy3Y22eAUSS94vLF8BVJi62wbqbD9iSUSUNU9wAA',
        ...     asset=tx['transaction']['asset'],
        ... )

    """
    if not isinstance(inputs, (list, tuple)):
        inputs = (inputs, )
    if not isinstance(recipients, (list, tuple)):
        recipients = [([recipients], 1)]

    # NOTE: Needed for the time being. See
    # https://github.com/bigchaindb/bigchaindb/issues/797
    if isinstance(recipients, tuple):
        recipients = [(list(recipients), 1)]

    fulfillments = [
        Input(Fulfillment.from_dict(input_['fulfillment']),
              input_['owners_before'],
              fulfills=TransactionLink(**input_['fulfills']))
        for input_ in inputs
    ]

    transaction = Transaction.transfer(
        fulfillments,
        recipients,
        asset_id=asset['id'],
        metadata=metadata,
    )
    return transaction.to_dict()
Ejemplo n.º 30
0
def main():
    """ Main function """

    ctx = {}

    def pretty_json(data):
        return json.dumps(data, indent=2, sort_keys=True)

    client = server.create_app().test_client()

    host = 'example.com:9984'

    # HTTP Index
    res = client.get('/', environ_overrides={'HTTP_HOST': host})
    res_data = json.loads(res.data.decode())
    ctx['index'] = pretty_json(res_data)

    # API index
    res = client.get('/api/v1/', environ_overrides={'HTTP_HOST': host})
    ctx['api_index'] = pretty_json(json.loads(res.data.decode()))

    # tx create
    privkey = 'CfdqtD7sS7FgkMoGPXw55MVGGFwQLAoHYTcBhZDtF99Z'
    pubkey = '4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD'
    asset = {'msg': 'Hello BigchainDB!'}
    tx = Transaction.create([pubkey], [([pubkey], 1)],
                            asset=asset,
                            metadata={'sequence': 0})
    tx = tx.sign([privkey])
    ctx['tx'] = pretty_json(tx.to_dict())
    ctx['public_keys'] = tx.outputs[0].public_keys[0]
    ctx['txid'] = tx.id

    # tx transfer
    privkey_transfer = '3AeWpPdhEZzWLYfkfYHBfMFC2r1f8HEaGS9NtbbKssya'
    pubkey_transfer = '3yfQPHeWAa1MxTX9Zf9176QqcpcnWcanVZZbaHb8B3h9'

    cid = 0
    input_ = Input(fulfillment=tx.outputs[cid].fulfillment,
                   fulfills=TransactionLink(txid=tx.id, output=cid),
                   owners_before=tx.outputs[cid].public_keys)
    tx_transfer = Transaction.transfer([input_], [([pubkey_transfer], 1)],
                                       asset_id=tx.id,
                                       metadata={'sequence': 1})
    tx_transfer = tx_transfer.sign([privkey])
    ctx['tx_transfer'] = pretty_json(tx_transfer.to_dict())
    ctx['public_keys_transfer'] = tx_transfer.outputs[0].public_keys[0]
    ctx['tx_transfer_id'] = tx_transfer.id

    # privkey_transfer_last = 'sG3jWDtdTXUidBJK53ucSTrosktG616U3tQHBk81eQe'
    pubkey_transfer_last = '3Af3fhhjU6d9WecEM9Uw5hfom9kNEwE7YuDWdqAUssqm'

    cid = 0
    input_ = Input(fulfillment=tx_transfer.outputs[cid].fulfillment,
                   fulfills=TransactionLink(txid=tx_transfer.id, output=cid),
                   owners_before=tx_transfer.outputs[cid].public_keys)
    tx_transfer_last = Transaction.transfer([input_],
                                            [([pubkey_transfer_last], 1)],
                                            asset_id=tx.id,
                                            metadata={'sequence': 2})
    tx_transfer_last = tx_transfer_last.sign([privkey_transfer])
    ctx['tx_transfer_last'] = pretty_json(tx_transfer_last.to_dict())
    ctx['tx_transfer_last_id'] = tx_transfer_last.id
    ctx['public_keys_transfer_last'] = tx_transfer_last.outputs[0].public_keys[
        0]

    # block
    node_private = "5G2kE1zJAgTajkVSbPAQWo4c2izvtwqaNHYsaNpbbvxX"
    node_public = "DngBurxfeNVKZWCEcDnLj1eMPAS7focUZTE5FndFGuHT"
    signature = "53wxrEQDYk1dXzmvNSytbCfmNVnPqPkDQaTnAe8Jf43s6ssejPxezkCvUnGTnduNUmaLjhaan1iRLi3peu6s5DzA"

    app_hash = 'f6e0c49c6d94d6924351f25bb334cf2a99af4206339bf784e741d1a5ab599056'
    block = lib.Block(height=1, transactions=[tx.to_dict()], app_hash=app_hash)
    block_dict = block._asdict()
    block_dict.pop('app_hash')
    ctx['block'] = pretty_json(block_dict)
    ctx['blockid'] = block.height

    # block status
    block_list = [block.height]
    ctx['block_list'] = pretty_json(block_list)

    base_path = os.path.join(os.path.dirname(__file__), 'source/http-samples')
    if not os.path.exists(base_path):
        os.makedirs(base_path)

    for name, tpl in TPLS.items():
        path = os.path.join(base_path, name + '.http')
        code = tpl % ctx
        with open(path, 'w') as handle:
            handle.write(code)
Ejemplo n.º 31
0
def prepare_transfer_transaction(*, inputs, recipients, asset, metadata=None):
    """Prepares a ``"TRANSFER"`` transaction payload, ready to be
    fulfilled.

    Args:
        inputs (:obj:`dict` | :obj:`list` | :obj:`tuple`): One or more
            inputs holding the condition(s) that this transaction
            intends to fulfill. Each input is expected to be a
            :obj:`dict`.
        recipients (:obj:`str` | :obj:`list` | :obj:`tuple`): One or
            more public keys representing the new recipients(s) of the
            asset being transferred.
        asset (:obj:`dict`): A single-key dictionary holding the ``id``
            of the asset being transferred with this transaction.
        metadata (:obj:`dict`): Metadata associated with the
            transaction. Defaults to ``None``.

    Returns:
        dict: The prepared ``"TRANSFER"`` transaction.

    .. important::

        * ``asset`` MUST be in the form of::

            {
                'id': '<Asset ID (i.e. TX ID of its CREATE transaction)>'
            }

    Example:

        .. todo:: Replace this section with docs.

        In case it may not be clear what an input should look like, say
        Alice (public key: ``'3Cxh1eKZk3Wp9KGBWFS7iVde465UvqUKnEqTg2MW4wNf'``)
        wishes to transfer an asset over to Bob
        (public key: ``'EcRawy3Y22eAUSS94vLF8BVJi62wbqbD9iSUSUNU9wAA'``).
        Let the asset creation transaction payload be denoted by
        ``tx``::

            # noqa E501
            >>> tx
                {'asset': {'data': {'msg': 'Hello BigchainDB!'}},
                 'id': '9650055df2539223586d33d273cb8fd05bd6d485b1fef1caf7c8901a49464c87',
                 'inputs': [{'fulfillment': {'public_key': '3Cxh1eKZk3Wp9KGBWFS7iVde465UvqUKnEqTg2MW4wNf',
                                             'type': 'ed25519-sha-256'},
                             'fulfills': None,
                             'owners_before': ['3Cxh1eKZk3Wp9KGBWFS7iVde465UvqUKnEqTg2MW4wNf']}],
                 'metadata': None,
                 'operation': 'CREATE',
                 'outputs': [{'amount': '1',
                              'condition': {'details': {'public_key': '3Cxh1eKZk3Wp9KGBWFS7iVde465UvqUKnEqTg2MW4wNf',
                                                        'type': 'ed25519-sha-256'},
                                            'uri': 'ni:///sha-256;7ApQLsLLQgj5WOUipJg1txojmge68pctwFxvc3iOl54?fpt=ed25519-sha-256&cost=131072'},
                              'public_keys': ['3Cxh1eKZk3Wp9KGBWFS7iVde465UvqUKnEqTg2MW4wNf']}],
                 'version': '2.0'}

        Then, the input may be constructed in this way::

            output_index
            output = tx['transaction']['outputs'][output_index]
            input_ = {
                'fulfillment': output['condition']['details'],
                'input': {
                    'output_index': output_index,
                    'transaction_id': tx['id'],
                },
                'owners_before': output['owners_after'],
            }

        Displaying the input on the prompt would look like::

            >>> input_
            {'fulfillment': {
              'public_key': '3Cxh1eKZk3Wp9KGBWFS7iVde465UvqUKnEqTg2MW4wNf',
              'type': 'ed25519-sha-256'},
             'input': {'output_index': 0,
              'transaction_id': '9650055df2539223586d33d273cb8fd05bd6d485b1fef1caf7c8901a49464c87'},
             'owners_before': ['3Cxh1eKZk3Wp9KGBWFS7iVde465UvqUKnEqTg2MW4wNf']}


        To prepare the transfer:

        >>> prepare_transfer_transaction(
        ...     inputs=input_,
        ...     recipients='EcRawy3Y22eAUSS94vLF8BVJi62wbqbD9iSUSUNU9wAA',
        ...     asset=tx['transaction']['asset'],
        ... )

    """
    if not isinstance(inputs, (list, tuple)):
        inputs = (inputs, )
    if not isinstance(recipients, (list, tuple)):
        recipients = [([recipients], 1)]

    # NOTE: Needed for the time being. See
    # https://github.com/bigchaindb/bigchaindb/issues/797
    if isinstance(recipients, tuple):
        recipients = [(list(recipients), 1)]

    fulfillments = [
        Input(_fulfillment_from_details(input_['fulfillment']),
              input_['owners_before'],
              fulfills=TransactionLink(
                  txid=input_['fulfills']['transaction_id'],
                  output=input_['fulfills']['output_index']))
        for input_ in inputs
    ]

    transaction = Transaction.transfer(
        fulfillments,
        recipients,
        asset_id=asset['id'],
        metadata=metadata,
    )
    return transaction.to_dict()
def main():
    """ Main function """

    ctx = {}

    def pretty_json(data):
        return json.dumps(data, indent=2, sort_keys=True)

    client = server.create_app().test_client()

    host = 'example.com:9984'

    # HTTP Index
    res = client.get('/', environ_overrides={'HTTP_HOST': host})
    res_data = json.loads(res.data.decode())
    res_data['keyring'] = [
        "6qHyZew94NMmUTYyHnkZsB8cxJYuRNEiEpXHe1ih9QX3",
        "AdDuyrTyjrDt935YnFu4VBCVDhHtY2Y6rcy7x2TFeiRi"
    ]
    res_data['public_key'] = 'NC8c8rYcAhyKVpx1PCV65CBmyq4YUbLysy3Rqrg8L8mz'
    ctx['index'] = pretty_json(res_data)

    # API index
    res = client.get('/api/v1/', environ_overrides={'HTTP_HOST': host})
    ctx['api_index'] = pretty_json(json.loads(res.data.decode()))

    # tx create
    privkey = 'CfdqtD7sS7FgkMoGPXw55MVGGFwQLAoHYTcBhZDtF99Z'
    pubkey = '4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD'
    asset = {'msg': 'Hello BigchainDB!'}
    tx = Transaction.create([pubkey], [([pubkey], 1)],
                            asset=asset,
                            metadata={'sequence': 0})
    tx = tx.sign([privkey])
    ctx['tx'] = pretty_json(tx.to_dict())
    ctx['public_keys'] = tx.outputs[0].public_keys[0]
    ctx['txid'] = tx.id

    # tx transfer
    privkey_transfer = '3AeWpPdhEZzWLYfkfYHBfMFC2r1f8HEaGS9NtbbKssya'
    pubkey_transfer = '3yfQPHeWAa1MxTX9Zf9176QqcpcnWcanVZZbaHb8B3h9'

    cid = 0
    input_ = Input(fulfillment=tx.outputs[cid].fulfillment,
                   fulfills=TransactionLink(txid=tx.id, output=cid),
                   owners_before=tx.outputs[cid].public_keys)
    tx_transfer = Transaction.transfer([input_], [([pubkey_transfer], 1)],
                                       asset_id=tx.id,
                                       metadata={'sequence': 1})
    tx_transfer = tx_transfer.sign([privkey])
    ctx['tx_transfer'] = pretty_json(tx_transfer.to_dict())
    ctx['public_keys_transfer'] = tx_transfer.outputs[0].public_keys[0]
    ctx['tx_transfer_id'] = tx_transfer.id

    # privkey_transfer_last = 'sG3jWDtdTXUidBJK53ucSTrosktG616U3tQHBk81eQe'
    pubkey_transfer_last = '3Af3fhhjU6d9WecEM9Uw5hfom9kNEwE7YuDWdqAUssqm'

    cid = 0
    input_ = Input(fulfillment=tx_transfer.outputs[cid].fulfillment,
                   fulfills=TransactionLink(txid=tx_transfer.id, output=cid),
                   owners_before=tx_transfer.outputs[cid].public_keys)
    tx_transfer_last = Transaction.transfer([input_],
                                            [([pubkey_transfer_last], 1)],
                                            asset_id=tx.id,
                                            metadata={'sequence': 2})
    tx_transfer_last = tx_transfer_last.sign([privkey_transfer])
    ctx['tx_transfer_last'] = pretty_json(tx_transfer_last.to_dict())
    ctx['tx_transfer_last_id'] = tx_transfer_last.id
    ctx['public_keys_transfer_last'] = tx_transfer_last.outputs[0].public_keys[
        0]

    # block
    node_private = "5G2kE1zJAgTajkVSbPAQWo4c2izvtwqaNHYsaNpbbvxX"
    node_public = "DngBurxfeNVKZWCEcDnLj1eMPAS7focUZTE5FndFGuHT"
    signature = "53wxrEQDYk1dXzmvNSytbCfmNVnPqPkDQaTnAe8Jf43s6ssejPxezkCvUnGTnduNUmaLjhaan1iRLi3peu6s5DzA"
    block = Block(transactions=[tx],
                  node_pubkey=node_public,
                  voters=[node_public],
                  signature=signature)
    ctx['block'] = pretty_json(block.to_dict())
    ctx['blockid'] = block.id

    block_transfer = Block(transactions=[tx_transfer],
                           node_pubkey=node_public,
                           voters=[node_public],
                           signature=signature)
    ctx['block_transfer'] = pretty_json(block.to_dict())

    # vote
    DUMMY_SHA3 = '0123456789abcdef' * 4
    b = Bigchain(public_key=node_public, private_key=node_private)
    vote = b.vote(block.id, DUMMY_SHA3, True)
    ctx['vote'] = pretty_json(vote)

    # block status
    block_list = [block_transfer.id, block.id]
    ctx['block_list'] = pretty_json(block_list)

    base_path = os.path.join(os.path.dirname(__file__), 'source/http-samples')
    if not os.path.exists(base_path):
        os.makedirs(base_path)

    for name, tpl in TPLS.items():
        path = os.path.join(base_path, name + '.http')
        code = tpl % ctx
        with open(path, 'w') as handle:
            handle.write(code)