Пример #1
0
    def add_batch(self, batch, state_hash=None, required=False):
        with self._condition:
            if self._final:
                raise SchedulerError('Invalid attempt to add batch to '
                                     'finalized scheduler; batch: {}'
                                     .format(batch.header_signature))
            if not self._batches:
                self._least_batch_id_wo_results = batch.header_signature

            preserve = required
            if not required:
                # If this is the first non-required batch, it is preserved for
                # the schedule to be completed (i.e. no empty schedules in the
                # event of unschedule_incomplete_batches being called before
                # the first batch is completed).
                preserve = _first(
                    filterfalse(lambda sb: sb.required,
                                self._batches_by_id.values())) is None

            self._batches.append(batch)
            self._batches_by_id[batch.header_signature] = \
                _AnnotatedBatch(batch, required=required, preserve=preserve)
            for txn in batch.transactions:
                self._batches_by_txn_id[txn.header_signature] = batch
                self._txns_available.append(txn)
                self._transactions[txn.header_signature] = txn

            if state_hash is not None:
                b_id = batch.header_signature
                self._batches_with_state_hash[b_id] = state_hash

            # For dependency handling: First, we determine our dependencies
            # based on the current state of the predecessor tree.  Second,
            # we update the predecessor tree with reader and writer
            # information based on input and outputs.
            for txn in batch.transactions:
                header = TransactionHeader()
                header.ParseFromString(txn.header)

                # Calculate predecessors (transaction ids which must come
                # prior to the current transaction).
                predecessors = self._find_input_dependencies(header.inputs)
                predecessors.extend(
                    self._find_output_dependencies(header.outputs))

                txn_id = txn.header_signature
                # Update our internal state with the computed predecessors.
                self._txn_predecessors[txn_id] = set(predecessors)

                # Update the predecessor tree.
                #
                # Order of reader/writer operations is relevant.  A writer
                # may overshadow a reader.  For example, if the transaction
                # has the same input/output address, the end result will be
                # this writer (txn.header_signature) stored at the address of
                # the predecessor tree.  The reader information will have been
                # discarded.  Write operations to partial addresses will also
                # overshadow entire parts of the predecessor tree.
                #
                # Thus, the order here (inputs then outputs) will cause the
                # minimal amount of relevant information to be stored in the
                # predecessor tree, with duplicate information being
                # automatically discarded by the set_writer() call.
                for address in header.inputs:
                    self._predecessor_tree.add_reader(
                        address, txn_id)
                for address in header.outputs:
                    self._predecessor_tree.set_writer(
                        address, txn_id)

            self._condition.notify_all()
Пример #2
0
 def _txn_header(self, txn):
     txn_hdr = TransactionHeader()
     txn_hdr.ParseFromString(txn.header)
     return txn_hdr
Пример #3
0
 def _get_dependencies(self, transaction):
     header = TransactionHeader()
     header.ParseFromString(transaction.header)
     return list(header.dependencies)
Пример #4
0
    def is_transaction_signer_authorized(self, transactions, state_root,
                                         from_state):
        """ Check the transaction signing key against the allowed transactor
            permissions. The roles being checked are the following, from first
            to last:
                "transactor.transaction_signer.<TP_Name>"
                "transactor.transaction_signer"
                "transactor"
                "default"

            The first role that is set will be the one used to enforce if the
            transaction signer is allowed.

            Args:
                transactions (List of Transactions): The transactions that are
                    being verified.
                state_root(string): The state root of the previous block. If
                    this is None, the current state root hash will be
                    retrieved.
                from_state (bool): Whether the identity value should be read
                    directly from state, instead of using the cached values.
                    This should be used when the state_root passed is not from
                    the current chain head.
        """
        role = None
        if role is None:
            role = self._cache.get_role("transactor.transaction_signer",
                                        state_root, from_state)

        if role is None:
            role = self._cache.get_role("transactor", state_root, from_state)

        if role is None:
            policy_name = "default"
        else:
            policy_name = role.policy_name

        policy = self._cache.get_policy(policy_name, state_root, from_state)

        family_roles = {}
        for transaction in transactions:
            header = TransactionHeader()
            header.ParseFromString(transaction.header)
            family_policy = None
            if header.family_name not in family_roles:
                role = self._cache.get_role(
                    "transactor.transaction_signer." + header.family_name,
                    state_root, from_state)

                if role is not None:
                    family_policy = self._cache.get_policy(
                        role.policy_name, state_root, from_state)
                family_roles[header.family_name] = family_policy
            else:
                family_policy = family_roles[header.family_name]

            if family_policy is not None:
                if not self._allowed(header.signer_public_key, family_policy):
                    LOGGER.debug("Transaction Signer: %s is not permitted.",
                                 header.signer_public_key)
                    return False
            else:
                if policy is not None:
                    if not self._allowed(header.signer_public_key, policy):
                        LOGGER.debug(
                            "Transaction Signer: %s is not permitted.",
                            header.signer_public_key)
                        return False
        return True
Пример #5
0
    def is_transaction_signer_authorized(self, transactions, state_root):
        """ Check the transaction signing key against the allowed transactor
            permissions. The roles being checked are the following, from first
            to last:
                "transactor.transaction_signer.<TP_Name>"
                "transactor.transaction_signer"
                "transactor"
                "default"

            The first role that is set will be the one used to enforce if the
            transaction signer is allowed.

            Args:
                transactions (List of Transactions): The transactions that are
                    being verified.
                identity_view (IdentityView): The IdentityView that should be
                    used to verify the transactions.
        """
        role = None
        if role is None:
            role = self._cache.get_role("transactor.transaction_signer",
                                        state_root)

        if role is None:
            role = self._cache.get_role("transactor", state_root)

        if role is None:
            policy_name = "default"
        else:
            policy_name = role.policy_name

        policy = self._cache.get_policy(policy_name, state_root)

        family_roles = {}
        for transaction in transactions:
            header = TransactionHeader()
            header.ParseFromString(transaction.header)
            family_policy = None
            if header.family_name not in family_roles:
                role = self._cache.get_role(
                    "transactor.transaction_signer." + header.family_name,
                    state_root)

                if role is not None:
                    family_policy = self._cache.get_policy(
                        role.policy_name, state_root)
                family_roles[header.family_name] = family_policy
            else:
                family_policy = family_roles[header.family_name]

            if family_policy is not None:
                if not self._allowed(header.signer_public_key, family_policy):
                    LOGGER.debug("Transaction Signer: %s is not permitted.",
                                 header.signer_public_key)
                    return False
            else:
                if policy is not None:
                    if not self._allowed(header.signer_public_key, policy):
                        LOGGER.debug(
                            "Transaction Signer: %s is not permitted.",
                            header.signer_public_key)
                        return False
        return True