public BlockRequestWorker(Logger logger, WorkerConfig workerConfig, LocalClient localClient, CoreDaemon blockchainDaemon, ChainedHeaderCache chainedHeaderCache, BlockCache blockCache) : base("BlockRequestWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime, logger) { this.logger = logger; this.localClient = localClient; this.blockchainDaemon = blockchainDaemon; this.chainedHeaderCache = chainedHeaderCache; this.blockCache = blockCache; this.allBlockRequests = new ConcurrentDictionary <UInt256, DateTime>(); this.blockRequestsByPeer = new ConcurrentDictionary <IPEndPoint, ConcurrentDictionary <UInt256, DateTime> >(); this.missingBlockQueue = new SortedList <int, ChainedHeader>(); this.localClient.OnBlock += HandleBlock; this.blockchainDaemon.OnChainStateChanged += HandleChainStateChanged; this.blockchainDaemon.OnTargetChainChanged += HandleTargetChainChanged; this.blockCache.OnMissing += HandleBlockMissing; this.blockRequestDurationMeasure = new DurationMeasure(sampleCutoff: TimeSpan.FromMinutes(5)); this.blockDownloadRateMeasure = new RateMeasure(); this.duplicateBlockDownloadRateMeasure = new RateMeasure(); this.targetChainLookAhead = 1; this.criticalTargetChainLookAhead = 1; this.flushWorker = new WorkerMethod("BlockRequestWorker.FlushWorker", FlushWorkerMethod, initialNotify: true, minIdleTime: TimeSpan.Zero, maxIdleTime: TimeSpan.MaxValue, logger: this.logger); this.flushQueue = new ConcurrentQueue <Tuple <RemoteNode, Block> >(); }
public BlockRequestWorker(WorkerConfig workerConfig, Logger logger, LocalClient localClient, CoreDaemon coreDaemon) : base("BlockRequestWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime, logger) { this.logger = logger; this.localClient = localClient; this.coreDaemon = coreDaemon; this.coreStorage = coreDaemon.CoreStorage; this.allBlockRequests = new ConcurrentDictionary <UInt256, BlockRequest>(); this.blockRequestsByPeer = new ConcurrentDictionary <Peer, ConcurrentDictionary <UInt256, DateTime> >(); this.missedBlockRequests = new ConcurrentDictionary <UInt256, BlockRequest>(); this.localClient.OnBlock += HandleBlock; this.coreDaemon.OnChainStateChanged += HandleChainStateChanged; this.coreDaemon.OnTargetChainChanged += HandleTargetChainChanged; this.coreStorage.BlockTxesMissed += HandleBlockTxesMissed; this.coreDaemon.BlockMissed += HandleBlockMissed; this.blockRequestDurationMeasure = new DurationMeasure(sampleCutoff: TimeSpan.FromMinutes(5)); this.blockDownloadRateMeasure = new RateMeasure(); this.duplicateBlockDownloadCountMeasure = new CountMeasure(TimeSpan.FromSeconds(30)); this.targetChainQueue = new List <ChainedHeader>(); this.targetChainQueueIndex = 0; this.targetChainLookAhead = 1; this.flushWorker = new WorkerMethod("BlockRequestWorker.FlushWorker", FlushWorkerMethod, initialNotify: true, minIdleTime: TimeSpan.Zero, maxIdleTime: TimeSpan.MaxValue, logger: this.logger); this.flushQueue = new ConcurrentQueue <FlushBlock>(); this.flushBlocks = new ConcurrentSet <UInt256>(); this.diagnosticWorker = new WorkerMethod("BlockRequestWorker.DiagnosticWorker", DiagnosticWorkerMethod, initialNotify: true, minIdleTime: TimeSpan.FromSeconds(10), maxIdleTime: TimeSpan.FromSeconds(10), logger: this.logger); }
private void StatsWorker(WorkerMethod instance) { this.logger.Info( "UNCONNECTED: {0,3}, PENDING: {1,3}, CONNECTED: {2,3}, BAD: {3,3}, INCOMING: {4,3}, MESSAGES/SEC: {5,6:#,##0}".Format2( /*0*/ this.peerWorker.UnconnectedPeersCount, /*1*/ this.peerWorker.PendingPeers.Count, /*2*/ this.peerWorker.ConnectedPeers.Count, /*3*/ this.peerWorker.BadPeers.Count, /*4*/ this.peerWorker.IncomingCount, /*5*/ this.messageRateMeasure.GetAverage(TimeSpan.FromSeconds(1)))); }
private Task GcWorker(WorkerMethod instance) { logger.Info( string.Join("\n", new string('-', 80), $"GC Memory: {(float)GC.GetTotalMemory(false) / 1.MILLION(),10:N2} MB", $"Process Memory: {(float)Process.GetCurrentProcess().PrivateMemorySize64 / 1.MILLION(),10:N2} MB", new string('-', 80) )); return(Task.CompletedTask); }
public CoreDaemon(ICoreRules rules, IStorageManager storageManager) { this.rules = rules; this.storageManager = storageManager; coreStorage = new CoreStorage(storageManager); // create chain state builder chainStateBuilder = new ChainStateBuilder(this.rules, coreStorage, this.storageManager); // create unconfirmed txes builder unconfirmedTxesBuilder = new UnconfirmedTxesBuilder(this, coreStorage, this.storageManager); // create workers targetChainWorker = new TargetChainWorker( new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMilliseconds(0), maxIdleTime: TimeSpan.FromSeconds(30)), ChainParams, coreStorage); chainStateWorker = new ChainStateWorker( new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMilliseconds(0), maxIdleTime: TimeSpan.FromSeconds(5)), targetChainWorker, chainStateBuilder, this.rules, coreStorage); unconfirmedTxesWorker = new UnconfirmedTxesWorker( new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMilliseconds(0), maxIdleTime: TimeSpan.FromSeconds(5)), chainStateWorker, unconfirmedTxesBuilder, coreStorage); pruningWorker = new PruningWorker( new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromSeconds(0), maxIdleTime: TimeSpan.FromMinutes(5)), this, this.storageManager, chainStateWorker); defragWorker = new DefragWorker( new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMinutes(5), maxIdleTime: TimeSpan.FromMinutes(5)), this.storageManager); gcWorker = new WorkerMethod("GC Worker", GcWorker, initialNotify: true, minIdleTime: TimeSpan.FromMinutes(5), maxIdleTime: TimeSpan.FromMinutes(5)); utxoScanWorker = new WorkerMethod("UTXO Scan Worker", UtxoScanWorker, initialNotify: true, minIdleTime: TimeSpan.FromSeconds(60), maxIdleTime: TimeSpan.FromSeconds(60)); statsWorker = new StatsWorker( new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMinutes(0), maxIdleTime: TimeSpan.MaxValue), this); // wire events chainStateWorker.BlockMissed += HandleBlockMissed; targetChainWorker.OnTargetChainChanged += HandleTargetChainChanged; chainStateWorker.OnChainStateChanged += HandleChainStateChanged; pruningWorker.OnWorkFinished += defragWorker.NotifyWork; unconfirmedTxesBuilder.UnconfirmedTxAdded += RaiseUnconfirmedTxAdded; unconfirmedTxesBuilder.TxesConfirmed += RaiseTxesConfirmed; unconfirmedTxesBuilder.TxesUnconfirmed += RaiseTxesUnconfirmed; }
public LocalClient(ChainType type, IKernel kernel, CoreDaemon coreDaemon, INetworkPeerStorage networkPeerStorage) { this.shutdownToken = new CancellationTokenSource(); this.type = type; this.kernel = kernel; this.coreDaemon = coreDaemon; this.chainParams = coreDaemon.ChainParams; this.coreStorage = coreDaemon.CoreStorage; this.networkPeerStorage = networkPeerStorage; this.messageRateMeasure = new RateMeasure(); this.headersRequestWorker = new HeadersRequestWorker( new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMilliseconds(50), maxIdleTime: TimeSpan.FromSeconds(5)), this, this.coreDaemon); this.blockRequestWorker = new BlockRequestWorker( new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMilliseconds(50), maxIdleTime: TimeSpan.FromSeconds(30)), this, this.coreDaemon); this.peerWorker = new PeerWorker( new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromSeconds(1), maxIdleTime: TimeSpan.FromSeconds(1)), this, this.coreDaemon, this.headersRequestWorker); this.listenWorker = new ListenWorker(this, this.peerWorker); this.statsWorker = new WorkerMethod("LocalClient.StatsWorker", StatsWorker, true, TimeSpan.FromSeconds(5), TimeSpan.FromMinutes(5)); this.peerWorker.PeerHandshakeCompleted += HandlePeerHandshakeCompleted; this.peerWorker.PeerDisconnected += HandlePeerDisconnected; this.blockRequestWorker.OnBlockFlushed += HandleBlockFlushed; switch (this.Type) { case ChainType.MainNet: Messaging.Port = 8333; Messaging.Magic = Messaging.MAGIC_MAIN; break; case ChainType.TestNet3: Messaging.Port = 18333; Messaging.Magic = Messaging.MAGIC_TESTNET3; break; case ChainType.Regtest: Messaging.Port = 18444; Messaging.Magic = Messaging.MAGIC_COMPARISON_TOOL; break; } }
private Task StatsWorker(WorkerMethod instance) { logger.Info(string.Join(", ", $"UNCONNECTED: {this.peerWorker.UnconnectedPeersCount,3}", $"PENDING: {this.peerWorker.PendingPeers.Count,3}", $"CONNECTED: {this.peerWorker.ConnectedPeers.Count,3}", $"BAD: {this.peerWorker.BadPeers.Count,3}", $"INCOMING: {this.peerWorker.IncomingCount,3}", $"MESSAGES/SEC: {this.messageRateMeasure.GetAverage(),6:N0}" )); return(Task.CompletedTask); }
public MainWindowViewModel(IKernel kernel, WalletMonitor walletMonitor = null) { this.kernel = kernel; coreDaemon = kernel.Get <CoreDaemon>(); coreStorage = coreDaemon.CoreStorage; localClient = kernel.Get <LocalClient>(); this.walletMonitor = walletMonitor; startTime = DateTimeOffset.Now; runningTimeTimer = new DispatcherTimer(); runningTimeTimer.Tick += (sender, e) => { var runningTime = (DateTimeOffset.Now - startTime); RunningTime = $"{Math.Floor(runningTime.TotalHours):#,#00}:{runningTime:mm':'ss}"; }; runningTimeTimer.Interval = TimeSpan.FromMilliseconds(100); runningTimeTimer.Start(); WinningBlockchainHeight = -1; CurrentBlockchainHeight = -1; DownloadedBlockCount = -1; WalletHeight = -1; updateWorker = new WorkerMethod("", _ => { WinningBlockchainHeight = coreDaemon.TargetChainHeight; CurrentBlockchainHeight = coreDaemon.CurrentChain.Height; DownloadedBlockCount = coreStorage.BlockWithTxesCount; BlockRate = coreDaemon.GetBlockRate(); TransactionRate = coreDaemon.GetTxRate(); InputRate = coreDaemon.GetInputRate(); BlockDownloadRate = localClient.GetBlockDownloadRate(); DuplicateBlockDownloadCount = localClient.GetDuplicateBlockDownloadCount(); BlockMissCount = localClient.GetBlockMissCount(); if (walletMonitor != null) { WalletHeight = this.walletMonitor.WalletHeight; WalletEntriesCount = this.walletMonitor.EntriesCount; BitBalance = this.walletMonitor.BitBalance; BtcBalance = this.walletMonitor.BtcBalance; } return(Task.CompletedTask); }, initialNotify: true, minIdleTime: TimeSpan.FromSeconds(1), maxIdleTime: TimeSpan.FromSeconds(1)); updateWorker.Start(); }
public LocalClient(Logger logger, RulesEnum type, IKernel kernel, IBlockchainRules rules, CoreDaemon coreDaemon, NetworkPeerCache networkPeerCache) { this.shutdownToken = new CancellationTokenSource(); this.logger = logger; this.type = type; this.kernel = kernel; this.rules = rules; this.coreDaemon = coreDaemon; this.coreStorage = coreDaemon.CoreStorage; this.networkPeerCache = networkPeerCache; this.messageRateMeasure = new RateMeasure(); this.peerWorker = new PeerWorker( new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromSeconds(1), maxIdleTime: TimeSpan.FromSeconds(1)), this.logger, this, this.coreDaemon); this.listenWorker = new ListenWorker(this.logger, this, this.peerWorker); this.headersRequestWorker = new HeadersRequestWorker( new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMilliseconds(50), maxIdleTime: TimeSpan.FromSeconds(5)), this.logger, this, this.coreDaemon); this.blockRequestWorker = new BlockRequestWorker( new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMilliseconds(50), maxIdleTime: TimeSpan.FromSeconds(30)), this.logger, this, this.coreDaemon); this.statsWorker = new WorkerMethod("LocalClient.StatsWorker", StatsWorker, true, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(30), this.logger); this.peerWorker.PeerConnected += HandlePeerConnected; this.peerWorker.PeerDisconnected += HandlePeerDisconnected; switch (this.Type) { case RulesEnum.MainNet: Messaging.Port = 8333; Messaging.Magic = Messaging.MAGIC_MAIN; break; case RulesEnum.TestNet3: Messaging.Port = 18333; Messaging.Magic = Messaging.MAGIC_TESTNET3; break; case RulesEnum.ComparisonToolTestNet: Messaging.Port = 18444; Messaging.Magic = Messaging.MAGIC_COMPARISON_TOOL; break; } }
public HeadersRequestWorker(WorkerConfig workerConfig, LocalClient localClient, CoreDaemon coreDaemon) : base("HeadersRequestWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime) { this.localClient = localClient; this.coreDaemon = coreDaemon; this.coreStorage = coreDaemon.CoreStorage; this.headersRequestsByPeer = new ConcurrentDictionary <Peer, DateTimeOffset>(); this.localClient.OnBlockHeaders += HandleBlockHeaders; this.coreDaemon.OnTargetChainChanged += HandleTargetChainChanged; this.flushWorker = new WorkerMethod("HeadersRequestWorker.FlushWorker", FlushWorkerMethod, initialNotify: true, minIdleTime: TimeSpan.Zero, maxIdleTime: TimeSpan.MaxValue); this.flushQueue = new ConcurrentQueue <FlushHeaders>(); }
private void DiagnosticWorkerMethod(WorkerMethod instance) { this.logger.Info(new string('-', 80)); this.logger.Info("allBlockRequests.Count: {0:#,##0}".Format2(this.allBlockRequests.Count)); this.logger.Info("blockRequestsByPeer.InnerCount: {0:#,##0}".Format2(this.blockRequestsByPeer.Sum(x => x.Value.Count))); this.logger.Info("targetChainQueue.Count: {0:#,##0}".Format2(this.targetChainQueue.Count)); this.logger.Info("targetChainQueueIndex: {0:#,##0}".Format2(this.targetChainQueueIndex)); this.logger.Info("targetChainQueueTime: {0}".Format2(this.targetChainQueueTime)); this.logger.Info("blockRequestDurationMeasure: {0}".Format2(this.blockRequestDurationMeasure.GetAverage())); this.logger.Info("blockDownloadRateMeasure: {0}/s".Format2(this.blockDownloadRateMeasure.GetAverage(TimeSpan.FromSeconds(1)))); this.logger.Info("duplicateBlockDownloadCountMeasure: {0}/s".Format2(this.duplicateBlockDownloadCountMeasure.GetCount())); this.logger.Info("targetChainLookAhead: {0}".Format2(this.targetChainLookAhead)); this.logger.Info("flushQueue.Count: {0}".Format2(this.flushQueue.Count)); this.logger.Info("flushBlocks.Count: {0}".Format2(this.flushBlocks.Count)); }
private void FlushWorkerMethod(WorkerMethod instance) { var initalCount = this.flushQueue.Count; var count = 0; FlushBlock flushBlock; while (this.flushQueue.TryDequeue(out flushBlock)) { // cooperative loop this.ThrowIfCancelled(); var peer = flushBlock.Peer; var block = flushBlock.Block; if (this.coreStorage.TryAddBlock(block)) { this.blockDownloadRateMeasure.Tick(); } else { this.duplicateBlockDownloadCountMeasure.Tick(); } this.flushBlocks.Remove(block.Hash); BlockRequest blockRequest; this.allBlockRequests.TryRemove(block.Hash, out blockRequest); DateTime requestTime; ConcurrentDictionary <UInt256, DateTime> peerBlockRequests; if (this.blockRequestsByPeer.TryGetValue(peer, out peerBlockRequests) && peerBlockRequests.TryRemove(block.Hash, out requestTime)) { this.blockRequestDurationMeasure.Tick(DateTime.UtcNow - requestTime); } this.NotifyWork(); count++; if (count > initalCount) { break; } } //this.blockCache.Flush(); }
public HeadersRequestWorker(Logger logger, WorkerConfig workerConfig, LocalClient localClient, CoreDaemon blockchainDaemon, BlockHeaderCache blockHeaderCache) : base("HeadersRequestWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime, logger) { this.logger = logger; this.localClient = localClient; this.blockchainDaemon = blockchainDaemon; this.blockHeaderCache = blockHeaderCache; this.headersRequestsByPeer = new ConcurrentDictionary <IPEndPoint, DateTime>(); this.localClient.OnBlockHeaders += HandleBlockHeaders; this.blockchainDaemon.OnTargetChainChanged += HandleTargetChainChanged; this.flushWorker = new WorkerMethod("HeadersRequestWorker.FlushWorker", FlushWorkerMethod, initialNotify: true, minIdleTime: TimeSpan.Zero, maxIdleTime: TimeSpan.MaxValue, logger: this.logger); this.flushQueue = new ConcurrentQueue <Tuple <RemoteNode, IImmutableList <BlockHeader> > >(); }
private Task DiagnosticWorkerMethod(WorkerMethod instance) { logger.Info(new string('-', 80)); logger.Info($"allBlockRequests.Count: {this.allBlockRequests.Count:N0}"); logger.Info($"blockRequestsByPeer.InnerCount: {this.blockRequestsByPeer.Sum(x => x.Value.Count):N0}"); logger.Info($"targetChainQueue.Count: {this.targetChainQueue.Count:N0}"); logger.Info($"targetChainQueueIndex: {this.targetChainQueueIndex:N0}"); logger.Info($"blockRequestDurationMeasure: {this.blockRequestDurationMeasure.GetAverage()}"); logger.Info($"blockDownloadRateMeasure: {this.blockDownloadRateMeasure.GetAverage()}/s"); logger.Info($"duplicateBlockDownloadCountMeasure: {this.duplicateBlockDownloadCountMeasure.GetCount()}/s"); logger.Info($"targetChainLookAhead: {this.targetChainLookAhead}"); logger.Info($"flushQueue.Count: {this.flushQueue.Count}"); logger.Info($"flushBlocks.Count: {this.flushBlocks.Count}"); return(Task.CompletedTask); }
public LocalClient(Logger logger, RulesEnum type, IKernel kernel, IBlockchainRules rules, CoreDaemon blockchainDaemon, BlockHeaderCache blockHeaderCache, ChainedHeaderCache chainedHeaderCache, TransactionCache transactionCache, BlockCache blockCache, NetworkPeerCache networkPeerCache) { this.shutdownToken = new CancellationTokenSource(); this.logger = logger; this.type = type; this.kernel = kernel; this.rules = rules; this.blockchainDaemon = blockchainDaemon; this.blockHeaderCache = blockHeaderCache; this.chainedHeaderCache = chainedHeaderCache; this.transactionCache = transactionCache; this.blockCache = blockCache; this.networkPeerCache = networkPeerCache; this.messageRateMeasure = new RateMeasure(); this.connectWorker = new WorkerMethod("LocalClient.ConnectWorker", ConnectWorker, true, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), this.logger); this.headersRequestWorker = kernel.Get <HeadersRequestWorker>( new ConstructorArgument("workerConfig", new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMilliseconds(50), maxIdleTime: TimeSpan.FromSeconds(30))), new ConstructorArgument("localClient", this)); this.blockRequestWorker = kernel.Get <BlockRequestWorker>( new ConstructorArgument("workerConfig", new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMilliseconds(50), maxIdleTime: TimeSpan.FromSeconds(30))), new ConstructorArgument("localClient", this)); this.statsWorker = new WorkerMethod("LocalClient.StatsWorker", StatsWorker, true, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(30), this.logger); switch (this.Type) { case RulesEnum.MainNet: Messaging.Port = 8333; Messaging.Magic = Messaging.MAGIC_MAIN; break; case RulesEnum.TestNet3: Messaging.Port = 18333; Messaging.Magic = Messaging.MAGIC_TESTNET3; break; case RulesEnum.ComparisonToolTestNet: Messaging.Port = 18444; Messaging.Magic = Messaging.MAGIC_COMPARISON_TOOL; break; } }
private Task UtxoScanWorker(WorkerMethod instance) { // time taking chain state snapshots var stopwatch = Stopwatch.StartNew(); int chainStateHeight; using (var chainState = GetChainState()) { chainStateHeight = chainState.Chain.Height; } stopwatch.Stop(); logger.Info($"GetChainState at {chainStateHeight:N0}: {stopwatch.Elapsed.TotalSeconds:N2}s"); // time enumerating chain state snapshots stopwatch = Stopwatch.StartNew(); using (var chainState = GetChainState()) { chainStateHeight = chainState.Chain.Height; chainState.ReadUnspentTransactions().Count(); } stopwatch.Stop(); logger.Info($"Enumerate chain state at {chainStateHeight:N0}: {stopwatch.Elapsed.TotalSeconds:N2}s"); //using (var chainStateLocal = this.GetChainState()) //{ // new MethodTimer(logger).Time("UTXO Commitment: {0:N0}".Format2(chainStateLocal.UnspentTxCount), () => // { // using (var utxoStream = new UtxoStream(logger, chainStateLocal.ReadUnspentTransactions())) // { // var utxoHash = SHA256Pool.ComputeHash(utxoStream); // logger.Info("UXO Commitment Hash: {0}".Format2(utxoHash.ToHexNumberString())); // } // }); // //new MethodTimer().Time("Full UTXO Scan: {0:N0}".Format2(chainStateLocal.Utxo.TransactionCount), () => // //{ // // foreach (var output in chainStateLocal.Utxo.GetUnspentTransactions()) // // { // // } // //}); //} return(Task.CompletedTask); }
private void FlushWorkerMethod(WorkerMethod instance) { FlushHeaders flushHeaders; while (this.flushQueue.TryDequeue(out flushHeaders)) { // cooperative loop this.ThrowIfCancelled(); var peer = flushHeaders.Peer; var blockHeaders = flushHeaders.Headers; // chain the downloaded headers this.coreStorage.ChainHeaders(blockHeaders); DateTime ignore; this.headersRequestsByPeer.TryRemove(peer, out ignore); } }
public BlockRequestWorker(WorkerConfig workerConfig, LocalClient localClient, CoreDaemon coreDaemon) : base("BlockRequestWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime) { this.localClient = localClient; this.coreDaemon = coreDaemon; this.coreStorage = coreDaemon.CoreStorage; this.allBlockRequests = new ConcurrentDictionary <UInt256, BlockRequest>(); this.blockRequestsByPeer = new ConcurrentDictionary <Peer, ConcurrentDictionary <UInt256, DateTimeOffset> >(); this.missedBlockRequests = new ConcurrentDictionary <UInt256, BlockRequest>(); this.localClient.OnBlock += HandleBlock; this.coreDaemon.OnChainStateChanged += HandleChainStateChanged; this.coreDaemon.OnTargetChainChanged += HandleTargetChainChanged; this.coreDaemon.BlockMissed += HandleBlockMissed; this.blockRequestDurationMeasure = new DurationMeasure(sampleCutoff: TimeSpan.FromMinutes(5)); this.blockDownloadRateMeasure = new RateMeasure(); this.duplicateBlockDownloadCountMeasure = new CountMeasure(TimeSpan.FromSeconds(30)); this.targetChainQueue = new List <ChainedHeader>(); this.targetChainQueueIndex = 0; this.targetChainLookAhead = 1; this.flushWorker = new ActionBlock <FlushBlock>((Action <FlushBlock>)FlushWorkerMethod, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }); this.flushQueue = new BufferBlock <FlushBlock>(); this.flushBlocks = new ConcurrentSet <UInt256>(); this.flushQueue.LinkTo(this.flushWorker, new DataflowLinkOptions { PropagateCompletion = true }); this.diagnosticWorker = new WorkerMethod("BlockRequestWorker.DiagnosticWorker", DiagnosticWorkerMethod, initialNotify: true, minIdleTime: TimeSpan.FromSeconds(10), maxIdleTime: TimeSpan.FromSeconds(10)); }
public CoreDaemon(Logger logger, IKernel kernel, IBlockchainRules rules, IStorageManager storageManager) { this.logger = logger; this.shutdownToken = new CancellationTokenSource(); this.kernel = kernel; this.rules = rules; this.storageManager = storageManager; this.coreStorage = new CoreStorage(storageManager, logger); // write genesis block out to storage this.coreStorage.AddGenesisBlock(this.rules.GenesisChainedHeader); this.coreStorage.TryAddBlock(this.rules.GenesisBlock); // create chain state builder this.chainStateBuilder = new ChainStateBuilder(this.logger, this.rules, this.coreStorage); // add genesis block to chain state, if needed if (this.chainStateBuilder.Chain.Height < 0) { this.chainStateBuilder.AddBlock(this.rules.GenesisChainedHeader, this.rules.GenesisBlock.Transactions); } // create workers this.targetChainWorker = new TargetChainWorker( new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMilliseconds(50), maxIdleTime: TimeSpan.FromSeconds(30)), this.logger, this.rules, this.coreStorage); this.chainStateWorker = new ChainStateWorker( new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMilliseconds(50), maxIdleTime: TimeSpan.FromSeconds(5)), this.targetChainWorker, this.chainStateBuilder, this.logger, this.rules, this.coreStorage); this.pruningWorker = new PruningWorker( new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromSeconds(60), maxIdleTime: TimeSpan.FromMinutes(15)), this.coreStorage, this.chainStateWorker, this.chainStateBuilder, this.logger, this.rules); this.defragWorker = new DefragWorker( new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMinutes(5), maxIdleTime: TimeSpan.FromMinutes(5)), this.coreStorage, this.logger); // notify defrag worker after pruning this.pruningWorker.OnWorkFinished += this.defragWorker.NotifyWork; this.chainStateWorker.BlockMissed += HandleBlockMissed; this.targetChainWorker.OnTargetChainChanged += () => { var handler = this.OnTargetChainChanged; if (handler != null) { handler(this, EventArgs.Empty); } }; this.chainStateWorker.OnChainStateChanged += () => { this.pruningWorker.NotifyWork(); this.utxoScanWorker.NotifyWork(); var handler = this.OnChainStateChanged; if (handler != null) { handler(this, EventArgs.Empty); } }; this.gcWorker = new WorkerMethod("GC Worker", _ => { this.logger.Info( string.Join("\n", new string('-', 80), "GC Memory: {0,10:#,##0.00} MB", "Process Memory: {1,10:#,##0.00} MB", new string('-', 80) ) .Format2 ( /*0*/ (float)GC.GetTotalMemory(false) / 1.MILLION(), /*1*/ (float)Process.GetCurrentProcess().PrivateMemorySize64 / 1.MILLION() )); }, initialNotify: true, minIdleTime: TimeSpan.FromSeconds(30), maxIdleTime: TimeSpan.FromSeconds(30), logger: this.logger); this.utxoScanWorker = new WorkerMethod("UTXO Scan Worker", _ => { // time taking chain state snapshots var stopwatch = Stopwatch.StartNew(); int chainStateHeight; using (var chainState = this.GetChainState()) { chainStateHeight = chainState.Chain.Height; } stopwatch.Stop(); this.logger.Info("GetChainState at {0:#,##0}: {1:#,##0.00}s".Format2(chainStateHeight, stopwatch.Elapsed.TotalSeconds)); // time enumerating chain state snapshots stopwatch = Stopwatch.StartNew(); using (var chainState = this.GetChainState()) { chainStateHeight = chainState.Chain.Height; chainState.ReadUnspentTransactions().Count(); } stopwatch.Stop(); this.logger.Info("Enumerate chain state at {0:#,##0}: {1:#,##0.00}s".Format2(chainStateHeight, stopwatch.Elapsed.TotalSeconds)); //using (var chainStateLocal = this.GetChainState()) //{ // new MethodTimer(this.logger).Time("UTXO Commitment: {0:#,##0}".Format2(chainStateLocal.UnspentTxCount), () => // { // using (var utxoStream = new UtxoStream(this.logger, chainStateLocal.ReadUnspentTransactions())) // { // var sha256 = new SHA256Managed(); // var utxoHash = sha256.ComputeHash(utxoStream); // this.logger.Info("UXO Commitment Hash: {0}".Format2(utxoHash.ToHexNumberString())); // } // }); // //new MethodTimer().Time("Full UTXO Scan: {0:#,##0}".Format2(chainStateLocal.Utxo.TransactionCount), () => // //{ // // var sha256 = new SHA256Managed(); // // foreach (var output in chainStateLocal.Utxo.GetUnspentTransactions()) // // { // // } // //}); //} }, initialNotify: true, minIdleTime: TimeSpan.FromSeconds(60), maxIdleTime: TimeSpan.FromSeconds(60), logger: this.logger); }
/// <summary> /// Sets up the background worker. /// </summary> /// <remarks> /// The method passed to this constructor can't have any arguments. /// </remarks> /// <param name="p_dlgWorker">The method that will do the work.</param> public BackgroundWorkerProgressDialog(WorkerMethod p_dlgWorker) : this() { m_wkmWorkMethod = p_dlgWorker; }
public static void StartShadowTask(WorkerMethod method) { Thread newThread = new Thread(new ThreadStart(method)); newThread.Start(); }
public CoreDaemon(Logger logger, IKernel kernel, IBlockchainRules rules, BlockHeaderCache blockHeaderCache, ChainedHeaderCache chainedHeaderCache, BlockTxHashesCache blockTxHashesCache, TransactionCache transactionCache, BlockCache blockCache) { this.logger = logger; this.shutdownToken = new CancellationTokenSource(); this.kernel = kernel; this.rules = rules; this.blockHeaderCache = blockHeaderCache; this.chainedHeaderCache = chainedHeaderCache; this.blockTxHashesCache = blockTxHashesCache; this.transactionCache = transactionCache; this.blockCache = blockCache; // write genesis block out to storage this.blockHeaderCache[this.rules.GenesisBlock.Hash] = this.rules.GenesisBlock.Header; this.blockCache[this.rules.GenesisBlock.Hash] = this.rules.GenesisBlock; this.chainedHeaderCache[this.rules.GenesisChainedHeader.Hash] = this.rules.GenesisChainedHeader; // wire up cache events this.blockHeaderCache.OnAddition += OnBlockHeaderAddition; this.blockHeaderCache.OnModification += OnBlockHeaderModification; this.blockCache.OnAddition += OnBlockAddition; this.blockCache.OnModification += OnBlockModification; this.blockTxHashesCache.OnAddition += OnBlockTxHashesAddition; this.blockTxHashesCache.OnModification += OnBlockTxHashesModification; this.chainedHeaderCache.OnAddition += OnChainedHeaderAddition; this.chainedHeaderCache.OnModification += OnChainedHeaderModification; // create chain state builder this.chainStateBuilder = this.kernel.Get <ChainStateBuilder>( new ConstructorArgument("chain", Chain.CreateForGenesisBlock(this.rules.GenesisChainedHeader).ToBuilder()), new ConstructorArgument("parentUtxo", Utxo.CreateForGenesisBlock(this.rules.GenesisBlock.Hash))); this.chainStateLock = new ReaderWriterLockSlim(); // create workers this.chainingWorker = kernel.Get <ChainingWorker>( new ConstructorArgument("workerConfig", new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromSeconds(0), maxIdleTime: TimeSpan.FromSeconds(30)))); this.targetChainWorker = kernel.Get <TargetChainWorker>( new ConstructorArgument("workerConfig", new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromSeconds(0), maxIdleTime: TimeSpan.FromSeconds(30)))); this.chainStateWorker = kernel.Get <ChainStateWorker>( new ConstructorArgument("workerConfig", new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.Zero, maxIdleTime: TimeSpan.FromSeconds(5))), new ConstructorArgument("getTargetChain", (Func <Chain>)(() => this.targetChainWorker.TargetChain)), new ConstructorArgument("targetChainWorker", this.targetChainWorker), new ConstructorArgument("chainStateBuilder", this.chainStateBuilder)); this.targetChainWorker.OnTargetBlockChanged += () => { var handler = this.OnTargetBlockChanged; if (handler != null) { handler(this, EventArgs.Empty); } }; this.targetChainWorker.OnTargetChainChanged += () => { this.chainStateWorker.NotifyWork(); var handler = this.OnTargetChainChanged; if (handler != null) { handler(this, EventArgs.Empty); } }; this.chainStateWorker.OnChainStateChanged += () => { this.utxoScanWorker.NotifyWork(); //TODO once fully synced, this should save off the immutable snapshot immediately //TODO this will allow there to always be an active chain state once synced this.chainStateLock.DoWrite(() => this.chainState = null); var handler = this.OnChainStateChanged; if (handler != null) { handler(this, EventArgs.Empty); } }; this.gcWorker = new WorkerMethod("GC Worker", () => { this.logger.Info( string.Join("\n", new string('-', 80), "GC Memory: {0,10:#,##0.00} MB", "Process Memory: {1,10:#,##0.00} MB", new string('-', 80) ) .Format2 ( /*0*/ (float)GC.GetTotalMemory(false) / 1.MILLION(), /*1*/ (float)Process.GetCurrentProcess().PrivateMemorySize64 / 1.MILLION() )); }, initialNotify: true, minIdleTime: TimeSpan.FromSeconds(30), maxIdleTime: TimeSpan.FromSeconds(30), logger: this.logger); this.utxoScanWorker = new WorkerMethod("UTXO Scan Worker", () => { var chainStateLocal = this.GetChainState(); if (chainStateLocal == null) { return; } new MethodTimer().Time("Full UTXO Scan: {0:#,##0}".Format2(chainStateLocal.Utxo.OutputCount), () => { var sha256 = new SHA256Managed(); foreach (var output in chainStateLocal.Utxo.GetUnspentOutputs()) { if (new UInt256(sha256.ComputeDoubleHash(output.Value.ScriptPublicKey.ToArray())) == UInt256.Zero) { } } }); }, initialNotify: true, minIdleTime: TimeSpan.Zero, maxIdleTime: TimeSpan.MaxValue, logger: this.logger); }