def test_generate_key_pair(self): private_value_base58, public_value_compressed_base58 = generate_key_pair( ) assert PrivateKey.encode( PrivateKey.decode(private_value_base58)) == private_value_base58 assert PublicKey.encode(*PublicKey.decode( public_value_compressed_base58)) == public_value_compressed_base58
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_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_create_new_block(self, b): new_block = b.create_block([]) block_hash = hash_data(b.serialize(new_block['block'])) assert new_block['block']['voters'] == [b.me] assert new_block['block']['node_pubkey'] == b.me assert PublicKey(b.me).verify(b.serialize(new_block['block']), new_block['signature']) is True assert new_block['id'] == block_hash assert new_block['votes'] == []
def test_vote_creation_valid(self, b): # create valid block block = b.create_block([]) # retrieve vote vote = b.vote(block, 'abc', True) # assert vote is correct assert vote['vote']['voting_for_block'] == block['id'] assert vote['vote']['previous_block'] == 'abc' 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 verify_signature(self, signed_transaction): """Verify the signature of a transaction A valid transaction should have been signed `current_owner` corresponding private key. Args: signed_transaction (dict): a transaction with the `signature` included. Returns: bool: True if the signature is correct, False otherwise. """ data = signed_transaction.copy() # if assignee field in the transaction, remove it if 'assignee' in data: data.pop('assignee') signature = data.pop('signature') public_key_base58 = signed_transaction['transaction']['current_owner'] public_key = PublicKey(public_key_base58) return public_key.verify(self.serialize(data), signature)
def verify_signature(signed_transaction): """Verify the signature of a transaction A valid transaction should have been signed `current_owner` corresponding private key. Args: signed_transaction (dict): a transaction with the `signature` included. Returns: bool: True if the signature is correct, False otherwise. """ data = signed_transaction.copy() # if assignee field in the transaction, remove it if 'assignee' in data: data.pop('assignee') signatures = data.pop('signatures') for public_key_base58 in signed_transaction['transaction'][ 'current_owners']: public_key = PublicKey(public_key_base58) if isinstance(signatures, list): try: signature = [ s['signature'] for s in signatures if s['public_key'] == public_key_base58 ] except KeyError: return False if not len(signature) == 1: return False signature = signature[0] else: signature = signatures if not public_key.verify(serialize(data), signature): return False return True
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_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_public_key_encode(self): public_value_compressed_base58 = PublicKey.encode(self.PUBLIC_VALUE_X, self.PUBLIC_VALUE_Y) assert public_value_compressed_base58 == self.PUBLIC_VALUE_COMPRESSED_B58
def test_sign_verify(self): message = 'Hello World!' public_key = PublicKey(self.PUBLIC_VALUE_COMPRESSED_B58) private_key = PrivateKey(self.PRIVATE_VALUE_B58) assert public_key.verify(message, private_key.sign(message)) is True
def test_public_key_decode(self): public_value_x, public_value_y = PublicKey.decode(self.PUBLIC_VALUE_COMPRESSED_B58) assert public_value_x == self.PUBLIC_VALUE_X assert public_value_y == self.PUBLIC_VALUE_Y
def test_sign_verify(self): message = 'Hello World!' public_key = PublicKey(self.PUBLIC_VALUE_COMPRESSED_B58) private_key = PrivateKey(self.PRIVATE_VALUE_B58) assert public_key.verify(message, private_key.sign(message)) == True
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 = 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 = generate_key_pair() tx2 = b.create_transaction(test_user_pub, test_user2_pub, tx['id'], '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 PublicKey(b.me).verify(util.serialize(vote['vote']), vote['signature']) is True
def test_generate_key_pair(self): private_value_base58, public_value_compressed_base58 = generate_key_pair() assert PrivateKey.encode( PrivateKey.decode(private_value_base58)) == private_value_base58 assert PublicKey.encode( *PublicKey.decode(public_value_compressed_base58)) == public_value_compressed_base58