def test_valid_block_voting_sequential(b, genesis_block, monkeypatch):
    from bigchaindb.backend import query
    from bigchaindb.common import crypto, utils
    from bigchaindb.pipelines import vote

    monkeypatch.setattr('time.time', lambda: 1111111111)
    vote_obj = vote.Vote()
    block = dummy_block(b).to_dict()
    txs = block['block']['transactions']

    for tx, block_id, num_tx in vote_obj.ungroup(block['id'], txs):
        last_vote = vote_obj.vote(*vote_obj.validate_tx(tx, block_id, num_tx))

    vote_obj.write_vote(*last_vote)
    vote_rs = query.get_votes_by_block_id_and_voter(b.connection, block_id,
                                                    b.me)
    vote_doc = vote_rs.next()

    assert vote_doc['vote'] == {
        'voting_for_block': block['id'],
        'previous_block': genesis_block.id,
        'is_block_valid': True,
        'invalid_reason': None,
        'timestamp': '1111111111'
    }

    serialized_vote = utils.serialize(vote_doc['vote']).encode()
    assert vote_doc['node_pubkey'] == b.me
    assert crypto.PublicKey(b.me).verify(serialized_vote,
                                         vote_doc['signature']) is True
def test_vote_creation_invalid(b):
    from bigchaindb.common import crypto
    from bigchaindb.common.utils import serialize

    # create valid block
    block = dummy_block(b)
    # retrieve vote
    vote = b.vote(block.id, DUMMY_SHA3, False)

    # assert vote is correct
    assert vote['vote']['voting_for_block'] == block.id
    assert vote['vote']['previous_block'] == DUMMY_SHA3
    assert vote['vote']['is_block_valid'] is False
    assert vote['vote']['invalid_reason'] is None
    assert vote['node_pubkey'] == b.me
    assert crypto.PublicKey(b.me).verify(
        serialize(vote['vote']).encode(), vote['signature']) is True
def test_valid_block_voting_with_create_transaction(b, genesis_block,
                                                    monkeypatch):
    from bigchaindb.backend import query
    from bigchaindb.common import crypto, utils
    from bigchaindb.models import Transaction
    from bigchaindb.pipelines import vote

    # create a `CREATE` transaction
    test_user_priv, test_user_pub = crypto.generate_key_pair()
    tx = Transaction.create([b.me], [([test_user_pub], 1)])
    tx = tx.sign([b.me_private])

    monkeypatch.setattr('time.time', lambda: 1111111111)
    block = b.create_block([tx])
    block_dict = decouple_assets(b, block)

    inpipe = Pipe()
    outpipe = Pipe()

    vote_pipeline = vote.create_pipeline()
    vote_pipeline.setup(indata=inpipe, outdata=outpipe)

    inpipe.put(block_dict)
    vote_pipeline.start()
    vote_out = outpipe.get()
    vote_pipeline.terminate()

    vote_rs = query.get_votes_by_block_id_and_voter(b.connection, block.id,
                                                    b.me)
    vote_doc = vote_rs.next()
    assert vote_out['vote'] == vote_doc['vote']
    assert vote_doc['vote'] == {
        'voting_for_block': block.id,
        'previous_block': genesis_block.id,
        'is_block_valid': True,
        'invalid_reason': None,
        'timestamp': '1111111111'
    }

    serialized_vote = utils.serialize(vote_doc['vote']).encode()
    assert vote_doc['node_pubkey'] == b.me
    assert crypto.PublicKey(b.me).verify(serialized_vote,
                                         vote_doc['signature']) is True
def test_invalid_content_in_tx_in_block_voting(monkeypatch, b, user_pk,
                                               genesis_block):
    from bigchaindb.backend import query
    from bigchaindb.common import crypto, utils
    from bigchaindb.models import Transaction
    from bigchaindb.pipelines import vote

    inpipe = Pipe()
    outpipe = Pipe()

    monkeypatch.setattr('time.time', lambda: 1111111111)
    vote_pipeline = vote.create_pipeline()
    vote_pipeline.setup(indata=inpipe, outdata=outpipe)

    # NOTE: `tx` is invalid, because its content is not corresponding to its id
    tx = Transaction.create([b.me], [([b.me], 1)])
    tx = tx.sign([b.me_private])
    block = b.create_block([tx]).to_dict()
    block['block']['transactions'][0]['id'] = 'an invalid tx id'

    inpipe.put(block)
    vote_pipeline.start()
    vote_out = outpipe.get()
    vote_pipeline.terminate()

    vote_rs = query.get_votes_by_block_id_and_voter(b.connection, block['id'],
                                                    b.me)
    vote_doc = vote_rs.next()
    assert vote_out['vote'] == vote_doc['vote']
    assert vote_doc['vote'] == {
        'voting_for_block': block['id'],
        'previous_block': genesis_block.id,
        'is_block_valid': False,
        'invalid_reason': None,
        'timestamp': '1111111111'
    }

    serialized_vote = utils.serialize(vote_doc['vote']).encode()
    assert vote_doc['node_pubkey'] == b.me
    assert crypto.PublicKey(b.me).verify(serialized_vote,
                                         vote_doc['signature']) is True
Example #5
0
def verify_vote_signature(voters, signed_vote):
    """Verify the signature of a vote

    A valid vote should have been signed by a voter's private key.

    Args:
        voters (list): voters of the block that is under election
        signed_vote (dict): a vote with the `signature` included.

    Returns:
        bool: True if the signature is correct, False otherwise.
    """

    signature = signed_vote['signature']
    pk_base58 = signed_vote['node_pubkey']

    # immediately return False if the voter is not in the block voter list
    if pk_base58 not in voters:
        return False

    public_key = crypto.PublicKey(pk_base58)
    return public_key.verify(serialize(signed_vote['vote']).encode(), signature)
def test_invalid_block_voting(monkeypatch, b, user_pk, genesis_block):
    from bigchaindb.backend import query
    from bigchaindb.common import crypto, utils
    from bigchaindb.pipelines import vote

    inpipe = Pipe()
    outpipe = Pipe()

    monkeypatch.setattr('time.time', lambda: 1111111111)
    vote_pipeline = vote.create_pipeline()
    vote_pipeline.setup(indata=inpipe, outdata=outpipe)

    block = dummy_block(b).to_dict()
    block['block']['id'] = 'this-is-not-a-valid-hash'

    inpipe.put(block)
    vote_pipeline.start()
    vote_out = outpipe.get()
    vote_pipeline.terminate()

    vote_rs = query.get_votes_by_block_id_and_voter(b.connection, block['id'],
                                                    b.me)
    vote_doc = vote_rs.next()
    assert vote_out['vote'] == vote_doc['vote']
    assert vote_doc['vote'] == {
        'voting_for_block': block['id'],
        'previous_block': genesis_block.id,
        'is_block_valid': False,
        'invalid_reason': None,
        'timestamp': '1111111111'
    }

    serialized_vote = utils.serialize(vote_doc['vote']).encode()
    assert vote_doc['node_pubkey'] == b.me
    assert crypto.PublicKey(b.me).verify(serialized_vote,
                                         vote_doc['signature']) is True
def test_valid_block_voting_multiprocessing(b, genesis_block, monkeypatch):
    from bigchaindb.backend import query
    from bigchaindb.common import crypto, utils
    from bigchaindb.pipelines import vote

    inpipe = Pipe()
    outpipe = Pipe()

    monkeypatch.setattr('time.time', lambda: 1111111111)
    vote_pipeline = vote.create_pipeline()
    vote_pipeline.setup(indata=inpipe, outdata=outpipe)

    block = dummy_block(b)
    block_dict = decouple_assets(b, block)

    inpipe.put(block_dict)
    vote_pipeline.start()
    vote_out = outpipe.get()
    vote_pipeline.terminate()

    vote_rs = query.get_votes_by_block_id_and_voter(b.connection, block.id,
                                                    b.me)
    vote_doc = vote_rs.next()
    assert vote_out['vote'] == vote_doc['vote']
    assert vote_doc['vote'] == {
        'voting_for_block': block.id,
        'previous_block': genesis_block.id,
        'is_block_valid': True,
        'invalid_reason': None,
        'timestamp': '1111111111'
    }

    serialized_vote = utils.serialize(vote_doc['vote']).encode()
    assert vote_doc['node_pubkey'] == b.me
    assert crypto.PublicKey(b.me).verify(serialized_vote,
                                         vote_doc['signature']) is True
def test_valid_block_voting_with_transfer_transactions(monkeypatch, b,
                                                       genesis_block):
    from bigchaindb.backend import query
    from bigchaindb.common import crypto, utils
    from bigchaindb.models import Transaction
    from bigchaindb.pipelines import vote

    # create a `CREATE` transaction
    test_user_priv, test_user_pub = crypto.generate_key_pair()
    tx = Transaction.create([b.me], [([test_user_pub], 1)])
    tx = tx.sign([b.me_private])

    monkeypatch.setattr('time.time', lambda: 1000000000)
    block = b.create_block([tx])
    b.write_block(block)

    # create a `TRANSFER` transaction
    test_user2_priv, test_user2_pub = crypto.generate_key_pair()
    tx2 = Transaction.transfer(tx.to_inputs(), [([test_user2_pub], 1)],
                               asset_id=tx.id)
    tx2 = tx2.sign([test_user_priv])

    monkeypatch.setattr('time.time', lambda: 2000000000)
    block2 = b.create_block([tx2])
    b.write_block(block2)

    inpipe = Pipe()
    outpipe = Pipe()

    vote_pipeline = vote.create_pipeline()
    vote_pipeline.setup(indata=inpipe, outdata=outpipe)

    vote_pipeline.start()
    inpipe.put(block.to_dict())
    time.sleep(1)
    inpipe.put(block2.to_dict())
    vote_out = outpipe.get()
    vote2_out = outpipe.get()
    vote_pipeline.terminate()

    vote_rs = query.get_votes_by_block_id_and_voter(b.connection, block.id,
                                                    b.me)
    vote_doc = vote_rs.next()
    assert vote_out['vote'] == vote_doc['vote']
    assert vote_doc['vote'] == {
        'voting_for_block': block.id,
        'previous_block': genesis_block.id,
        'is_block_valid': True,
        'invalid_reason': None,
        'timestamp': '2000000000'
    }

    serialized_vote = utils.serialize(vote_doc['vote']).encode()
    assert vote_doc['node_pubkey'] == b.me
    assert crypto.PublicKey(b.me).verify(serialized_vote,
                                         vote_doc['signature']) is True

    vote2_rs = query.get_votes_by_block_id_and_voter(b.connection, block2.id,
                                                     b.me)
    vote2_doc = vote2_rs.next()
    assert vote2_out['vote'] == vote2_doc['vote']
    assert vote2_doc['vote'] == {
        'voting_for_block': block2.id,
        'previous_block': block.id,
        'is_block_valid': True,
        'invalid_reason': None,
        'timestamp': '2000000000'
    }

    serialized_vote2 = utils.serialize(vote2_doc['vote']).encode()
    assert vote2_doc['node_pubkey'] == b.me
    assert crypto.PublicKey(b.me).verify(serialized_vote2,
                                         vote2_doc['signature']) is True