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()
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
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
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
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)
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()
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)
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()
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)