def next_transaction(self): with self._condition: if self._in_progress_transaction is not None: return None txn = None while txn is None: try: txn = self._txn_queue.get() except EmptyQueue: if self._final: raise StopIteration() return None # Handle this transaction being invalid based on a # dependency. if any( self._dep_is_known(d) and self._in_invalid_batch(d) for d in self._get_dependencies(txn)): self._set_batch_result(txn.header_signature, False, None) self._check_change_last_good_context_id(txn=txn) txn = None continue # Handle fail fast. if self._in_invalid_batch(txn.header_signature): self._handle_fail_fast(txn) txn = None self._in_progress_transaction = txn.header_signature base_contexts = [] if self._previous_context_id is None \ else [self._previous_context_id] txn_info = TxnInformation(txn=txn, state_hash=self._previous_state_hash, base_context_ids=base_contexts) self._scheduled_transactions.append(txn_info) return txn_info
def next_transaction(self): with self._condition: if self._in_progress_transaction is not None: return None txn = None try: while txn is None: txn = self._txn_queue.get(block=False) # Handle this transaction being invalid based on a # dependency. if any( self._dep_is_known(d) and self._dep_is_not_valid(d) for d in self._get_dependencies(txn)): self._set_batch_result(txn.header_signature, False, None) txn = None except queue.Empty: return None self._in_progress_transaction = txn.header_signature base_contexts = [] if self._previous_context_id is None \ else [self._previous_context_id] txn_info = TxnInformation(txn=txn, state_hash=self._previous_state_hash, base_context_ids=base_contexts) self._scheduled_transactions.append(txn_info) return txn_info
def next_transaction(self): with self._condition: # We return the next transaction which hasn't been scheduled and # is not blocked by a dependency. next_txn = None no_longer_available = [] for txn_id, txn in self._txns_available.items(): if (self._has_predecessors(txn_id) or self._is_outstanding(txn_id)): continue header = TransactionHeader() header.ParseFromString(txn.header) deps = tuple(header.dependencies) if self._dependency_not_processed(deps): continue if self._txn_failed_by_dep(deps): no_longer_available.append(txn_id) self._txn_results[txn_id] = \ TxnExecutionResult( signature=txn_id, is_valid=False, context_id=None, state_hash=None) continue if not self._txn_is_in_valid_batch(txn_id) and \ self._can_fail_fast(txn_id): self._txn_results[txn_id] = \ TxnExecutionResult( signature=txn_id, is_valid=False, context_id=None, state_hash=None) no_longer_available.append(txn_id) continue next_txn = txn break for txn_id in no_longer_available: del self._txns_available[txn_id] if next_txn is not None: bases = self._get_initial_state_for_transaction(next_txn) info = TxnInformation( txn=next_txn, state_hash=self._first_state_hash, base_context_ids=bases) self._scheduled.append(next_txn.header_signature) del self._txns_available[next_txn.header_signature] self._scheduled_txn_info[next_txn.header_signature] = info return info return None
def next_transaction(self): with self._condition: # We return the next transaction which hasn't been scheduled and # is not blocked by a dependency. next_txn = None for txn in self._unscheduled_transactions(): if not self._has_predecessors(txn) and \ not self._is_outstanding(txn) and \ not self._dependency_not_processed(txn): if self._txn_failed_by_dep(txn): self._txn_results[txn.header_signature] = \ TransactionExecutionResult(False, None, None) continue next_txn = txn break if next_txn is not None: bases = self._get_initial_state_for_transaction(next_txn) info = TxnInformation(txn=next_txn, state_hash=self._first_state_hash, base_context_ids=bases) self._scheduled.append(next_txn.header_signature) self._scheduled_txn_info[next_txn.header_signature] = info return info return None
def next_transaction(self): with self._condition: # We return the next transaction which hasn't been scheduled and # is not blocked by a dependency. next_txn = None for txn in self._unscheduled_transactions(): if not self._has_predecessors(txn) and \ not self._is_outstanding(txn) and \ not self._dependency_not_processed(txn): if self._txn_failed_by_dep(txn): self._txns_available.remove(txn) self._txn_results[txn.header_signature] = \ TxnExecutionResult( signature=txn.header_signature, is_valid=False, context_id=None, state_hash=None) continue txn_id = txn.header_signature if not self._txn_is_in_valid_batch( txn_id) and self._can_fail_fast(txn_id): self._txn_results[ txn.header_signature] = TxnExecutionResult( False, None, None) self._txns_available.remove(txn) continue next_txn = txn break if next_txn is not None: bases = self._get_initial_state_for_transaction(next_txn) # """ for DAG self._first_state_hash can be changed real_state_hash and set this state for all transaction into this block so we should update _first_state_hash only for first computing batch into this block """ if not self._is_first_state_hash_updated: real_state_hash = self._merkle_root( ) if self._merkle_root else '' LOGGER.debug( 'next_transaction: real_state_hash=%s bases=%s', real_state_hash[:8], bases) self._first_state_hash = real_state_hash self._is_first_state_hash_updated = True LOGGER.debug('next_transaction: tnx=%s STATE=%s\n', next_txn.header_signature[:8], self._first_state_hash[:8]) info = TxnInformation(txn=next_txn, state_hash=self._first_state_hash, base_context_ids=bases) self._scheduled.append(next_txn.header_signature) self._txns_available.remove(next_txn) self._scheduled_txn_info[next_txn.header_signature] = info return info return None
def next_transaction(self): with self._condition: if self._in_progress_transaction is not None: return None try: txn = self._txn_queue.get(block=False) except queue.Empty: return None self._in_progress_transaction = txn.header_signature txn_info = TxnInformation(txn, self._last_state_hash) self._scheduled_transactions.append(txn_info) return txn_info
def next_transaction(self): with self._condition: if self._in_progress_transaction is not None: return None try: txn = self._txn_queue.get(block=False) except queue.Empty: return None self._in_progress_transaction = txn.header_signature base_contexts = [] if self._previous_context_id is None \ else [self._previous_context_id] txn_info = TxnInformation(txn=txn, state_hash=self._previous_state_hash, base_context_ids=base_contexts) self._scheduled_transactions.append(txn_info) return txn_info
def next_transaction(self): with self._condition: if self._in_progress_transaction is not None: return None txn = None while txn is None: try: txn = self._txn_queue.popleft() except IndexError: if self._final: self._condition.notify_all() raise StopIteration() return None # Handle this transaction being invalid based on a # dependency. if any( self._dep_is_known(d) and self._in_invalid_batch(d) for d in self._get_dependencies(txn)): self._set_batch_result(txn.header_signature, False, None) self._check_change_last_good_context_id(txn=txn) txn = None continue # Handle fail fast. if self._in_invalid_batch(txn.header_signature): self._handle_fail_fast(txn) txn = None self._in_progress_transaction = txn.header_signature base_contexts = [] if self._previous_context_id is None else [ self._previous_context_id ] # for DAG we should use real merkle root real_state_hash = self._merkle_root() if self._merkle_root else '' LOGGER.debug('next_transaction: tnx=%s PREV STATE=%s~%s \n', txn.header_signature[:8], self._previous_state_hash[:8], real_state_hash[:8]) txn_info = TxnInformation( txn=txn, state_hash=self._previous_state_hash if real_state_hash == '' else real_state_hash, base_context_ids=base_contexts) self._scheduled_transactions.append(txn_info) return txn_info