Example #1
0
    def test_block_deserialization(self, b):
        from bigchaindb.common.crypto import hash_data
        from bigchaindb.common.utils import gen_timestamp, serialize
        from bigchaindb.models import Block, Transaction

        transaction = Transaction.create([b.me], [([b.me], 1)])
        transaction.sign([b.me_private])
        timestamp = gen_timestamp()
        voters = ['Qaaa', 'Qbbb']
        expected = Block([transaction], b.me, timestamp, voters)

        block = {
            'timestamp': timestamp,
            'transactions': [transaction.to_dict()],
            'node_pubkey': b.me,
            'voters': voters,
        }

        block_body = {
            'id': hash_data(serialize(block)),
            'block': block,
            'signature': None,
        }

        assert expected == Block.from_dict(block_body)
def test_get_votes_by_block_id(signed_create_tx, structurally_valid_vote):
    from bigchaindb.common.crypto import generate_key_pair
    from bigchaindb.backend import connect, query
    from bigchaindb.models import Block
    conn = connect()

    # create and insert a block
    block = Block(transactions=[signed_create_tx])
    conn.db.bigchain.insert_one(block.to_dict())

    # create and insert some votes
    structurally_valid_vote['vote']['voting_for_block'] = block.id
    conn.db.votes.insert_one(structurally_valid_vote)
    # create a second vote under a different key
    _, pk = generate_key_pair()
    structurally_valid_vote['vote']['voting_for_block'] = block.id
    structurally_valid_vote['node_pubkey'] = pk
    structurally_valid_vote.pop('_id')
    conn.db.votes.insert_one(structurally_valid_vote)

    votes = list(query.get_votes_by_block_id(conn, block.id))

    assert len(votes) == 2
    assert votes[0]['vote']['voting_for_block'] == block.id
    assert votes[1]['vote']['voting_for_block'] == block.id
Example #3
0
    def test_sign_block(self, b, alice):
        from bigchaindb.common.crypto import PrivateKey, PublicKey
        from bigchaindb.common.utils import gen_timestamp, serialize
        from bigchaindb.models import Block, Transaction

        transactions = [
            Transaction.create([alice.public_key], [([alice.public_key], 1)])
        ]
        timestamp = gen_timestamp()
        voters = ['Qaaa', 'Qbbb']
        expected_block = {
            'timestamp': timestamp,
            'transactions': [tx.to_dict() for tx in transactions],
            'node_pubkey': alice.public_key,
            'voters': voters,
        }
        expected_block_serialized = serialize(expected_block).encode()
        expected = PrivateKey(
            alice.private_key).sign(expected_block_serialized)
        block = Block(transactions, alice.public_key, timestamp, voters)
        block = block.sign(alice.private_key)
        assert block.signature == expected.decode()

        public_key = PublicKey(alice.public_key)
        assert public_key.verify(expected_block_serialized, block.signature)
Example #4
0
    def test_from_db(self, b):
        from bigchaindb.models import Block, Transaction

        assets = [
            {'msg': '1'},
            {'msg': '2'},
            {'msg': '3'},
        ]

        txs = []
        # create 3 assets
        for asset in assets:
            tx = Transaction.create([b.me], [([b.me], 1)], asset=asset)
            txs.append(tx)

        # create a `TRANSFER` transaction.
        # the asset in `TRANSFER` transactions is not extracted
        tx = Transaction.transfer(txs[0].to_inputs(), [([b.me], 1)],
                                  asset_id=txs[0].id)
        txs.append(tx)

        # create the block
        block = Block(txs)
        # decouple assets
        assets_from_block, block_dict = block.decouple_assets()

        # write the assets and block separately
        b.write_assets(assets_from_block)
        b.write_block(block)

        # check the reconstructed block is the same as the original block
        block_from_db = Block.from_db(b, block_dict)
        assert block == block_from_db
def test_get_last_voted_block_id(genesis_block, signed_create_tx, b):
    from bigchaindb.backend import connect, query
    from bigchaindb.models import Block
    from bigchaindb.common.exceptions import CyclicBlockchainError
    conn = connect()

    # check that the last voted block is the genesis block
    assert query.get_last_voted_block_id(conn, b.me) == genesis_block.id

    # create and insert a new vote and block
    block = Block(transactions=[signed_create_tx])
    conn.db.bigchain.insert_one(block.to_dict())
    vote = b.vote(block.id, genesis_block.id, True)
    conn.db.votes.insert_one(vote)

    assert query.get_last_voted_block_id(conn, b.me) == block.id

    # force a bad chain
    vote.pop('_id')
    vote['vote']['voting_for_block'] = genesis_block.id
    vote['vote']['previous_block'] = block.id
    conn.db.votes.insert_one(vote)

    with pytest.raises(CyclicBlockchainError):
        query.get_last_voted_block_id(conn, b.me)
Example #6
0
def test_filter_unspent_outputs(b, user_pk, user_sk):
    out = [([user_pk], 1)]
    tx1 = Transaction.create([user_pk], out * 3)
    tx1.sign([user_sk])

    # There are 3 inputs
    inputs = tx1.to_inputs()

    # Each spent individually
    tx2 = Transaction.transfer([inputs[0]], out, tx1.id)
    tx2.sign([user_sk])
    tx3 = Transaction.transfer([inputs[1]], out, tx1.id)
    tx3.sign([user_sk])
    tx4 = Transaction.transfer([inputs[2]], out, tx1.id)
    tx4.sign([user_sk])

    # The CREATE and first TRANSFER are valid. tx2 produces a new unspent.
    for tx in [tx1, tx2]:
        block = Block([tx])
        b.write_block(block)
        b.write_vote(b.vote(block.id, '', True))

    # The second TRANSFER is invalid. inputs[1] remains unspent.
    block = Block([tx3])
    b.write_block(block)
    b.write_vote(b.vote(block.id, '', False))

    # The third TRANSFER is undecided. It procuces a new unspent.
    block = Block([tx4])
    b.write_block(block)

    outputs = b.fastquery.get_outputs_by_public_key(user_pk)
    spents = b.fastquery.filter_unspent_outputs(outputs)

    assert set(spents) == {inputs[0].fulfills, inputs[2].fulfills}
Example #7
0
    def get_block(self, block_id, include_status=False):
        """Get the block with the specified `block_id` (and optionally its status)

        Returns the block corresponding to `block_id` or None if no match is
        found.

        Args:
            block_id (str): transaction id of the transaction to get
            include_status (bool): also return the status of the block
                       the return value is then a tuple: (block, status)
        """
        # get block from database
        block_dict = backend.query.get_block(self.connection, block_id)
        # get the asset ids from the block
        if block_dict:
            asset_ids = Block.get_asset_ids(block_dict)
            txn_ids = Block.get_txn_ids(block_dict)
            # get the assets from the database
            assets = self.get_assets(asset_ids)
            # get the metadata from the database
            metadata = self.get_metadata(txn_ids)
            # add the assets to the block transactions
            block_dict = Block.couple_assets(block_dict, assets)
            # add the metadata to the block transactions
            block_dict = Block.couple_metadata(block_dict, metadata)

        status = None
        if include_status:
            if block_dict:
                status = self.block_election_status(block_dict)
            return block_dict, status
        else:
            return block_dict
Example #8
0
    def test_get_asset_ids(self, b):
        from bigchaindb.models import Block, Transaction

        assets = [
            {'msg': '1'},
            {'msg': '2'},
            {'msg': '3'},
        ]

        txs = []
        # create 3 assets
        for asset in assets:
            tx = Transaction.create([b.me], [([b.me], 1)], asset=asset)
            txs.append(tx)

        # create a `TRANSFER` transaction.
        # the asset in `TRANSFER` transactions is not extracted
        tx = Transaction.transfer(txs[0].to_inputs(), [([b.me], 1)],
                                  asset_id=txs[0].id)
        txs.append(tx)

        # create the block
        block = Block(txs)
        # decouple assets
        assets_from_block, block_dict = block.decouple_assets()

        # get the asset_ids and check that they are the same as the `CREATE`
        # transactions
        asset_ids = Block.get_asset_ids(block_dict)
        assert asset_ids == [tx.id for tx in txs[:-1]]
Example #9
0
    def get_last_voted_block(self):
        """Returns the last block that this node voted on."""

        try:
            # get the latest value for the vote timestamp (over all votes)
            max_timestamp = self.connection.run(
                r.table('votes', read_mode=self.read_mode).filter(
                    r.row['node_pubkey'] == self.me).max(
                        r.row['vote']['timestamp']))['vote']['timestamp']

            last_voted = list(
                self.connection.run(
                    r.table('votes', read_mode=self.read_mode).filter(
                        r.row['vote']['timestamp'] == max_timestamp).filter(
                            r.row['node_pubkey'] == self.me)))

        except r.ReqlNonExistenceError:
            # return last vote if last vote exists else return Genesis block
            res = self.connection.run(
                r.table('bigchain', read_mode=self.read_mode).filter(
                    util.is_genesis_block))
            block = list(res)[0]
            return Block.from_dict(block)

        # Now the fun starts. Since the resolution of timestamp is a second,
        # we might have more than one vote per timestamp. If this is the case
        # then we need to rebuild the chain for the blocks that have been retrieved
        # to get the last one.

        # Given a block_id, mapping returns the id of the block pointing at it.
        mapping = {
            v['vote']['previous_block']: v['vote']['voting_for_block']
            for v in last_voted
        }

        # Since we follow the chain backwards, we can start from a random
        # point of the chain and "move up" from it.
        last_block_id = list(mapping.values())[0]

        # We must be sure to break the infinite loop. This happens when:
        # - the block we are currenty iterating is the one we are looking for.
        #   This will trigger a KeyError, breaking the loop
        # - we are visiting again a node we already explored, hence there is
        #   a loop. This might happen if a vote points both `previous_block`
        #   and `voting_for_block` to the same `block_id`
        explored = set()

        while True:
            try:
                if last_block_id in explored:
                    raise exceptions.CyclicBlockchainError()
                explored.add(last_block_id)
                last_block_id = mapping[last_block_id]
            except KeyError:
                break

        res = self.connection.run(
            r.table('bigchain', read_mode=self.read_mode).get(last_block_id))

        return Block.from_dict(res)
Example #10
0
    def test_compare_blocks(self, b):
        from bigchaindb.models import Block, Transaction

        transactions = [Transaction.create([b.me], [([b.me], 1)])]

        assert Block() != 'invalid comparison'
        assert Block(transactions) == Block(transactions)
Example #11
0
    def test_decouple_assets(self, b):
        from bigchaindb.models import Block, Transaction

        assets = [
            {'msg': '1'},
            {'msg': '2'},
            {'msg': '3'},
        ]

        txs = []
        # create 3 assets
        for asset in assets:
            tx = Transaction.create([b.me], [([b.me], 1)], asset=asset)
            txs.append(tx)

        # create a `TRANSFER` transaction.
        # the asset in `TRANSFER` transactions is not extracted
        tx = Transaction.transfer(txs[0].to_inputs(), [([b.me], 1)],
                                  asset_id=txs[0].id)
        txs.append(tx)

        # create the block
        block = Block(txs)
        # decouple assets
        assets_from_block, block_dict = block.decouple_assets()

        assert len(assets_from_block) == 3
        for i in range(3):
            assert assets_from_block[i]['data'] == assets[i]
            assert assets_from_block[i]['id'] == txs[i].id

        # check the `TRANSFER` transaction was not changed
        assert block.transactions[3].to_dict() == \
            block_dict['block']['transactions'][3]
Example #12
0
    def test_block_invalid_signature(self, b, alice):
        from bigchaindb.common.crypto import hash_data
        from bigchaindb.common.exceptions import InvalidSignature
        from bigchaindb.common.utils import gen_timestamp, serialize
        from bigchaindb.models import Block, Transaction

        transaction = Transaction.create([alice.public_key],
                                         [([alice.public_key], 1)])
        transaction.sign([alice.private_key])
        timestamp = gen_timestamp()

        block = {
            'timestamp': timestamp,
            'transactions': [transaction.to_dict()],
            'node_pubkey': alice.public_key,
        }

        block_body = {
            'id': hash_data(serialize(block)),
            'block': block,
            'signature': 'an invalid signature',
        }

        with raises(InvalidSignature):
            Block.from_dict(block_body).validate(b)
Example #13
0
    def get_block(self, block_id, include_status=False):
        """Get the block with the specified `block_id` (and optionally its status)

        Returns the block corresponding to `block_id` or None if no match is
        found.

        Args:
            block_id (str): transaction id of the transaction to get
            include_status (bool): also return the status of the block
                       the return value is then a tuple: (block, status)
        """
        # get block from database
        block_dict = backend.query.get_block(self.connection, block_id)
        # get the asset ids from the block
        if block_dict:
            asset_ids = Block.get_asset_ids(block_dict)
            # get the assets from the database
            assets = self.get_assets(asset_ids)
            # add the assets to the block transactions
            block_dict = Block.couple_assets(block_dict, assets)

        status = None
        if include_status:
            if block_dict:
                status = self.block_election_status(block_dict)
            return block_dict, status
        else:
            return block_dict
Example #14
0
    def test_block_serialization(self, b, alice):
        from bigchaindb.common.crypto import hash_data
        from bigchaindb.common.utils import gen_timestamp, serialize
        from bigchaindb.models import Block, Transaction

        transactions = [
            Transaction.create([alice.public_key], [([alice.public_key], 1)])
        ]
        timestamp = gen_timestamp()
        voters = ['Qaaa', 'Qbbb']
        expected_block = {
            'timestamp': timestamp,
            'transactions': [tx.to_dict() for tx in transactions],
            'node_pubkey': alice.public_key,
            'voters': voters,
        }
        expected = {
            'id': hash_data(serialize(expected_block)),
            'block': expected_block,
            'signature': None,
        }

        block = Block(transactions, alice.public_key, timestamp, voters)

        assert block.to_dict() == expected
def test_get_spent_for_tx_with_multiple_inputs(carol):
    from bigchaindb.backend import connect, query
    from bigchaindb.models import Block, Transaction
    conn = connect()
    tx_0 = Transaction.create(
        [carol.public_key],
        [([carol.public_key], 1), ([carol.public_key], 1),
         ([carol.public_key], 2)],
    ).sign([carol.private_key])
    block = Block(transactions=[tx_0])
    conn.db.bigchain.insert_one(block.to_dict())
    spents = list(query.get_spent(conn, tx_0.id, 0))
    assert not spents

    tx_1 = Transaction.transfer(
        tx_0.to_inputs()[2:3],
        [([carol.public_key], 1), ([carol.public_key], 1)],
        asset_id=tx_0.id,
    ).sign([carol.private_key])
    block = Block(transactions=[tx_1])
    conn.db.bigchain.insert_one(block.to_dict())
    spents = list(query.get_spent(conn, tx_0.id, 0))
    assert not spents

    tx_2 = Transaction.transfer(
        tx_0.to_inputs()[0:1] + tx_1.to_inputs()[1:2],
        [([carol.public_key], 2)],
        asset_id=tx_0.id,
    ).sign([carol.private_key])
    block = Block(transactions=[tx_2])
    conn.db.bigchain.insert_one(block.to_dict())
    spents = list(query.get_spent(conn, tx_0.id, 1))
    assert not spents
def test_count_blocks(signed_create_tx):
    from bigchaindb.backend import connect, query
    from bigchaindb.models import Block
    conn = connect()

    # create and insert some blocks
    block = Block(transactions=[signed_create_tx])
    conn.db.bigchain.insert_one(block.to_dict())
    conn.db.bigchain.insert_one(block.to_dict())

    assert query.count_blocks(conn) == 2
def test_write_block(signed_create_tx):
    from bigchaindb.backend import connect, query
    from bigchaindb.models import Block
    conn = connect()

    # create and write block
    block = Block(transactions=[signed_create_tx])
    query.write_block(conn, block.to_dict())

    block_db = conn.db.bigchain.find_one({'id': block.id}, {'_id': False})

    assert block_db == block.to_dict()
Example #18
0
def blockdata(b, user_pk, user2_pk):
    txs = [Transaction.create([user_pk], [([user2_pk], 1)]),
           Transaction.create([user2_pk], [([user_pk], 1)]),
           Transaction.create([user_pk], [([user_pk], 1), ([user2_pk], 1)])]
    blocks = []
    for i in range(3):
        block = Block([txs[i]])
        b.write_block(block)
        blocks.append(block.to_dict())
    b.write_vote(b.vote(blocks[1]['id'], '', True))
    b.write_vote(b.vote(blocks[2]['id'], '', False))
    return blocks, [b['id'] for b in blocks]
def test_get_block(signed_create_tx):
    from bigchaindb.backend import connect, query
    from bigchaindb.models import Block
    conn = connect()

    # create and insert block
    block = Block(transactions=[signed_create_tx])
    conn.db.bigchain.insert_one(block.to_dict())

    block_db = query.get_block(conn, block.id)

    assert block_db == block.to_dict()
Example #20
0
    def test_block_initialization(self, monkeypatch):
        from bigchaindb.models import Block

        monkeypatch.setattr('time.time', lambda: 1)

        block = Block()
        assert block.transactions == []
        assert block.timestamp == '1'
        assert block.node_pubkey is None
        assert block.signature is None

        with raises(TypeError):
            Block('not a list or None')
Example #21
0
    def test_block_invalid_id_deserialization(self, b, alice):
        from bigchaindb.common.exceptions import InvalidHash
        from bigchaindb.models import Block

        block = {
            'id': 'an invalid id',
            'block': {
                'node_pubkey': alice.public_key,
            }
        }

        with raises(InvalidHash):
            Block.from_dict(block)
def test_get_owned_ids(signed_create_tx, user_pk):
    from bigchaindb.backend import connect, query
    from bigchaindb.models import Block
    conn = connect()

    # create and insert a block
    block = Block(transactions=[signed_create_tx])
    conn.db.bigchain.insert_one(block.to_dict())

    [(block_id, tx)] = list(query.get_owned_ids(conn, user_pk))

    assert block_id == block.id
    assert tx == signed_create_tx.to_dict()
def test_get_asset_by_id(create_tx):
    from bigchaindb.backend import connect, query
    from bigchaindb.models import Block
    conn = connect()

    # create asset and block
    create_tx.asset = {'msg': 'aaa'}
    block = Block(transactions=[create_tx])
    conn.db.bigchain.insert_one(block.to_dict())

    asset = list(query.get_asset_by_id(conn, create_tx.id))

    assert len(asset) == 1
    assert asset[0]['asset'] == create_tx.asset
Example #24
0
    def check_for_quorum(self, next_vote):
        """
        Checks if block has enough invalid votes to make a decision

        Args:
            next_vote: The next vote.

        """
        try:
            block_id = next_vote['vote']['voting_for_block']
            node = next_vote['node_pubkey']
        except KeyError:
            return

        next_block = self.bigchain.get_block(block_id)

        result = self.bigchain.block_election(next_block)
        self.handle_block_events(result, block_id)
        if result['status'] == self.bigchain.BLOCK_INVALID:
            return Block.from_dict(next_block)

        # Log the result
        if result['status'] != self.bigchain.BLOCK_UNDECIDED:
            msg = 'node:%s block:%s status:%s' % \
                (node, block_id, result['status'])
            # Extra data can be accessed via the log formatter.
            # See logging.dictConfig.
            logger_results.debug(msg,
                                 extra={
                                     'current_vote': next_vote,
                                     'election_result': result,
                                 })
Example #25
0
    def check_for_quorum(self, next_vote):
        """
        Checks if block has enough invalid votes to make a decision

        Args:
            next_vote: The next vote.

        """
        try:
            block_id = next_vote['vote']['voting_for_block']
            node = next_vote['node_pubkey']
        except KeyError:
            return

        next_block = self.bigchain.get_block(block_id)

        result = self.bigchain.block_election(next_block)
        self.handle_block_events(result, block_id)
        if result['status'] == self.bigchain.BLOCK_INVALID:
            return Block.from_dict(next_block)

        # Log the result
        if result['status'] != self.bigchain.BLOCK_UNDECIDED:
            msg = 'node:%s block:%s status:%s' % \
                (node, block_id, result['status'])
            # Extra data can be accessed via the log formatter.
            # See logging.dictConfig.
            logger_results.debug(msg, extra={
                'current_vote': next_vote,
                'election_result': result,
            })
def test_get_block_status_from_transaction(create_tx):
    from bigchaindb.backend import connect, query
    from bigchaindb.models import Block
    conn = connect()

    # create a block
    block = Block(transactions=[create_tx], voters=['aaa', 'bbb', 'ccc'])
    # insert block
    conn.db.bigchain.insert_one(block.to_dict())

    block_db = list(
        query.get_blocks_status_from_transaction(conn, create_tx.id))

    assert len(block_db) == 1
    block_db = block_db.pop()
    assert block_db['id'] == block.id
    assert block_db['block']['voters'] == block.voters
def test_get_transaction_from_block(user_pk):
    from bigchaindb.backend import connect, query
    from bigchaindb.models import Transaction, Block
    conn = connect()

    # create a block with 2 transactions
    txs = [
        Transaction.create([user_pk], [([user_pk], 1)]),
        Transaction.create([user_pk], [([user_pk], 1)]),
    ]
    block = Block(transactions=txs)
    conn.db.bigchain.insert_one(block.to_dict())

    tx_db = query.get_transaction_from_block(conn, txs[0].id, block.id)
    assert tx_db == txs[0].to_dict()

    assert query.get_transaction_from_block(conn, txs[0].id, 'aaa') is None
    assert query.get_transaction_from_block(conn, 'aaa', block.id) is None
Example #28
0
    def test_couple_assets(self, b, alice):
        from bigchaindb.models import Block, Transaction

        assets = [
            {
                'msg': '1'
            },
            {
                'msg': '2'
            },
            {
                'msg': '3'
            },
        ]

        txs = []
        # create 3 assets
        for asset in assets:
            tx = Transaction.create([alice.public_key],
                                    [([alice.public_key], 1)],
                                    asset=asset)
            tx.sign([alice.private_key])
            txs.append(tx)

        # create a `TRANSFER` transaction.
        # the asset in `TRANSFER` transactions is not extracted
        tx = Transaction.transfer(txs[0].to_inputs(),
                                  [([alice.public_key], 1)],
                                  asset_id=txs[0].id)
        tx.sign([alice.private_key])
        txs.append(tx)

        # create the block
        block = Block(txs)
        # decouple assets
        assets_from_block, block_dict = block.decouple_assets()

        # reconstruct the block
        block_dict_reconstructed = Block.couple_assets(block_dict,
                                                       assets_from_block)

        # check that the reconstructed block is the same as the original block
        assert block == Block.from_dict(block_dict_reconstructed)
Example #29
0
    def test_get_last_voted_block_returns_genesis_if_no_votes_has_been_casted(
            self, b):
        from bigchaindb.models import Block
        from bigchaindb.backend import query

        genesis = query.get_genesis_block(b.connection)
        genesis = Block.from_db(b, genesis)
        gb = b.get_last_voted_block()
        assert gb == genesis
        assert b.validate_block(gb) == gb
def test_get_spending_transactions(user_pk):
    from bigchaindb.backend import connect, query
    from bigchaindb.models import Block, Transaction
    conn = connect()

    out = [([user_pk], 1)]
    tx1 = Transaction.create([user_pk], out * 3)
    inputs = tx1.to_inputs()
    tx2 = Transaction.transfer([inputs[0]], out, tx1.id)
    tx3 = Transaction.transfer([inputs[1]], out, tx1.id)
    tx4 = Transaction.transfer([inputs[2]], out, tx1.id)
    block = Block([tx1, tx2, tx3, tx4])
    conn.db.bigchain.insert_one(block.to_dict())

    links = [inputs[0].fulfills.to_dict(), inputs[2].fulfills.to_dict()]
    res = list(query.get_spending_transactions(conn, links))

    # tx3 not a member because input 1 not asked for
    assert res == [(block.id, tx2.to_dict()), (block.id, tx4.to_dict())]
Example #31
0
    def test_block_dupe_tx(self, b, alice):
        from bigchaindb.models import Block, Transaction
        from bigchaindb.common.exceptions import DuplicateTransaction

        tx = Transaction.create([alice.public_key], [([alice.public_key], 1)])
        block = Block([tx, tx], alice.public_key)
        block.sign(alice.private_key)
        b.store_block(block.to_dict())
        with raises(DuplicateTransaction):
            block.validate(b)
def test_get_txids_filtered(signed_create_tx, signed_transfer_tx):
    from bigchaindb.backend import connect, query
    from bigchaindb.models import Block, Transaction
    conn = connect()

    # create and insert two blocks, one for the create and one for the
    # transfer transaction
    block = Block(transactions=[signed_create_tx])
    conn.db.bigchain.insert_one(block.to_dict())
    block = Block(transactions=[signed_transfer_tx])
    conn.db.bigchain.insert_one(block.to_dict())

    asset_id = Transaction.get_asset_id([signed_create_tx, signed_transfer_tx])

    # Test get by just asset id
    txids = set(query.get_txids_filtered(conn, asset_id))
    assert txids == {signed_create_tx.id, signed_transfer_tx.id}

    # Test get by asset and CREATE
    txids = set(query.get_txids_filtered(conn, asset_id, Transaction.CREATE))
    assert txids == {signed_create_tx.id}

    # Test get by asset and TRANSFER
    txids = set(query.get_txids_filtered(conn, asset_id, Transaction.TRANSFER))
    assert txids == {signed_transfer_tx.id}
Example #33
0
    def create_block(self, validated_transactions):
        """Creates a block given a list of `validated_transactions`.

        Note that this method does not validate the transactions. Transactions
        should be validated before calling create_block.

        Args:
            validated_transactions (list(Transaction)): list of validated
                                                        transactions.

        Returns:
            Block: created block.
        """
        # Prevent the creation of empty blocks
        if len(validated_transactions) == 0:
            raise exceptions.OperationError('Empty block creation is not '
                                            'allowed')

        voters = self.nodes_except_me + [self.me]
        block = Block(validated_transactions, self.me, gen_timestamp(), voters)
        block = block.sign(self.me_private)

        return block
Example #34
0
    def check_for_quorum(self, next_vote):
        """
        Checks if block has enough invalid votes to make a decision

        Args:
            next_vote: The next vote.

        """
        next_block = self.bigchain.get_block(
            next_vote['vote']['voting_for_block'])

        block_status = self.bigchain.block_election_status(next_block['id'],
                                                           next_block['block']['voters'])
        if block_status == self.bigchain.BLOCK_INVALID:
            return Block.from_dict(next_block)
Example #35
0
 def validate_block(self, block):
     if not self.bigchain.has_previous_vote(block['id']):
         try:
             block = Block.from_dict(block)
         except (exceptions.InvalidHash):
             # XXX: if a block is invalid we should skip the `validate_tx`
             # step, but since we are in a pipeline we cannot just jump to
             # another function. Hackish solution: generate an invalid
             # transaction and propagate it to the next steps of the
             # pipeline.
             return block['id'], [self.invalid_dummy_tx]
         try:
             block._validate_block(self.bigchain)
         except exceptions.ValidationError:
             # XXX: if a block is invalid we should skip the `validate_tx`
             # step, but since we are in a pipeline we cannot just jump to
             # another function. Hackish solution: generate an invalid
             # transaction and propagate it to the next steps of the
             # pipeline.
             return block.id, [self.invalid_dummy_tx]
         return block.id, block.transactions
Example #36
0
    def get_last_voted_block(self):
        """Returns the last block that this node voted on."""

        return Block.from_dict(backend.query.get_last_voted_block(self.connection, self.me))