def set_transaction_execution_result(self, txn_signature, is_valid,
                                         context_id):
        with self._condition:
            if (self._in_progress_transaction is None
                    or self._in_progress_transaction != txn_signature):
                raise ValueError(
                    "transaction not in progress: {}".format(txn_signature))
            self._in_progress_transaction = None

            if txn_signature not in self._txn_to_batch:
                raise ValueError(
                    "transaction not in any batches: {}".format(txn_signature))

            batch_signature = self._txn_to_batch[txn_signature]
            if is_valid:
                self._previous_context_id = context_id

            else:
                # txn is invalid, preemptively fail the batch
                self._batch_statuses[batch_signature] = \
                    BatchExecutionResult(is_valid=is_valid, state_hash=None)
            if txn_signature in self._last_in_batch:
                if batch_signature not in self._batch_statuses:
                    # because of the else clause above, txn is valid here
                    self._previous_valid_batch_c_id = self._previous_context_id
                    state_hash = None
                    required_state_hash = self._required_state_hashes.get(
                        batch_signature)
                    if required_state_hash is not None \
                            or self._last_in_batch[-1] == txn_signature:
                        state_hash = self._compute_merkle_root(
                            required_state_hash)
                    self._batch_statuses[batch_signature] = \
                        BatchExecutionResult(
                            is_valid=is_valid,
                            state_hash=state_hash)
                else:
                    self._previous_context_id = self._previous_valid_batch_c_id
                    required_state_hash = self._required_state_hashes.get(
                        batch_signature)
                    if self._last_in_batch[-1] == txn_signature and \
                            required_state_hash is None:
                        # This is only needed for block publishing, where
                        # the state hash is for state changes in all valid
                        # batches.
                        s_hash = self._compute_merkle_root(
                            required_state_root=required_state_hash)
                        for t_id in self._last_in_batch[::-1]:
                            b_id = self._txn_to_batch[t_id]
                            if self._batch_statuses[b_id].is_valid:
                                self._batch_statuses[b_id].state_hash = s_hash
                                # found the last valid batch, so break out
                                break

                is_last_batch = \
                    len(self._batch_statuses) == len(self._last_in_batch)

                if self._final and is_last_batch:
                    self._complete = True
            self._condition.notify_all()
    def get_batch_execution_result(self, batch_signature):
        with self._condition:
            # This method calculates the BatchExecutionResult on the fly,
            # where only the TxnExecutionResults are cached, instead
            # of BatchExecutionResults, as in the SerialScheduler
            batch = self._batches_by_id[batch_signature]

            if not self._is_valid_batch(batch):
                return BatchExecutionResult(is_valid=False, state_hash=None)

            state_hash = None
            if self._is_explicit_request_for_state_root(batch_signature):
                contexts = self._get_contexts_for_squash(batch_signature)
                state_hash = self._squash(self._first_state_hash,
                                          contexts,
                                          persist=False,
                                          clean_up=False)
                if self._is_state_hash_correct(state_hash, batch_signature):
                    self._squash(self._first_state_hash,
                                 contexts,
                                 persist=True,
                                 clean_up=True)
                else:
                    self._squash(self._first_state_hash,
                                 contexts,
                                 persist=False,
                                 clean_up=True)
            elif self._is_implicit_request_for_state_root(batch_signature):
                contexts = self._get_contexts_for_squash(batch_signature)
                state_hash = self._squash(self._first_state_hash,
                                          contexts,
                                          persist=self._always_persist,
                                          clean_up=True)
            return BatchExecutionResult(is_valid=True, state_hash=state_hash)
    def set_transaction_execution_result(self,
                                         txn_signature,
                                         is_valid,
                                         context_id,
                                         state_changes=None,
                                         events=None,
                                         data=None,
                                         error_message="",
                                         error_data=b""):
        with self._condition:
            if (self._in_progress_transaction is None
                    or self._in_progress_transaction != txn_signature):
                LOGGER.debug('Received result for %s, but was unscheduled',
                             txn_signature)
                return

            self._in_progress_transaction = None

            if txn_signature not in self._txn_to_batch:
                raise ValueError(
                    "transaction not in any batches: {}".format(txn_signature))

            if txn_signature not in self._txn_results:
                self._txn_results[txn_signature] = TxnExecutionResult(
                    signature=txn_signature,
                    is_valid=is_valid,
                    context_id=context_id if is_valid else None,
                    state_hash=self._previous_state_hash if is_valid else None,
                    state_changes=state_changes,
                    events=events,
                    data=data,
                    error_message=error_message,
                    error_data=error_data)

            batch_signature = self._txn_to_batch[txn_signature]
            if is_valid:
                self._previous_context_id = context_id

            else:
                # txn is invalid, preemptively fail the batch
                self._batch_statuses[batch_signature] = \
                    BatchExecutionResult(is_valid=False, state_hash=None)
            if txn_signature in self._last_in_batch:
                if batch_signature not in self._batch_statuses:
                    # because of the else clause above, txn is valid here
                    self._previous_valid_batch_c_id = self._previous_context_id
                    state_hash = self._calculate_state_root_if_required(
                        batch_id=batch_signature)
                    self._batch_statuses[batch_signature] = \
                        BatchExecutionResult(is_valid=True,
                                             state_hash=state_hash)
                else:
                    self._previous_context_id = self._previous_valid_batch_c_id

            self._condition.notify_all()
Example #4
0
    def _process_batches(self, yaml_batches, priv_key, pub_key):
        batches = []
        b_results = {}
        for batch in yaml_batches:
            batch_state_root = None
            if self._contains_and_not_none('state_hash', batch):
                batch_state_root = batch['state_hash']

            txn_processing_result = self._process_txns(
                batch=batch,
                previous_batch_results=b_results.copy(),
                priv_key=priv_key,
                pub_key=pub_key)
            txns, batch_is_valid = txn_processing_result
            batch_real = create_batch(
                transactions=txns,
                private_key=priv_key,
                public_key=pub_key)
            for txn in txns:
                txn_id = txn.header_signature
                batch_id = batch_real.header_signature
                self._batch_id_by_txn_id[txn_id] = batch_id

            b_results[batch_real.header_signature] = BatchExecutionResult(
                is_valid=batch_is_valid,
                state_hash=batch_state_root)
            batches.append(batch_real)
        return batches, b_results
Example #5
0
    def _process_batches(self, yaml_batches, priv_key, pub_key):
        batches = []
        batches_waiting = []
        b_results = {}
        for batch in yaml_batches:
            batch_state_root = None
            batch_dict = None
            if self._contains_and_not_none('state_hash', batch):
                batch_state_root = batch['state_hash']

            if 'state_hash' in batch:  # here we don't care if it is None
                batch_dict = copy.copy(batch)
                del batch['state_hash']

            txn_processing_result = self._process_txns(batch=batch,
                                                       priv_key=priv_key,
                                                       pub_key=pub_key)
            if txn_processing_result is None:
                key = self._unique_integer_key()
                batches.append(key)
                waiting_batch = UnProcessedBatchInfo(
                    batch=batch_dict if batch_dict is not None else batch,
                    key=key)
                batches_waiting.append(waiting_batch)
            else:
                txns, batch_is_valid = txn_processing_result
                batch_real = create_batch(transactions=txns,
                                          private_key=priv_key,
                                          public_key=pub_key)
                b_results[batch_real.header_signature] = BatchExecutionResult(
                    is_valid=batch_is_valid, state_hash=batch_state_root)
                batches.append(batch_real)
        return batches, b_results, batches_waiting
Example #6
0
    def _process_prev_batches(self,
                              unprocessed_batches,
                              priv_key,
                              pub_key,
                              strip_deps=False):
        batches = []
        batches_waiting = []
        b_results = {}
        for batch_info in unprocessed_batches:
            batch = batch_info.batch
            key = batch_info.key
            batch_state_root = None
            if self._contains_and_not_none('state_hash', batch):
                batch_state_root = batch['state_hash']
            if 'state_hash' in batch:  # here we don't care if it is None
                del batch['state_hash']

            txn_processing_result = self._process_txns(batch=batch,
                                                       priv_key=priv_key,
                                                       pub_key=pub_key,
                                                       strip_deps=strip_deps)
            if txn_processing_result is None:
                batches_waiting.append(batch_info)

            else:
                txns, batch_is_valid = txn_processing_result
                batch_real = create_batch(transactions=txns,
                                          private_key=priv_key,
                                          public_key=pub_key)
                b_results[batch_real.header_signature] = BatchExecutionResult(
                    is_valid=batch_is_valid, state_hash=batch_state_root)
                batches.append((batch_real, key))
        return batches, b_results, batches_waiting
Example #7
0
 def _set_batch_result(self, txn_id, valid, state_hash):
     batch_id = self._txn_to_batch[txn_id]
     self._batch_statuses[batch_id] = BatchExecutionResult(
         is_valid=valid, state_hash=state_hash)
     batch = self._batch_by_id[batch_id]
     for txn in batch.transactions:
         if txn.header_signature not in self._txns_with_results:
             self._txns_with_results.append(txn.header_signature)
Example #8
0
    def set_transaction_execution_result(self, txn_signature, is_valid,
                                         context_id):
        with self._condition:
            if (self._in_progress_transaction is None
                    or self._in_progress_transaction != txn_signature):
                raise ValueError(
                    "transaction not in progress: {}".format(txn_signature))
            self._in_progress_transaction = None

            if txn_signature not in self._txn_to_batch:
                raise ValueError(
                    "transaction not in any batches: {}".format(txn_signature))

            batch_signature = self._txn_to_batch[txn_signature]
            if is_valid:
                self._previous_context_id = context_id

            else:
                # txn is invalid, preemptively fail the batch
                self._batch_statuses[batch_signature] = \
                    BatchExecutionResult(is_valid=is_valid, state_hash=None)
            if txn_signature in self._last_in_batch:
                if batch_signature not in self._batch_statuses:
                    # because of the else clause above, txn is valid here
                    self._previous_valid_batch_c_id = self._previous_context_id
                    state_hash = None
                    required_state_hash = self._required_state_hashes.get(
                        batch_signature)
                    if required_state_hash is not None \
                            or self._last_in_batch[-1] == txn_signature:
                        state_hash = self._compute_merkle_root(
                            required_state_hash)
                    self._batch_statuses[batch_signature] = \
                        BatchExecutionResult(
                            is_valid=is_valid,
                            state_hash=state_hash)
                else:
                    self._previous_context_id = self._previous_valid_batch_c_id

                is_last_batch = \
                    len(self._batch_statuses) == len(self._last_in_batch)

                if self._final and is_last_batch:
                    self._complete = True
            self._condition.notify_all()
Example #9
0
    def get_batch_execution_result(self, batch_signature):
        result = True
        if self.batch_execution_result is None:
            batch = self.batches[batch_signature]
            for txn in batch.transactions:
                if txn.payload == b'BAD':
                    result = False
        else:
            result = self.batch_execution_result

        return BatchExecutionResult(is_valid=result, state_hash='0' * 70)
    def set_transaction_execution_result(self, txn_signature, is_valid,
                                         context_id):
        """the control flow is that on every valid txn a new state root is
        generated. If the txn is invalid the batch status is set,
        if the txn is the last txn in the batch, is valid, and no
         prior txn failed the batch, the
        batch is valid
        """
        with self._condition:
            if (self._in_progress_transaction is None
                    or self._in_progress_transaction != txn_signature):
                raise ValueError("transaction not in progress: {}",
                                 txn_signature)
            self._in_progress_transaction = None

            if txn_signature not in self._txn_to_batch:
                raise ValueError(
                    "transaction not in any batches: {}".format(txn_signature))
            if is_valid:
                # txn is valid, get a new state hash
                state_hash = self._squash(self._last_state_hash, [context_id])
                self._last_state_hash = state_hash
            else:
                # txn is invalid, preemptively fail the batch
                batch_signature = self._txn_to_batch[txn_signature]
                self._batch_statuses[batch_signature] = \
                    BatchExecutionResult(is_valid=is_valid, state_hash=None)
            if txn_signature in self._last_in_batch:
                batch_signature = self._txn_to_batch[txn_signature]
                if batch_signature not in self._batch_statuses:
                    # because of the else clause above, txn is valid here
                    self._batch_statuses[batch_signature] = \
                        BatchExecutionResult(
                            is_valid=is_valid,
                            state_hash=self._last_state_hash)

                is_last_batch = \
                    len(self._batch_statuses) == len(self._last_in_batch)
                if self._final and is_last_batch:
                    self._complete = True
            self._condition.notify_all()
    def _set_batch_result(self, txn_id, valid, state_hash):
        if txn_id not in self._txn_to_batch:
            # An incomplete transaction in progress will have been removed
            return

        batch_id = self._txn_to_batch[txn_id]
        self._batch_statuses[batch_id] = BatchExecutionResult(
            is_valid=valid, state_hash=state_hash)
        batch = self._batch_by_id[batch_id].batch
        for txn in batch.transactions:
            if txn.header_signature not in self._txn_results:
                self._txn_results[txn.header_signature] = TxnExecutionResult(
                    txn.header_signature, is_valid=False)
Example #12
0
    def set_transaction_execution_result(self, txn_signature, is_valid,
                                         context_id):
        with self._condition:
            if (self._in_progress_transaction is None
                    or self._in_progress_transaction != txn_signature):
                raise ValueError(
                    "transaction not in progress: {}".format(txn_signature))
            self._in_progress_transaction = None

            if txn_signature not in self._txn_to_batch:
                raise ValueError(
                    "transaction not in any batches: {}".format(txn_signature))

            if txn_signature not in self._txns_with_results:
                self._txns_with_results.append(txn_signature)

            batch_signature = self._txn_to_batch[txn_signature]
            if is_valid:
                self._previous_context_id = context_id

            else:
                # txn is invalid, preemptively fail the batch
                self._batch_statuses[batch_signature] = \
                    BatchExecutionResult(is_valid=False, state_hash=None)
            if txn_signature in self._last_in_batch:
                if batch_signature not in self._batch_statuses:
                    # because of the else clause above, txn is valid here
                    self._previous_valid_batch_c_id = self._previous_context_id
                    state_hash = self._calculate_state_root_if_required(
                        batch_id=batch_signature)
                    self._batch_statuses[batch_signature] = \
                        BatchExecutionResult(is_valid=True,
                                             state_hash=state_hash)
                else:
                    self._previous_context_id = self._previous_valid_batch_c_id

            self._condition.notify_all()
Example #13
0
    def get_batch_execution_result(self, batch_signature):

        return BatchExecutionResult(is_valid=True, state_hash="0000000000")
    def get_batch_execution_result(self, batch_signature):
        with self._condition:
            # This method calculates the BatchExecutionResult on the fly,
            # where only the TxnExecutionResults are cached, instead
            # of BatchExecutionResults, as in the SerialScheduler
            if batch_signature not in self._batches_by_id:
                return None

            batch = self._batches_by_id[batch_signature].batch

            if not self._is_valid_batch(batch):
                return BatchExecutionResult(is_valid=False, state_hash=None)

            state_hash = None
            try:
                if self._is_explicit_request_for_state_root(batch_signature):
                    contexts = self._get_contexts_for_squash(batch_signature)
                    state_hash, updates, deletes = self._squash(
                        self._first_state_hash,
                        contexts,
                        persist=False,
                        clean_up=False)
                    # save recomputing context
                    self._state_recompute_context['updates'] = updates
                    self._state_recompute_context['deletes'] = deletes
                    LOGGER.debug(
                        "get batch=%s execution_result:explicit state_hash=%s context=%s",
                        batch_signature[:8], state_hash[:8],
                        self._state_recompute_context)
                    if self._is_state_hash_correct(state_hash,
                                                   batch_signature):
                        LOGGER.debug(
                            "get batch=%s execution_result: state hash correct",
                            batch_signature[:8])
                        self._squash(self._first_state_hash,
                                     contexts,
                                     persist=True,
                                     clean_up=True)
                    else:
                        self._squash(self._first_state_hash,
                                     contexts,
                                     persist=False,
                                     clean_up=True)
                elif self._is_implicit_request_for_state_root(batch_signature):
                    contexts = self._get_contexts_for_squash(batch_signature)
                    LOGGER.debug(
                        "get batch=%s execution_result:implicit contexts=%s",
                        batch_signature[:8], contexts)

                    state_hash, updates, deletes = self._squash(
                        self._first_state_hash,
                        contexts,
                        persist=self._always_persist,
                        clean_up=True)
                    self._state_recompute_context['updates'] = updates
                    self._state_recompute_context['deletes'] = deletes
                    LOGGER.debug(
                        "get batch=%s execution_result:implicit state_hash=%s",
                        batch_signature[:8], state_hash[:8])

            except _UnscheduledTransactionError:
                return None

            return BatchExecutionResult(is_valid=True, state_hash=state_hash)