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
Exemple #3
0
    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
Exemple #4
0
    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()