示例#1
0
文件: core.py 项目: galtys/bigchaindb
    def vote(self, block, previous_block_id, decision, invalid_reason=None):
        """Cast your vote on the block given the previous_block_hash and the decision (valid/invalid)
        return the block to the updated in the database.

        Args:
            block (dict): Block to vote.
            previous_block_id (str): The id of the previous block.
            decision (bool): Whether the block is valid or invalid.
            invalid_reason (Optional[str]): Reason the block is invalid
        """

        vote = {
            'voting_for_block': block['id'],
            'previous_block': previous_block_id,
            'is_block_valid': decision,
            'invalid_reason': invalid_reason,
            'timestamp': util.timestamp()
        }

        vote_data = util.serialize(vote)
        signature = crypto.SigningKey(self.me_private).sign(vote_data)

        vote_signed = {
            'node_pubkey': self.me,
            'signature': signature,
            'vote': vote
        }

        return vote_signed
示例#2
0
文件: core.py 项目: galtys/bigchaindb
    def create_block(self, validated_transactions):
        """Creates a block given a list of `validated_transactions`.

        Note that this method does not validate the transactions. Transactions should be validated before
        calling create_block.

        Args:
            validated_transactions (list): list of validated transactions.

        Returns:
            dict: created block.
        """

        # Create the new block
        block = {
            'timestamp': util.timestamp(),
            'transactions': validated_transactions,
            'node_pubkey': self.me,
            'voters': self.federation_nodes + [self.me]
        }

        # Calculate the hash of the new block
        block_data = util.serialize(block)
        block_hash = crypto.hash_data(block_data)
        block_signature = crypto.SigningKey(self.me_private).sign(block_data)

        block = {
            'id': block_hash,
            'block': block,
            'signature': block_signature,
            'votes': []
        }

        return block
    def test_invalid_transactions_in_block(self, b, user_public_key, ):
        # invalid transaction
        valid_input = b.get_owned_ids(user_public_key).pop()
        tx_invalid = b.create_transaction('a', 'b', valid_input, 'c')

        block = b.create_block([tx_invalid])

        # create a block with invalid transactions
        block = {
            'timestamp': util.timestamp(),
            'transactions': [tx_invalid],
            'node_pubkey': b.me,
            'voters': b.federation_nodes
        }

        block_data = util.serialize(block)
        block_hash = crypto.hash_data(block_data)
        block_signature = crypto.SigningKey(b.me_private).sign(block_data)

        block = {
            'id': block_hash,
            'block': block,
            'signature': block_signature,
            'votes': []
        }

        with pytest.raises(exceptions.TransactionOwnerError) as excinfo:
            b.validate_block(block)

        assert excinfo.value.args[0] == 'current_owner `a` does not own the input `{}`'.format(valid_input)
示例#4
0
def sign_tx(transaction, signing_keys, bigchain=None):
    """Sign a transaction

    A transaction signed with the `current_owner` corresponding private key.

    Args:
        transaction (dict): transaction to sign.
        signing_keys (list): list of base58 encoded private keys to create the fulfillments of the transaction.
        bigchain (obj): bigchain instance used to get the details of the previous transaction outputs. Useful
                        if the `Bigchain` instance was instantiated with parameters that override the config file.

    Returns:
        dict: transaction with the `fulfillment` fields populated.

    """
    # validate sk
    if not isinstance(signing_keys, list):
        signing_keys = [signing_keys]

    # create a mapping between sk and vk so that we can match the private key to the current_owners
    key_pairs = {}
    for sk in signing_keys:
        signing_key = crypto.SigningKey(sk)
        vk = signing_key.get_verifying_key().to_ascii().decode()
        key_pairs[vk] = signing_key

    tx = copy.deepcopy(transaction)

    bigchain = bigchain if bigchain is not None else bigchaindb.Bigchain()

    for fulfillment in tx['transaction']['fulfillments']:
        fulfillment_message = get_fulfillment_message(transaction, fulfillment)
        # TODO: avoid instantiation, pass as argument!
        input_condition = get_input_condition(bigchain, fulfillment)
        parsed_fulfillment = cc.Fulfillment.from_dict(
            input_condition['condition']['details'])
        # for the case in which the type of fulfillment is not covered by this method
        parsed_fulfillment_signed = parsed_fulfillment

        # single current owner
        if isinstance(parsed_fulfillment, cc.Ed25519Fulfillment):
            parsed_fulfillment_signed = fulfill_simple_signature_fulfillment(
                fulfillment, parsed_fulfillment, fulfillment_message,
                key_pairs)
        # multiple current owners
        elif isinstance(parsed_fulfillment, cc.ThresholdSha256Fulfillment):
            parsed_fulfillment_signed = fulfill_threshold_signature_fulfillment(
                fulfillment, parsed_fulfillment, fulfillment_message,
                key_pairs)

        signed_fulfillment = parsed_fulfillment_signed.serialize_uri()
        fulfillment.update({'fulfillment': signed_fulfillment})

    return tx
示例#5
0
def sign_tx(transaction, signing_keys):
    """Sign a transaction

    A transaction signed with the `current_owner` corresponding private key.

    Args:
        transaction (dict): transaction to sign.
        signing_keys (list): list of base58 encoded private keys to create the fulfillments of the transaction.

    Returns:
        dict: transaction with the `fulfillment` fields populated.

    """
    # validate sk
    if not isinstance(signing_keys, list):
        signing_keys = [signing_keys]

    # create a mapping between sk and vk so that we can match the private key to the current_owners
    key_pairs = {}
    for sk in signing_keys:
        signing_key = crypto.SigningKey(sk)
        vk = signing_key.get_verifying_key().to_ascii().decode()
        key_pairs[vk] = signing_key

    tx = copy.deepcopy(transaction)

    for fulfillment in tx['transaction']['fulfillments']:
        fulfillment_message = get_fulfillment_message(transaction, fulfillment)
        parsed_fulfillment = cc.Fulfillment.from_json(
            fulfillment_message['condition']['condition']['details'])
        # for the case in which the type of fulfillment is not covered by this method
        parsed_fulfillment_signed = parsed_fulfillment

        # single current owner
        if isinstance(parsed_fulfillment, cc.Ed25519Fulfillment):
            parsed_fulfillment_signed = fulfill_simple_signature_fulfillment(
                fulfillment, parsed_fulfillment, fulfillment_message,
                key_pairs)
        # multiple current owners
        elif isinstance(parsed_fulfillment, cc.ThresholdSha256Fulfillment):
            parsed_fulfillment_signed = fulfill_threshold_signature_fulfillment(
                fulfillment, parsed_fulfillment, fulfillment_message,
                key_pairs)

        signed_fulfillment = parsed_fulfillment_signed.serialize_uri()
        fulfillment.update({'fulfillment': signed_fulfillment})

    return tx
示例#6
0
def sign_tx(transaction, private_key):
    """Sign a transaction

    A transaction signed with the `current_owner` corresponding private key.

    Args:
        transaction (dict): transaction to sign.
        private_key (str): base58 encoded private key to create a signature of the transaction.

    Returns:
        dict: transaction with the `signature` field included.

    """
    private_key = crypto.SigningKey(private_key)
    signature = private_key.sign(serialize(transaction))
    signed_transaction = transaction.copy()
    signed_transaction.update({'signature': signature.decode()})
    return signed_transaction
示例#7
0
    def create_block(self, validated_transactions):
        """Creates a block given a list of `validated_transactions`.

        Note that this method does not validate the transactions. Transactions should be validated before
        calling create_block.

        Args:
            validated_transactions (list): list of validated transactions.

        Returns:
            dict: created block.
        """

        # Prevent the creation of empty blocks
        if len(validated_transactions) == 0:
            raise exceptions.OperationError(
                'Empty block creation is not allowed')

        # Create the new block
        block = {
            'timestamp': util.timestamp(),
            'transactions': validated_transactions,
            'node_pubkey': self.me,
            'voters': self.nodes_except_me + [self.me]
        }

        # Calculate the hash of the new block
        block_data = util.serialize(block)
        block_hash = crypto.hash_data(block_data)
        block_signature = crypto.SigningKey(self.me_private).sign(block_data)

        block = {
            'id': block_hash,
            'block': block,
            'signature': block_signature,
            'votes': []
        }

        return block