def is_valid_transaction(txn):
    # validate transactions signature
    header = TransactionHeader()
    header.ParseFromString(txn.header)

    if not signing.verify(txn.header, txn.header_signature,
                          header.signer_public_key):
        LOGGER.debug("transaction signature invalid for txn: %s",
                     txn.header_signature)
        return False

    # verify the payload field matches the header
    txn_payload_sha512 = hashlib.sha512(txn.payload).hexdigest()
    if txn_payload_sha512 != header.payload_sha512:
        LOGGER.debug(
            "payload doesn't match payload_sha512 of the header"
            "for txn: %s", txn.header_signature)
        return False

    return True
示例#2
0
def is_valid_transaction(txn):
    # validate transactions signature
    header = TransactionHeader()
    header.ParseFromString(txn.header)

    context = create_context('secp256k1')
    public_key = Secp256k1PublicKey.from_hex(header.signer_public_key)
    if not context.verify(txn.header_signature, txn.header, public_key):
        LOGGER.debug("transaction signature invalid for txn: %s",
                     txn.header_signature)
        return False

    # verify the payload field matches the header
    txn_payload_sha512 = hashlib.sha512(txn.payload).hexdigest()
    if txn_payload_sha512 != header.payload_sha512:
        LOGGER.debug(
            "payload doesn't match payload_sha512 of the header"
            "for txn: %s", txn.header_signature)
        return False

    return True
def validate_batch(batch):
    # validate batch signature
    header = BatchHeader()
    header.ParseFromString(batch.header)
    valid = signing.verify(batch.header, batch.header_signature,
                           header.signer_pubkey)

    # validate all transactions in batch
    total = len(batch.transactions)
    index = 0
    while valid and index < total:
        txn = batch.transactions[index]
        valid = validate_transaction(txn)
        if valid:
            txn_header = TransactionHeader()
            txn_header.ParseFromString(txn.header)
            if txn_header.batcher_pubkey != header.signer_pubkey:
                valid = False
        index += 1

    return valid
    def _do_xaty(self, transactions, arguments):
        """
        A transaction of type X must be in the block at position Y. The
        first argument is interpreted as the name of a transaction family.
        The second argument must be interpretable as an integer and defines
        the index of the transaction in the block that must be checked.
        Negative numbers can be used and count backwards from the last
        transaction in the block. The first transaction in the block has
        index 0. The last transaction in the block has index -1. If abs(Y)
        is larger than the number of transactions per block, then there
        would not be a transaction of type X at Y and the block would be
        invalid. For example, the string "XatY:intkey,0" means the first
        transaction in the block must be an intkey transaction.
        """
        try:
            family, num = arguments.split(',')
            position = int(num.strip())
        except ValueError:
            LOGGER.warning(
                "Ignore, XatY requires arguments in the format "
                "family,position not %s", arguments)
            return True

        family = family.strip()
        if abs(position) >= len(transactions):
            LOGGER.debug(
                "Block does not have enough transactions to "
                "validate this rule XatY:%s", arguments)
            return False
        txn = transactions[position]

        header = TransactionHeader()
        header.ParseFromString(txn.header)
        if header.family_name != family:
            LOGGER.debug("Transaction at postion %s is not of type %s",
                         position, family)
            return False
        return True
示例#5
0
    def _verify_batches_dependencies(self, batch, committed_txn):
        """Verify that all transactions dependencies in this batch have been
        satisfied, ie already committed by this block or prior block in the
        chain.

        :param batch: the batch to verify
        :param committed_txn(TransactionCache): Current set of committed
        transaction, updated during processing.
        :return:
        Boolean: True if all dependencies are present.
        """
        for txn in batch.transactions:
            txn_hdr = TransactionHeader()
            txn_hdr.ParseFromString(txn.header)
            for dep in txn_hdr.dependencies:
                if dep not in committed_txn:
                    LOGGER.debug(
                        "Block rejected due missing" +
                        " transaction dependency, transaction %s"
                        " depends on %s", txn.header_signature[:8], dep[:8])
                    return False
            committed_txn.add_txn(txn.header_signature)
        return True
示例#6
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()
示例#7
0
 def _get_dependencies(self, transaction):
     header = TransactionHeader()
     header.ParseFromString(transaction.header)
     return list(header.dependencies)
    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
示例#9
0
 def _txn_header(self, txn):
     txn_hdr = TransactionHeader()
     txn_hdr.ParseFromString(txn.header)
     return txn_hdr
    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