예제 #1
0
파일: utils.py 프로젝트: roderik/bigchaindb
def validate_transaction_model(tx):
    from bigchaindb.common.transaction import Transaction
    from bigchaindb.common.schema import validate_transaction_schema

    tx_dict = tx.to_dict()
    # Check that a transaction is valid by re-serializing it
    # And calling validate_transaction_schema
    validate_transaction_schema(tx_dict)
    Transaction.from_dict(tx_dict)
예제 #2
0
def test_create_create_transaction_threshold(user_pub, user2_pub, user3_pub,
                                             user_user2_threshold_output,
                                             user_user2_threshold_input, data):
    from bigchaindb.common.transaction import Transaction

    expected = {
        'outputs': [user_user2_threshold_output.to_dict()],
        'metadata':
        data,
        'asset': {
            'data': data,
        },
        'inputs': [
            {
                'owners_before': [
                    user_pub,
                ],
                'fulfillment': None,
                'fulfills': None,
            },
        ],
        'operation':
        'CREATE',
        'version':
        Transaction.VERSION
    }
    tx = Transaction.create([user_pub], [([user_pub, user2_pub], 1)],
                            metadata=data,
                            asset=data)
    tx_dict = tx.to_dict()
    tx_dict.pop('id')
    tx_dict['inputs'][0]['fulfillment'] = None

    assert tx_dict == expected
예제 #3
0
def test_create_create_transaction_multiple_io(user_output, user2_output,
                                               user_pub, user2_pub,
                                               asset_definition):
    from bigchaindb.common.transaction import Transaction, Input

    # a fulfillment for a create transaction with multiple `owners_before`
    # is a fulfillment for an implicit threshold condition with
    # weight = len(owners_before)
    input = Input.generate([user_pub, user2_pub]).to_dict()
    expected = {
        'outputs': [user_output.to_dict(),
                    user2_output.to_dict()],
        'metadata': {
            'message': 'hello'
        },
        'inputs': [input],
        'operation': 'CREATE',
        'version': Transaction.VERSION
    }
    tx = Transaction.create([user_pub, user2_pub], [([user_pub], 1),
                                                    ([user2_pub], 1)],
                            metadata={
                                'message': 'hello'
                            }).to_dict()
    tx.pop('id')
    tx.pop('asset')

    assert tx == expected
예제 #4
0
def test_validate_single_io_create_transaction(user_pub, user_priv, data,
                                               asset_definition):
    from bigchaindb.common.transaction import Transaction

    tx = Transaction.create([user_pub], [([user_pub], 1)], metadata=data)
    tx = tx.sign([user_priv])
    assert tx.inputs_valid() is True
예제 #5
0
def test_create_create_transaction_single_io(user_output, user_pub, data):
    from bigchaindb.common.transaction import Transaction
    from .utils import validate_transaction_model

    expected = {
        'outputs': [user_output.to_dict()],
        'metadata':
        data,
        'asset': {
            'data': data,
        },
        'inputs': [{
            'owners_before': [user_pub],
            'fulfillment': None,
            'fulfills': None
        }],
        'operation':
        'CREATE',
        'version':
        Transaction.VERSION,
    }

    tx = Transaction.create([user_pub], [([user_pub], 1)],
                            metadata=data,
                            asset=data)
    tx_dict = tx.to_dict()
    tx_dict['inputs'][0]['fulfillment'] = None
    tx_dict.pop('id')

    assert tx_dict == expected

    validate_transaction_model(tx)
예제 #6
0
def test_unspent_outputs_property(merlin, alice, bob, carol):
    from bigchaindb.common.transaction import Transaction
    tx = Transaction.create(
        [merlin.public_key],
        [([alice.public_key], 1), ([bob.public_key], 2),
         ([carol.public_key], 3)],
        asset={
            'hash': '06e47bcf9084f7ecfd2a2a2ad275444a'
        },
    ).sign([merlin.private_key])
    unspent_outputs = list(tx.unspent_outputs)
    assert len(unspent_outputs) == 3
    assert all(utxo.transaction_id == tx.id for utxo in unspent_outputs)
    assert all(utxo.asset_id == tx.id for utxo in unspent_outputs)
    assert all(utxo.output_index == i
               for i, utxo in enumerate(unspent_outputs))
    unspent_output_0 = unspent_outputs[0]
    assert unspent_output_0.amount == 1
    assert unspent_output_0.condition_uri == Ed25519Sha256(
        public_key=b58decode(alice.public_key)).condition_uri
    unspent_output_1 = unspent_outputs[1]
    assert unspent_output_1.amount == 2
    assert unspent_output_1.condition_uri == Ed25519Sha256(
        public_key=b58decode(bob.public_key)).condition_uri
    unspent_output_2 = unspent_outputs[2]
    assert unspent_output_2.amount == 3
    assert unspent_output_2.condition_uri == Ed25519Sha256(
        public_key=b58decode(carol.public_key)).condition_uri
예제 #7
0
def alice_transaction_obj(alice_pubkey):
    serial_number = b64encode(urandom(10), altchars=b'-_').decode()
    return Transaction.create(
        tx_signers=[alice_pubkey],
        recipients=[([alice_pubkey], 1)],
        asset={'serial_number': serial_number},
    )
예제 #8
0
def get():
    # Cryptographic Identities Generation
    alice, bob = generate_keypair(), generate_keypair()
    print(" ")
    # Digital Asset Definition (e.g. bicycle)
    asset = Asset(data={
        "bicycle": {
            "manufacturer": "bkfab",
            "serial_number": "abcd1234"
        }
    })

    # Metadata Definition
    metadata = {'planet': 'earth'}

    # create trnsaction  TODO : owners_before might be node_pubkey in v0.8.0
    tx = Transaction.create([alice.public_key], [alice.public_key],
                            metadata=metadata,
                            asset=asset)

    # sign with private key
    tx = tx.sign([alice.private_key])
    # get tx by id
    b = Bigchain()

    block = b.create_block([tx])
    block_voters = block.to_dict()['block']['voters']
    print(block_voters)
    tx_id = '2cb004cad29c0b79872646558f8c867a4c0aecbc4997f0917'
    tx = b.get_transaction(tx_id)
    print(
        "block status         : ",
        b.block_election_status(
            '2257384a0cee8cf98bd82c3142dd38eee5c268c124b5b357b773b8c6c1fa1221',
            block_voters))
예제 #9
0
 def transactions():
     priv, pub = generate_key_pair()
     tx = Transaction.create([pub], [([pub], 1)])
     while True:
         i = yield tx.to_dict()
         tx.asset = {'data': {'n': i}}
         tx.sign([priv])
예제 #10
0
    def from_dict(cls, block_body):
        """Transform a Python dictionary to a Block object.

        Args:
            block_body (dict): A block dictionary to be transformed.

        Returns:
            :class:`~Block`

        Raises:
            InvalidHash: If the block's id is not corresponding to its
                data.
        """
        # Validate block id
        block = block_body['block']
        block_serialized = serialize(block)
        block_id = hash_data(block_serialized)

        if block_id != block_body['id']:
            raise InvalidHash()

        transactions = [Transaction.from_dict(tx) for tx
                        in block['transactions']]

        signature = block_body.get('signature')

        return cls(transactions, block['node_pubkey'],
                   block['timestamp'], block['voters'], signature)
예제 #11
0
def test_sign_tx():
    tx = create_tx()
    signed = api.signTx({
        'tx': tx,
        'keys': [sec],
    })
    assert signed == Transaction.from_dict(tx).sign([sec]).to_dict()
예제 #12
0
def input_single_create(b):
    from bigchaindb.common.transaction import Transaction
    metadata = {'r': random.random()}
    tx = Transaction.create([b.me], [([b.me], 1)],
                            metadata).sign([b.me_private])
    b.write_transaction(tx)
    return tx
예제 #13
0
def fulfill_transaction(transaction, *, private_keys):
    """
    Fulfills the given transaction.

    Args:
        transaction (dict): The transaction to be fulfilled.
        private_keys (:obj:`str` | :obj:`list` | :obj:`tuple`): One or
            more private keys to be used for fulfilling the
            transaction.

    Returns:
        dict: The fulfilled transaction payload, ready to be sent to a
        BigchainDB federation.

    Raises:
        :exc:`~.exceptions.MissingPrivateKeyError`: If a private
            key is missing.

    """
    if not isinstance(private_keys, (list, tuple)):
        private_keys = [private_keys]

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

    transaction_obj = Transaction.from_dict(transaction)
    try:
        signed_transaction = transaction_obj.sign(private_keys)
    except KeypairMismatchException as exc:
        raise MissingPrivateKeyError('A private key is missing!') from exc

    return signed_transaction.to_dict()
예제 #14
0
def prepare_create_transaction(*,
                               owners_before,
                               owners_after=None,
                               asset=None,
                               metadata=None):
    """
    Prepares a ``"CREATE"`` transaction payload, ready to be
    fulfilled.

    Args:
        owners_before (:obj:`list` | :obj:`tuple` | :obj:`str`): One
            or more public keys representing the issuer(s) of the asset
            being created.
        owners_after (:obj:`list` | :obj:`tuple` | :obj:`str`, optional):
            One or more public keys representing the new owner(s) of the
            asset being created. Defaults to ``None``.
        asset (:obj:`dict`, optional): The asset being created. Defaults
            to ``None``.
        metadata (:obj:`dict`, optional): Metadata associated with the
            transaction. Defaults to ``None``.

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

    .. important:: If ``owners_after`` is not given, or evaluates to
        ``False``, it will be set equal to ``owners_before``::

            if not owners_after:
                owners_after = owners_before

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

    # TODO: This will only work for non-divisible. If its a divisible asset
    # Transaction.create will raise an exception saying that divisible assets
    # need to have amount > 1.
    if not owners_after:
        owners_after = [(owners_before, 1)]
    elif not isinstance(owners_after, (list, tuple)):
            owners_after = [([owners_after], 1)]
    # NOTE: Needed for the time being. See
    # https://github.com/bigchaindb/bigchaindb/issues/797
    elif isinstance(owners_after, tuple):
        owners_after = [(list(owners_after), 1)]

    asset = _normalize_asset(asset)

    transaction = Transaction.create(
        owners_before,
        owners_after,
        metadata=metadata,
        asset=asset,
    )
    return transaction.to_dict()
예제 #15
0
def test_create_default_asset_on_tx_initialization(asset_definition):
    from bigchaindb.common.transaction import Transaction

    expected = {'data': None}
    tx = Transaction(Transaction.CREATE, asset=expected)
    asset = tx.asset

    assert asset == expected
예제 #16
0
def test_validate_input_with_invalid_parameters(utx):
    from bigchaindb.common.transaction import Transaction

    input_conditions = [out.fulfillment.condition_uri for out in utx.outputs]
    tx_dict = utx.to_dict()
    tx_serialized = Transaction._to_str(tx_dict)
    valid = utx._input_valid(utx.inputs[0], tx_serialized, input_conditions[0])
    assert not valid
def test_validate_tx_simple_create_signature(user_input, user_output,
                                             user_priv, asset_definition):
    from bigchaindb.common.transaction import Transaction
    from .utils import validate_transaction_model

    tx = Transaction(Transaction.CREATE, asset_definition, [user_input],
                     [user_output])
    expected = deepcopy(user_output)
    message = str(tx).encode()
    expected.fulfillment.sign(message, b58decode(user_priv))
    tx.sign([user_priv])

    assert tx.inputs[0].to_dict()['fulfillment'] == \
        expected.fulfillment.serialize_uri()
    assert tx.inputs_valid() is True

    validate_transaction_model(tx)
예제 #18
0
def test_fulfilled_transaction_serialized(fulfilled_transaction):
    from bigchaindb.common.transaction import Transaction
    tx_obj = Transaction.from_dict(fulfilled_transaction)
    expected = json.dumps(fulfilled_transaction,
                          sort_keys=True,
                          separators=(',', ':'),
                          ensure_ascii=True)
    assert tx_obj.serialized == expected
예제 #19
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])
예제 #20
0
def merge_utxo(alicepub, alicepriv, include_spent):
    asset = Asset(data={
        "bicycle": {
            "manufacturer": "bkfab",
            "serial_number": "abcd1234"
        }
    },
                  data_id="334cd061-846b-4213-bd25-588e951def5f")
    metadata = {'planet': 'earth'}
    b = Bigchain()
    utxo = b.get_outputs_filtered_not_include_freeze(alicepub, include_spent)
    for u in utxo:
        # print(u)
        u.pop('details')
    print('userA unspent asset:')
    print(json.dumps(utxo, indent=4))
    inputs = []
    balance = 0
    utxo = b.get_outputs_filtered_not_include_freeze(alicepub, include_spent)
    for i in utxo:
        f = Fulfillment.from_dict({
            'fulfillment': i['details'],
            'input': {
                'cid': i['cid'],
                'txid': i['txid'],
            },
            'owners_before': [alicepub],
        })
        inputs.append(f)
        balance += i['amount']

    length = len(utxo)
    if balance <= 0:
        print('No need to merge, because of lack of balance')
    elif length <= 1:
        print('No need to merge, because utxo len = 1')
    else:
        tx = Transaction.transfer(inputs, [([alicepub], balance)],
                                  metadata=metadata,
                                  asset=asset)
        tx = tx.sign([alicepriv])
        tx_id = tx.to_dict()['id']
        # write to backlog
        b.write_transaction(tx)
        # wait 2 sec
        print("========userA merge multi-asset========")
        print("========wait for block and vote...========")
        sleep(5)
        # get tx by id
        tx = b.get_transaction(tx_id)
        print("merge txid:" + tx.to_dict()['id'])

    utxo = b.get_outputs_filtered_not_include_freeze(alicepub, include_spent)
    for u in utxo:
        # print(u)
        u.pop('details')
    print('userA unspent asset:')
    print(json.dumps(utxo, indent=4))
예제 #21
0
def bft():
    # Cryptographic Identities Generation
    alice, bob = generate_keypair(), generate_keypair()
    print(" ")
    # Digital Asset Definition (e.g. bicycle)
    asset = Asset(data={
        "bicycle": {
            "manufacturer": "bkfab",
            "serial_number": "abcd1234"
        }
    })

    # Metadata Definition
    metadata = {'planet': 'earth'}

    # create trnsaction  TODO : owners_before might be node_pubkey in v0.8.0
    tx = Transaction.create([alice.public_key], [([alice.public_key], 1)],
                            metadata=metadata,
                            asset=asset)

    # sign with private key
    tx = tx.sign([alice.private_key])
    tx_id = tx.to_dict()['id']
    print("tx_id                       : ", tx_id)

    # create block
    b = Bigchain()
    block = b.create_block([tx])

    print("valid block       timestamp : ",
          block.to_dict()['block']['timestamp'])
    # tamper block
    block.timestamp = '1'
    print("tamper block.timestamp to 1 : ")
    block_id = block.to_dict()['id']
    block_voters = block.to_dict()['block']['voters']

    print("invalid block     timestamp : ",
          block.to_dict()['block']['timestamp'])
    print("tamper_block_id             : ", block_id)

    print("db response of block        : ", b.write_block(block))
    sleep(0)

    last_voted_id = b.get_last_voted_block().id
    vote = b.vote(block_id, last_voted_id, True)
    print("crate vote 'True'           : ", vote)
    print("db response of vote         : ", b.write_vote(vote))

    print("tamper_block status         : ",
          b.block_election_status(block_id, block_voters))
    print("blocks_status_containing_tx : ",
          b.get_blocks_status_containing_tx(tx_id))
    print("wait for 20 sec             : ")
    sleep(20)
    print("blocks_status_containing_tx : ",
          b.get_blocks_status_containing_tx(tx_id))
    print(" ")
def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub,
                                               user2_output, user_priv):
    from bigchaindb.common.transaction import Transaction
    from bigchaindb.common.utils import serialize
    from .utils import validate_transaction_model

    expected = {
        'outputs': [user2_output.to_dict()],
        'metadata':
        None,
        'asset': {
            'id': tx.id,
        },
        'inputs': [{
            'owners_before': [user_pub],
            'fulfillment': None,
            'fulfills': {
                'transaction_id': tx.id,
                'output_index': 0
            }
        }],
        'operation':
        'TRANSFER',
        'version':
        Transaction.VERSION
    }
    inputs = tx.to_inputs([0])
    transfer_tx = Transaction.transfer(inputs, [([user2_pub], 1)],
                                       asset_id=tx.id)
    transfer_tx = transfer_tx.sign([user_priv])
    transfer_tx = transfer_tx.to_dict()

    expected_input = deepcopy(inputs[0])
    expected['id'] = transfer_tx['id']
    expected_input.fulfillment.sign(
        serialize(expected).encode(), b58decode(user_priv))
    expected_ffill = expected_input.fulfillment.serialize_uri()
    transfer_ffill = transfer_tx['inputs'][0]['fulfillment']

    assert transfer_ffill == expected_ffill

    transfer_tx = Transaction.from_dict(transfer_tx)
    assert transfer_tx.inputs_valid([tx.outputs[0]]) is True

    validate_transaction_model(transfer_tx)
예제 #23
0
 def transactions():
     priv, pub = generate_key_pair()
     tx = Transaction.create([pub], [([pub], 1)])
     while True:
         i = yield tx.to_dict()
         tx.asset = Asset(data={'n': i},
                          data_id='20170628150000',
                          divisible=True)
         tx.sign([priv])
예제 #24
0
def alice_transaction_obj(alice_pubkey):
    serial_number = b64encode(urandom(10), altchars=b'-_').decode()
    return Transaction.create(
        owners_before=[alice_pubkey],
        owners_after=[alice_pubkey],
        asset=Asset(data={'data': {
            'serial_number': serial_number
        }}),
    )
예제 #25
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, Transaction,
                                               TransactionLink)
    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 None,
                   amount=output['amount'] if "amount" in output else 1))

    return Transaction(
        operation='TRANSFER',
        asset=asset,
        inputs=_inputs,
        outputs=_outputs,
        metadata=metadata,
    )
예제 #26
0
def test_transaction_hash(fulfilled_transaction):
    from bigchaindb.common.transaction import Transaction
    tx_obj = Transaction.from_dict(fulfilled_transaction)
    assert tx_obj._id is None
    assert tx_obj.id is None
    thing_to_hash = json.dumps(fulfilled_transaction, sort_keys=True,
                               separators=(',', ':'), ensure_ascii=True)
    expected_hash_id = sha3_256(thing_to_hash.encode()).hexdigest()
    tx_obj._hash()
    assert tx_obj._id == expected_hash_id
    assert tx_obj.id == expected_hash_id
예제 #27
0
def test_validate_threshold_create_transaction(user_pub, user_priv, user2_pub,
                                               data, asset_definition):
    from bigchaindb.common.transaction import Transaction
    from .utils import validate_transaction_model

    tx = Transaction.create([user_pub], [([user_pub, user2_pub], 1)],
                            metadata=data)
    tx = tx.sign([user_priv])
    assert tx.inputs_valid() is True

    validate_transaction_model(tx)
예제 #28
0
def spend(transaction, output_id):
    """
    Convert a transaction's outputs to inputs.

    Convert outputs in TRANSACTION (json) to signable/spendable
    inputs. Outputs can individually be selected by passing one or
    more CONDITION_ID, as a JSON list. Otherwise, all outputs are converted.
    """
    transaction = Transaction.from_dict(transaction)
    inputs = transaction.to_inputs(output_id)
    click.echo(json.dumps([i.to_dict() for i in inputs]))
예제 #29
0
def test_invalid_transaction_initialization(asset_definition):
    from bigchaindb.common.transaction import Transaction

    with raises(ValueError):
        Transaction(operation='invalid operation', asset=asset_definition)
    with raises(TypeError):
        Transaction(operation='CREATE', asset='invalid asset')
    with raises(TypeError):
        Transaction(operation='TRANSFER', asset={})
    with raises(TypeError):
        Transaction(
            operation='CREATE',
            asset=asset_definition,
            outputs='invalid outputs'
        )
    with raises(TypeError):
        Transaction(
            operation='CREATE',
            asset=asset_definition,
            outputs=[],
            inputs='invalid inputs'
        )
    with raises(TypeError):
        Transaction(
            operation='CREATE',
            asset=asset_definition,
            outputs=[],
            inputs=[],
            metadata='invalid metadata'
        )
예제 #30
0
def test_validate_tx_threshold_create_signature(user_user2_threshold_input,
                                                user_user2_threshold_output,
                                                user_pub, user2_pub, user_priv,
                                                user2_priv, asset_definition):
    from bigchaindb.common.transaction import Transaction
    from .utils import validate_transaction_model

    tx = Transaction(Transaction.CREATE, asset_definition,
                     [user_user2_threshold_input],
                     [user_user2_threshold_output])
    tx_dict = tx.to_dict()
    tx_dict['inputs'][0]['fulfillment'] = None
    serialized_tx = json.dumps(tx_dict,
                               sort_keys=True,
                               separators=(',', ':'),
                               ensure_ascii=True)
    message = sha3_256(serialized_tx.encode()).digest()
    expected = deepcopy(user_user2_threshold_output)
    expected.fulfillment.subconditions[0]['body'].sign(message,
                                                       b58decode(user_priv))
    expected.fulfillment.subconditions[1]['body'].sign(message,
                                                       b58decode(user2_priv))
    tx.sign([user_priv, user2_priv])

    assert tx.inputs[0].to_dict()['fulfillment'] == \
        expected.fulfillment.serialize_uri()
    assert tx.inputs_valid() is True

    validate_transaction_model(tx)
예제 #31
0
def test_validate_multiple_io_create_transaction(user_pub, user_priv,
                                                 user2_pub, user2_priv,
                                                 asset_definition):
    from bigchaindb.common.transaction import Transaction
    from .utils import validate_transaction_model

    tx = Transaction.create([user_pub, user2_pub], [([user_pub], 1),
                                                    ([user2_pub], 1)],
                            metadata={'message': 'hello'})
    tx = tx.sign([user_priv, user2_priv])
    assert tx.inputs_valid() is True

    validate_transaction_model(tx)
예제 #32
0
def test_transaction_serialization(user_input, user_output, data):
    from bigchaindb.common.transaction import Transaction

    expected = {
        'id': None,
        'version': Transaction.VERSION,
        # NOTE: This test assumes that Inputs and Outputs can
        #       successfully be serialized
        'inputs': [user_input.to_dict()],
        'outputs': [user_output.to_dict()],
        'operation': Transaction.CREATE,
        'metadata': None,
        'asset': {
            'data': data,
        }
    }

    tx = Transaction(Transaction.CREATE, {'data': data}, [user_input],
                     [user_output])
    tx_dict = tx.to_dict()

    assert tx_dict == expected
예제 #33
0
    def from_dict(cls, block_body):
        """Transform a Python dictionary to a Block object.

        Args:
            block_body (dict): A block dictionary to be transformed.

        Returns:
            :class:`~Block`

        Raises:
            InvalidHash: If the block's id is not corresponding to its
                data.
            InvalidSignature: If the block's signature is not corresponding
                to it's data or `node_pubkey`.
        """
        # TODO: Reuse `is_signature_valid` method here.
        block = block_body['block']
        block_serialized = serialize(block)
        block_id = hash_data(block_serialized)
        public_key = PublicKey(block['node_pubkey'])

        try:
            signature = block_body['signature']
        except KeyError:
            signature = None

        if block_id != block_body['id']:
            raise InvalidHash()

        if signature is not None:
            # NOTE: CC throws a `ValueError` on some wrong signatures
            #       https://github.com/bigchaindb/cryptoconditions/issues/27
            try:
                signature_valid = public_key\
                        .verify(block_serialized.encode(), signature)
            except ValueError:
                signature_valid = False
            if signature_valid is False:
                raise InvalidSignature('Invalid block signature')

        transactions = [Transaction.from_dict(tx) for tx
                        in block['transactions']]

        return cls(transactions, block['node_pubkey'],
                   block['timestamp'], block['voters'], signature)
예제 #34
0
    'database': _database_map['localmongodb'],
    'log': {
        'file': log_config['handlers']['file']['filename'],
        'error_file': log_config['handlers']['errors']['filename'],
        'level_console': logging.getLevelName(
            log_config['handlers']['console']['level']).lower(),
        'level_logfile': logging.getLevelName(
            log_config['handlers']['file']['level']).lower(),
        'datefmt_console': log_config['formatters']['console']['datefmt'],
        'datefmt_logfile': log_config['formatters']['file']['datefmt'],
        'fmt_console': log_config['formatters']['console']['format'],
        'fmt_logfile': log_config['formatters']['file']['format'],
        'granular_levels': {},
    },
}

# We need to maintain a backup copy of the original config dict in case
# the user wants to reconfigure the node. Check ``bigchaindb.config_utils``
# for more info.
_config = copy.deepcopy(config)
from bigchaindb.common.transaction import Transaction  # noqa
from bigchaindb import models                          # noqa
from bigchaindb.upsert_validator import ValidatorElection  # noqa
from bigchaindb.elections.vote import Vote  # noqa

Transaction.register_type(Transaction.CREATE, models.Transaction)
Transaction.register_type(Transaction.TRANSFER, models.Transaction)
Transaction.register_type(ValidatorElection.OPERATION, ValidatorElection)
Transaction.register_type(ChainMigrationElection.OPERATION, ChainMigrationElection)
Transaction.register_type(Vote.OPERATION, Vote)
예제 #35
0
    def validate(self, bigchain):
        """Validate transaction spend

        Args:
            bigchain (Bigchain): an instantiated bigchaindb.Bigchain object.

        Returns:
            The transaction (Transaction) if the transaction is valid else it
            raises an exception describing the reason why the transaction is
            invalid.

        Raises:
            ValidationError: If the transaction is invalid
        """
        input_conditions = []

        if self.operation == Transaction.TRANSFER:
            # store the inputs so that we can check if the asset ids match
            input_txs = []
            for input_ in self.inputs:
                input_txid = input_.fulfills.txid
                input_tx, status = bigchain.\
                    get_transaction(input_txid, include_status=True)

                if input_tx is None:
                    raise InputDoesNotExist("input `{}` doesn't exist"
                                            .format(input_txid))

                if status != bigchain.TX_VALID:
                    raise TransactionNotInValidBlock(
                        'input `{}` does not exist in a valid block'.format(
                            input_txid))

                spent = bigchain.get_spent(input_txid, input_.fulfills.output)
                if spent and spent.id != self.id:
                    raise DoubleSpend('input `{}` was already spent'
                                      .format(input_txid))

                output = input_tx.outputs[input_.fulfills.output]
                input_conditions.append(output)
                input_txs.append(input_tx)

            # Validate that all inputs are distinct
            links = [i.fulfills.to_uri() for i in self.inputs]
            if len(links) != len(set(links)):
                raise DoubleSpend('tx "{}" spends inputs twice'.format(self.id))

            # validate asset id
            asset_id = Transaction.get_asset_id(input_txs)
            if asset_id != self.asset['id']:
                raise AssetIdMismatch(('The asset id of the input does not'
                                       ' match the asset id of the'
                                       ' transaction'))

            input_amount = sum([input_condition.amount for input_condition in input_conditions])
            output_amount = sum([output_condition.amount for output_condition in self.outputs])

            if output_amount != input_amount:
                raise AmountError(('The amount used in the inputs `{}`'
                                   ' needs to be same as the amount used'
                                   ' in the outputs `{}`')
                                  .format(input_amount, output_amount))

        if not self.inputs_valid(input_conditions):
            raise InvalidSignature('Transaction signature is invalid.')

        return self
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)