protected override Task WorkAction() { using (updatedTracker.TryUpdate(staleAction: NotifyWork)) { try { foreach (var pathElement in unconfirmedTxesBuilder.Chain.NavigateTowards(() => chainStateWorker.CurrentChain)) { // cooperative loop ThrowIfCancelled(); // get block and metadata for next link in blockchain var direction = pathElement.Item1; var chainedHeader = pathElement.Item2; IEnumerator <BlockTx> blockTxes; if (!coreStorage.TryReadBlockTransactions(chainedHeader.Hash, out blockTxes)) { BlockMissed?.Invoke(this, chainedHeader.Hash); break; } if (direction > 0) { unconfirmedTxesBuilder.AddBlock(chainedHeader, blockTxes.UsingAsEnumerable()); } else if (direction < 0) { unconfirmedTxesBuilder.RollbackBlock(chainedHeader, blockTxes.UsingAsEnumerable()); } else { throw new InvalidOperationException(); } currentChain = new Lazy <Chain>(() => unconfirmedTxesBuilder.Chain); OnChanged?.Invoke(this, EventArgs.Empty); } } catch (OperationCanceledException) { } catch (AggregateException ex) { foreach (var innerException in ex.Flatten().InnerExceptions) { HandleException(innerException); } } catch (Exception ex) { HandleException(ex); } } return(Task.CompletedTask); }
private void HandleException(Exception ex) { var missingException = ex as MissingDataException; if (missingException != null) { var missingBlockHash = (UInt256)missingException.Key; BlockMissed?.Invoke(this, missingBlockHash); } else { logger.Warn(ex, "UnconfirmedTxesWorker exception."); } }
private void HandleBlockMissed(UInt256 blockHash) { BlockMissed?.Invoke(blockHash); }