コード例 #1
0
    def validate(self, bigchain, current_transactions=[]):
        """Validate transaction spend
        Args:
            bigchain (BigchainDB): an instantiated bigchaindb.BigchainDB object.
        Returns:
            The transaction (Transaction) if the transaction is valid else it
            raises an exception describing the reason why the transaction is
            invalid.
        Raises:
            ValidationError: If the transaction is invalid
        """
        input_conditions = []

        if self.operation == Transaction.CREATE:
            duplicates = any(txn for txn in current_transactions
                             if txn.id == self.id)
            if bigchain.is_committed(self.id) or duplicates:
                raise DuplicateTransaction(
                    'transaction `{}` already exists'.format(self.id))

            if not self.inputs_valid(input_conditions):
                raise InvalidSignature('Transaction signature is invalid.')

        elif self.operation == Transaction.TRANSFER:
            self.validate_transfer_inputs(bigchain, current_transactions)

        return self
コード例 #2
0
    def validate(self, bigchain, current_transactions=[]):
        """Validate election transaction
        For more details refer BEP-21: https://github.com/bigchaindb/BEPs/tree/master/21

        NOTE:
        * A valid election is initiated by an existing validator.

        * A valid election is one where voters are validators and votes are
          alloacted according to the voting power of each validator node.

        Args:
            bigchain (BigchainDB): an instantiated bigchaindb.lib.BigchainDB object.

        Returns:
            ValidatorElection object

        Raises:
            ValidationError: If the election is invalid
        """
        input_conditions = []

        duplicates = any(txn for txn in current_transactions
                         if txn.id == self.id)
        if bigchain.get_transaction(self.id) or duplicates:
            raise DuplicateTransaction(
                'transaction `{}` already exists'.format(self.id))

        if not self.inputs_valid(input_conditions):
            raise InvalidSignature('Transaction signature is invalid.')

        current_validators = self.get_validators(bigchain)

        # NOTE: Proposer should be a single node
        if len(self.inputs) != 1 or len(self.inputs[0].owners_before) != 1:
            raise MultipleInputsError(
                '`tx_signers` must be a list instance of length one')

        # NOTE: change more than 1/3 of the current power is not allowed
        if self.asset['data']['power'] >= (1 / 3) * sum(
                current_validators.values()):
            raise InvalidPowerChange(
                '`power` change must be less than 1/3 of total power')

        # NOTE: Check if the proposer is a validator.
        [election_initiator_node_pub_key] = self.inputs[0].owners_before
        if election_initiator_node_pub_key not in current_validators.keys():
            raise InvalidProposer(
                'Public key is not a part of the validator set')

        # NOTE: Check if all validators have been assigned votes equal to their voting power
        if not self.is_same_topology(current_validators, self.outputs):
            raise UnequalValidatorSet(
                'Validator set much be exactly same to the outputs of election'
            )

        return self
コード例 #3
0
    def validate(self, bigchain, current_transactions=[]):
        """Validate election transaction

        NOTE:
        * A valid election is initiated by an existing validator.

        * A valid election is one where voters are validators and votes are
          allocated according to the voting power of each validator node.

        Args:
            :param bigchain: (BigchainDB) an instantiated bigchaindb.lib.BigchainDB object.
            :param current_transactions: (list) A list of transactions to be validated along with the election

        Returns:
            Election: a Election object or an object of the derived Election subclass.

        Raises:
            ValidationError: If the election is invalid
        """
        input_conditions = []

        duplicates = any(txn for txn in current_transactions
                         if txn.id == self.id)
        if bigchain.is_committed(self.id) or duplicates:
            raise DuplicateTransaction(
                'transaction `{}` already exists'.format(self.id))

        if not self.inputs_valid(input_conditions):
            raise InvalidSignature('Transaction signature is invalid.')

        current_validators = self.get_validators(bigchain)

        # NOTE: Proposer should be a single node
        if len(self.inputs) != 1 or len(self.inputs[0].owners_before) != 1:
            raise MultipleInputsError(
                '`tx_signers` must be a list instance of length one')

        # NOTE: Check if the proposer is a validator.
        [election_initiator_node_pub_key] = self.inputs[0].owners_before
        if election_initiator_node_pub_key not in current_validators.keys():
            raise InvalidProposer(
                'Public key is not a part of the validator set')

        # NOTE: Check if all validators have been assigned votes equal to their voting power
        if not self.is_same_topology(current_validators, self.outputs):
            raise UnequalValidatorSet(
                'Validator set much be exactly same to the outputs of election'
            )

        return self
コード例 #4
0
ファイル: models.py プロジェクト: saakaifoundry/bigchaindb
    def _validate_block_transactions(self, bigchain):
        """Validate Block transactions.

        Args:
            bigchain (Bigchain): an instantiated bigchaindb.Bigchain object.

        Raises:
            ValidationError: If an invalid transaction is found
        """
        txids = [tx.id for tx in self.transactions]
        if len(txids) != len(set(txids)):
            raise DuplicateTransaction('Block has duplicate transaction')

        for tx in self.transactions:
            # If a transaction is not valid, `validate_transactions` will
            # throw an an exception and block validation will be canceled.
            bigchain.validate_transaction(tx)
コード例 #5
0
ファイル: models.py プロジェクト: rriveros/bigchaindb2
    def _validate_block(self, bigchain):
        """Validate the Block without validating the transactions.

        Args:
            bigchain (:class:`~bigchaindb.Bigchain`): An instantiated Bigchain
                object.

        Raises:
            ValidationError: If there is a problem with the block
        """
        # Check that the signature is valid
        if not self.is_signature_valid():
            raise InvalidSignature('Invalid block signature')

        # Check that the block contains no duplicated transactions
        txids = [tx.id for tx in self.transactions]
        if len(txids) != len(set(txids)):
            raise DuplicateTransaction('Block has duplicate transaction')
コード例 #6
0
ファイル: models.py プロジェクト: tmoon/bigchaindb
    def validate(self, bigchain, current_transactions=[]):
        """Validate transaction spend

        Args:
            bigchain (BigchainDB): an instantiated bigchaindb.tendermint.BigchainDB object.

        Returns:
            The transaction (Transaction) if the transaction is valid else it
            raises an exception describing the reason why the transaction is
            invalid.

        Raises:
            ValidationError: If the transaction is invalid
        """
        input_conditions = []

        if self.operation == Transaction.CREATE:
            duplicates = any(txn for txn in current_transactions
                             if txn.id == self.id)
            if bigchain.get_transaction(self.to_dict()['id']) or duplicates:
                raise DuplicateTransaction(
                    'transaction `{}` already exists'.format(self.id))
        elif self.operation == Transaction.TRANSFER:
            # store the inputs so that we can check if the asset ids match
            input_txs = []
            for input_ in self.inputs:
                input_txid = input_.fulfills.txid
                input_tx, status = bigchain.\
                    get_transaction(input_txid, include_status=True)

                if input_tx is None:
                    for ctxn in current_transactions:
                        # assume that the status as valid for previously validated
                        # transactions in current round
                        if ctxn.id == input_txid:
                            input_tx = ctxn
                            status = bigchain.TX_VALID

                if input_tx is None:
                    raise InputDoesNotExist(
                        "input `{}` doesn't exist".format(input_txid))

                if status != bigchain.TX_VALID:
                    raise TransactionNotInValidBlock(
                        'input `{}` does not exist in a valid block'.format(
                            input_txid))

                spent = bigchain.get_spent(input_txid, input_.fulfills.output,
                                           current_transactions)
                if spent and spent.id != self.id:
                    raise DoubleSpend(
                        'input `{}` was already spent'.format(input_txid))

                output = input_tx.outputs[input_.fulfills.output]
                input_conditions.append(output)
                input_txs.append(input_tx)

            # Validate that all inputs are distinct
            links = [i.fulfills.to_uri() for i in self.inputs]
            if len(links) != len(set(links)):
                raise DoubleSpend('tx "{}" spends inputs twice'.format(
                    self.id))

            # validate asset id
            asset_id = Transaction.get_asset_id(input_txs)
            if asset_id != self.asset['id']:
                raise AssetIdMismatch(('The asset id of the input does not'
                                       ' match the asset id of the'
                                       ' transaction'))

            input_amount = sum([
                input_condition.amount for input_condition in input_conditions
            ])
            output_amount = sum(
                [output_condition.amount for output_condition in self.outputs])

            if output_amount != input_amount:
                raise AmountError(
                    ('The amount used in the inputs `{}`'
                     ' needs to be same as the amount used'
                     ' in the outputs `{}`').format(input_amount,
                                                    output_amount))

        if not self.inputs_valid(input_conditions):
            raise InvalidSignature('Transaction signature is invalid.')

        return self