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)
def sign(self, private_keys): """Fulfills a previous Transaction's Condition by signing Fulfillments. Note: This method works only for the following Cryptoconditions currently: - Ed25519Fulfillment - ThresholdSha256Fulfillment Furthermore, note that all keys required to fully sign the Transaction have to be passed to this method. A subset of all will cause this method to fail. Args: private_keys (:obj:`list` of :obj:`str`): A complete list of all private keys needed to sign all Fulfillments of this Transaction. Returns: :class:`~bigchaindb.common.transaction.Transaction` """ # TODO: Singing should be possible with at least one of all private # keys supplied to this method. if private_keys is None or not isinstance(private_keys, list): raise TypeError('`private_keys` must be a list instance') # NOTE: Generate public keys from private keys and match them in a # dictionary: # key: public_key # value: private_key def gen_public_key(private_key): # TODO FOR CC: Adjust interface so that this function becomes # unnecessary # cc now provides a single method `encode` to return the key # in several different encodings. public_key = private_key.get_verifying_key().encode() # Returned values from cc are always bytestrings so here we need # to decode to convert the bytestring into a python str return public_key.decode() key_pairs = { gen_public_key(PrivateKey(private_key)): PrivateKey(private_key) for private_key in private_keys } for index, fulfillment in enumerate(self.fulfillments): # NOTE: We clone the current transaction but only add the condition # and fulfillment we're currently working on plus all # previously signed ones. tx_partial = Transaction(self.operation, self.asset, [fulfillment], self.conditions, self.metadata, self.version) tx_partial_dict = tx_partial.to_dict() tx_partial_dict = Transaction._remove_signatures(tx_partial_dict) tx_serialized = Transaction._to_str(tx_partial_dict) self._sign_fulfillment(fulfillment, index, tx_serialized, key_pairs) return self
def sign(self, private_key): """Create a signature for the Block and overwrite `self.signature`. Args: private_key (str): A private key corresponding to `self.node_pubkey`. Returns: :class:`~.Block` """ block_body = self.to_dict() block_serialized = serialize(block_body['block']) private_key = PrivateKey(private_key) self.signature = private_key.sign(block_serialized.encode()).decode() return self
def test_get_last_voted_block_cyclic_blockchain(self, b, monkeypatch, alice): from bigchaindb.common.crypto import PrivateKey from bigchaindb.common.exceptions import CyclicBlockchainError from bigchaindb.common.utils import serialize from bigchaindb.models import Transaction tx = Transaction.create([alice.public_key], [([alice.public_key], 1)]) tx = tx.sign([alice.private_key]) monkeypatch.setattr('time.time', lambda: 1) block1 = b.create_block([tx]) b.write_block(block1) # Manipulate vote to create a cyclic Blockchain vote = b.vote(block1.id, b.get_last_voted_block().id, True) vote['vote']['previous_block'] = block1.id vote_data = serialize(vote['vote']) vote['signature'] = PrivateKey(alice.private_key).sign(vote_data.encode()) b.write_vote(vote) with pytest.raises(CyclicBlockchainError): b.get_last_voted_block()