def test_voter_chains_blocks_with_the_previous_ones(self, b): b.create_genesis_block() block_1 = b.create_block([]) b.write_block(block_1, durability='hard') block_2 = b.create_block([]) b.write_block(block_2, durability='hard') q_new_block = mp.Queue() voter = Voter(q_new_block) voter.start() time.sleep(1) voter.kill() # retrive blocks from bigchain blocks = list(r.table('bigchain') .order_by(r.asc((r.row['block']['timestamp']))) .run(b.conn)) assert blocks[0]['block_number'] == 0 assert blocks[1]['block_number'] == 1 assert blocks[2]['block_number'] == 2 # we don't vote on the genesis block right now # assert blocks[0]['votes'][0]['vote']['voting_for_block'] == genesis['id'] assert blocks[1]['votes'][0]['vote']['voting_for_block'] == block_1['id'] assert blocks[2]['votes'][0]['vote']['voting_for_block'] == block_2['id']
def start(self): logger.info('Initializing BigchainDB...') # instantiate block and voter block = Block(self.q_new_transaction) # start the web api app_server = server.create_server(bigchaindb.config['server']) p_webapi = mp.Process(name='webapi', target=app_server.run) p_webapi.start() # initialize the processes p_map_bigchain = mp.Process(name='bigchain_mapper', target=self.map_bigchain) p_map_backlog = mp.Process(name='backlog_mapper', target=self.map_backlog) p_block = mp.Process(name='block', target=block.start) p_voter = Voter(self.q_new_block) p_election = Election(self.q_block_new_vote) # start the processes logger.info('starting bigchain mapper') p_map_bigchain.start() logger.info('starting backlog mapper') p_map_backlog.start() logger.info('starting block') p_block.start() logger.info('starting voter') p_voter.start() logger.info('starting election') p_election.start() # start message block.initialized.wait() p_voter.initialized.wait() logger.info(BANNER.format(bigchaindb.config['server']['bind']))
def start(self): logger.info('Initializing BigchainDB...') delete_reverter = BlockDeleteRevert(self.q_revert_delete) # start the web api app_server = server.create_server(bigchaindb.config['server']) p_webapi = mp.Process(name='webapi', target=app_server.run) p_webapi.start() # initialize the processes p_map_bigchain = mp.Process(name='bigchain_mapper', target=self.map_bigchain) p_block_delete_revert = mp.Process(name='block_delete_revert', target=delete_reverter.start) p_voter = Voter(self.q_new_block) p_election = Election(self.q_block_new_vote) # start the processes logger.info('starting bigchain mapper') p_map_bigchain.start() logger.info('starting backlog mapper') logger.info('starting block') block.start() p_block_delete_revert.start() logger.info('starting voter') p_voter.start() logger.info('starting election') p_election.start() # start message p_voter.initialized.wait() logger.info(BANNER.format(bigchaindb.config['server']['bind']))
def test_valid_block_voting(self, b): q_new_block = mp.Queue() genesis = b.create_genesis_block() # create valid block block = b.create_block([]) # assert block is valid assert b.is_valid_block(block) b.write_block(block, durability='hard') # create queue and voter voter = Voter(q_new_block) # vote voter.start() # wait for vote to be written time.sleep(1) voter.kill() # retrive block from bigchain blocks = list(r.table('bigchain') .order_by(r.asc((r.row['block']['timestamp']))) .run(b.conn)) # validate vote assert len(blocks[1]['votes']) == 1 vote = blocks[1]['votes'][0] assert vote['vote']['voting_for_block'] == block['id'] assert vote['vote']['previous_block'] == genesis['id'] assert vote['vote']['is_block_valid'] is True assert vote['vote']['invalid_reason'] is None assert vote['node_pubkey'] == b.me assert crypto.VerifyingKey(b.me).verify(util.serialize(vote['vote']), vote['signature']) is True
def start(self): logger.info('Initializing BigchainDB...') # instantiate block and voter block = Block(self.q_new_transaction) # start the web api app_server = server.create_server(bigchaindb.config['server']) p_webapi = mp.Process(name='webapi', target=app_server.run) p_webapi.start() # initialize the processes p_map_bigchain = mp.Process(name='bigchain_mapper', target=self.map_bigchain) p_map_backlog = mp.Process(name='backlog_mapper', target=self.map_backlog) p_block = mp.Process(name='block', target=block.start) p_voter = Voter(self.q_new_block) # start the processes logger.info('starting bigchain mapper') p_map_bigchain.start() logger.info('starting backlog mapper') p_map_backlog.start() logger.info('starting block') p_block.start() logger.info('starting voter') p_voter.start() # start message block.initialized.wait() p_voter.initialized.wait() logger.info(BANNER.format(bigchaindb.config['server']['bind']))
def test_valid_block_voting(self, b): # create queue and voter q_new_block = mp.Queue() voter = Voter(q_new_block) genesis = b.create_genesis_block() # create valid block block = b.create_block([]) # assert block is valid assert b.is_valid_block(block) b.write_block(block, durability='hard') # insert into queue # FIXME: we disable this because the voter can currently vote more than one time for a block # q_new_block.put(block) # vote voter.start() # wait for vote to be written time.sleep(1) voter.kill() # retrive block from bigchain bigchain_block = r.table('bigchain').get(block['id']).run(b.conn) # validate vote assert len(bigchain_block['votes']) == 1 vote = bigchain_block['votes'][0] assert vote['vote']['voting_for_block'] == block['id'] assert vote['vote']['previous_block'] == genesis['id'] assert vote['vote']['is_block_valid'] == True assert vote['vote']['invalid_reason'] == None assert vote['node_pubkey'] == b.me assert PublicKey(b.me).verify(b.serialize(vote['vote']), vote['signature']) == True
def start(self): # instantiate block and voter block = Block(self.q_new_transaction) # initialize the processes p_map_bigchain = mp.Process(name='bigchain_mapper', target=self.map_bigchain) p_map_backlog = mp.Process(name='backlog_mapper', target=self.map_backlog) p_block = mp.Process(name='block', target=block.start) p_voter = Voter(self.q_new_block) # start the processes logger.info('starting bigchain mapper') p_map_bigchain.start() logger.info('starting backlog mapper') p_map_backlog.start() logger.info('starting block') p_block.start() logger.info('starting voter') p_voter.start()
def test_invalid_block_voting(self, b): # create queue and voter q_new_block = mp.Queue() voter = Voter(q_new_block) # create transaction transaction = b.create_transaction(b.me, USER_PUBLIC_KEY, None, 'CREATE') transaction_signed = b.sign_transaction(transaction, b.me_private) genesis = b.create_genesis_block() # create invalid block block = b.create_block([transaction_signed]) # change transaction id to make it invalid block['block']['transactions'][0]['id'] = 'abc' assert b.is_valid_block(block) == False b.write_block(block, durability='hard') # insert into queue # FIXME: we disable this because the voter can currently vote more than one time for a block # q_new_block.put(block) # vote voter.start() # wait for the vote to be written time.sleep(1) voter.kill() # retrive block from bigchain bigchain_block = r.table('bigchain').get(block['id']).run(b.conn) # validate vote assert len(bigchain_block['votes']) == 1 vote = bigchain_block['votes'][0] assert vote['vote']['voting_for_block'] == block['id'] assert vote['vote']['previous_block'] == genesis['id'] assert vote['vote']['is_block_valid'] == False assert vote['vote']['invalid_reason'] == None assert vote['node_pubkey'] == b.me assert PublicKey(b.me).verify(b.serialize(vote['vote']), vote['signature']) == True
def test_valid_block_voting(self, b): q_new_block = mp.Queue() genesis = b.create_genesis_block() # create valid block block = b.create_block([]) # assert block is valid assert b.is_valid_block(block) b.write_block(block, durability='hard') # create queue and voter voter = Voter(q_new_block) # vote voter.start() # wait for vote to be written time.sleep(1) voter.kill() # retrive block from bigchain blocks = list(r.table('bigchain') .order_by(r.asc((r.row['block']['timestamp']))) .run(b.conn)) # validate vote assert len(blocks[1]['votes']) == 1 vote = blocks[1]['votes'][0] assert vote['vote']['voting_for_block'] == block['id'] assert vote['vote']['previous_block'] == genesis['id'] assert vote['vote']['is_block_valid'] is True assert vote['vote']['invalid_reason'] is None assert vote['node_pubkey'] == b.me assert PublicKey(b.me).verify(util.serialize(vote['vote']), vote['signature']) is True
def test_valid_block_voting(self, b): # create queue and voter q_new_block = mp.Queue() voter = Voter(q_new_block) genesis = b.create_genesis_block() # create valid block block = b.create_block([]) # assert block is valid assert b.is_valid_block(block) b.write_block(block, durability='hard') # insert into queue # FIXME: we disable this because the voter can currently vote more than one time for a block # q_new_block.put(block) # vote voter.start() # wait for vote to be written time.sleep(1) voter.kill() # retrive block from bigchain bigchain_block = r.table('bigchain').get(block['id']).run(b.conn) # validate vote assert len(bigchain_block['votes']) == 1 vote = bigchain_block['votes'][0] assert vote['vote']['voting_for_block'] == block['id'] assert vote['vote']['previous_block'] == genesis['id'] assert vote['vote']['is_block_valid'] is True assert vote['vote']['invalid_reason'] is None assert vote['node_pubkey'] == b.me assert PublicKey(b.me).verify(b.serialize(vote['vote']), vote['signature']) is True
def test_invalid_block_voting(self, b): # create queue and voter q_new_block = mp.Queue() voter = Voter(q_new_block) # create transaction transaction = b.create_transaction(b.me, USER_PUBLIC_KEY, None, 'CREATE') transaction_signed = b.sign_transaction(transaction, b.me_private) genesis = b.create_genesis_block() # create invalid block block = b.create_block([transaction_signed]) # change transaction id to make it invalid block['block']['transactions'][0]['id'] = 'abc' assert not b.is_valid_block(block) b.write_block(block, durability='hard') # vote voter.start() time.sleep(1) voter.kill() # retrive block from bigchain blocks = list(r.table('bigchain') .order_by(r.asc((r.row['block']['timestamp']))) .run(b.conn)) # validate vote assert len(blocks[1]['votes']) == 1 vote = blocks[1]['votes'][0] assert vote['vote']['voting_for_block'] == block['id'] assert vote['vote']['previous_block'] == genesis['id'] assert vote['vote']['is_block_valid'] == False assert vote['vote']['invalid_reason'] == None assert vote['node_pubkey'] == b.me assert PublicKey(b.me).verify(b.serialize(vote['vote']), vote['signature']) == True
def test_voter_considers_unvoted_blocks_when_single_node(self, b): # simulate a voter going donw in a single node environment b.create_genesis_block() # insert blocks in the database while the voter process is not listening # (these blocks won't appear in the changefeed) block_1 = b.create_block([]) b.write_block(block_1, durability='hard') block_2 = b.create_block([]) b.write_block(block_2, durability='hard') # voter is back online, we simulate that by creating a queue and a Voter instance q_new_block = mp.Queue() voter = Voter(q_new_block) # create a new block that will appear in the changefeed block_3 = b.create_block([]) b.write_block(block_3, durability='hard') # put the last block in the queue q_new_block.put(block_3) # vote voter.start() time.sleep(1) voter.kill() # retrive blocks from bigchain blocks = list(r.table('bigchain') .order_by(r.asc((r.row['block']['timestamp']))) .run(b.conn)) # FIXME: remove genesis block, we don't vote on it (might change in the future) blocks.pop(0) assert all(block['votes'][0]['node_pubkey'] == b.me for block in blocks)
def test_invalid_block_voting(self, b, user_public_key): # create queue and voter q_new_block = mp.Queue() voter = Voter(q_new_block) # create transaction transaction = b.create_transaction(b.me, user_public_key, None, 'CREATE') transaction_signed = b.sign_transaction(transaction, b.me_private) genesis = b.create_genesis_block() # create invalid block block = b.create_block([transaction_signed]) # change transaction id to make it invalid block['block']['transactions'][0]['id'] = 'abc' assert b.is_valid_block(block) is False b.write_block(block, durability='hard') # insert into queue # FIXME: we disable this because the voter can currently vote more than one time for a block # q_new_block.put(block) # vote voter.start() # wait for the vote to be written time.sleep(1) voter.kill() # retrive block from bigchain bigchain_block = r.table('bigchain').get(block['id']).run(b.conn) # validate vote assert len(bigchain_block['votes']) == 1 vote = bigchain_block['votes'][0] assert vote['vote']['voting_for_block'] == block['id'] assert vote['vote']['previous_block'] == genesis['id'] assert vote['vote']['is_block_valid'] is False assert vote['vote']['invalid_reason'] is None assert vote['node_pubkey'] == b.me assert PublicKey(b.me).verify(util.serialize(vote['vote']), vote['signature']) is True
def test_valid_block_voting_with_create_transaction(self, b): q_new_block = mp.Queue() genesis = b.create_genesis_block() # create a `CREATE` transaction test_user_priv, test_user_pub = crypto.generate_key_pair() tx = b.create_transaction(b.me, test_user_pub, None, 'CREATE') tx_signed = b.sign_transaction(tx, b.me_private) assert b.is_valid_transaction(tx_signed) # create valid block block = b.create_block([tx_signed]) # assert block is valid assert b.is_valid_block(block) b.write_block(block, durability='hard') # create queue and voter voter = Voter(q_new_block) # vote voter.start() # wait for vote to be written time.sleep(1) voter.kill() # retrive block from bigchain blocks = list(r.table('bigchain') .order_by(r.asc((r.row['block']['timestamp']))) .run(b.conn)) # validate vote assert len(blocks[1]['votes']) == 1 vote = blocks[1]['votes'][0] assert vote['vote']['voting_for_block'] == block['id'] assert vote['vote']['previous_block'] == genesis['id'] assert vote['vote']['is_block_valid'] is True assert vote['vote']['invalid_reason'] is None assert vote['node_pubkey'] == b.me assert crypto.VerifyingKey(b.me).verify(util.serialize(vote['vote']), vote['signature']) is True
def test_invalid_block_voting(self, b): # create queue and voter q_new_block = mp.Queue() voter = Voter(q_new_block) # create transaction transaction = b.create_transaction(b.me, USER_PUBLIC_KEY, None, 'CREATE') transaction_signed = b.sign_transaction(transaction, b.me_private) genesis = b.create_genesis_block() # create invalid block block = b.create_block([transaction_signed]) # change transaction id to make it invalid block['block']['transactions'][0]['id'] = 'abc' assert not b.is_valid_block(block) b.write_block(block, durability='hard') # vote voter.start() time.sleep(1) voter.kill() # retrive block from bigchain blocks = list( r.table('bigchain').order_by(r.asc( (r.row['block']['timestamp']))).run(b.conn)) # validate vote assert len(blocks[1]['votes']) == 1 vote = blocks[1]['votes'][0] assert vote['vote']['voting_for_block'] == block['id'] assert vote['vote']['previous_block'] == genesis['id'] assert vote['vote']['is_block_valid'] == False assert vote['vote']['invalid_reason'] == None assert vote['node_pubkey'] == b.me assert PublicKey(b.me).verify(b.serialize(vote['vote']), vote['signature']) == True
def test_voter_considers_unvoted_blocks_when_single_node(self, b): # simulate a voter going donw in a single node environment b.create_genesis_block() # insert blocks in the database while the voter process is not listening # (these blocks won't appear in the changefeed) block_1 = b.create_block([]) b.write_block(block_1, durability='hard') block_2 = b.create_block([]) b.write_block(block_2, durability='hard') # voter is back online, we simulate that by creating a queue and a Voter instance q_new_block = mp.Queue() voter = Voter(q_new_block) # create a new block that will appear in the changefeed block_3 = b.create_block([]) b.write_block(block_3, durability='hard') # put the last block in the queue q_new_block.put(block_3) # vote voter.start() time.sleep(1) voter.kill() # retrive blocks from bigchain blocks = list( r.table('bigchain').order_by(r.asc( (r.row['block']['timestamp']))).run(b.conn)) # FIXME: remove genesis block, we don't vote on it (might change in the future) blocks.pop(0) assert all(block['votes'][0]['node_pubkey'] == b.me for block in blocks)
def test_valid_block_voting_with_transfer_transactions(self, b): q_new_block = mp.Queue() b.create_genesis_block() # create a `CREATE` transaction test_user_priv, test_user_pub = crypto.generate_key_pair() tx = b.create_transaction(b.me, test_user_pub, None, 'CREATE') tx_signed = b.sign_transaction(tx, b.me_private) assert b.is_valid_transaction(tx_signed) # create valid block block = b.create_block([tx_signed]) # assert block is valid assert b.is_valid_block(block) b.write_block(block, durability='hard') # create queue and voter voter = Voter(q_new_block) # vote voter.start() # wait for vote to be written time.sleep(1) voter.kill() # retrive block from bigchain blocks = list(r.table('bigchain') .order_by(r.asc((r.row['block']['timestamp']))) .run(b.conn)) # validate vote assert len(blocks[1]['votes']) == 1 # create a `TRANSFER` transaction test_user2_priv, test_user2_pub = crypto.generate_key_pair() tx2 = b.create_transaction(test_user_pub, test_user2_pub, {'txid': tx['id'], 'cid': 0}, 'TRANSFER') tx2_signed = b.sign_transaction(tx2, test_user_priv) assert b.is_valid_transaction(tx2_signed) # create valid block block = b.create_block([tx2_signed]) # assert block is valid assert b.is_valid_block(block) b.write_block(block, durability='hard') # create queue and voter voter = Voter(q_new_block) # vote voter.start() # wait for vote to be written time.sleep(1) voter.kill() # retrive block from bigchain blocks = list(r.table('bigchain') .order_by(r.asc((r.row['block']['timestamp']))) .run(b.conn)) # validate vote assert len(blocks[2]['votes']) == 1 vote = blocks[2]['votes'][0] assert vote['vote']['voting_for_block'] == block['id'] assert vote['vote']['is_block_valid'] is True assert vote['vote']['invalid_reason'] is None assert vote['node_pubkey'] == b.me assert crypto.VerifyingKey(b.me).verify(util.serialize(vote['vote']), vote['signature']) is True