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 ChainingWorker(WorkerConfig workerConfig, Logger logger, IBlockchainRules rules, BlockHeaderCache blockHeaderCache, ChainedHeaderCache chainedHeaderCache, BlockCache blockCache) : base("ChainingWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime, logger) { this.rules = rules; this.blockHeaderCache = blockHeaderCache; this.chainedHeaderCache = chainedHeaderCache; this.blockCache = blockCache; this.blockHeaders = new ConcurrentQueue <BlockHeader>(); this.unchainedByPrevious = new Dictionary <UInt256, Dictionary <UInt256, BlockHeader> >(); this.blockHeaderCache.OnAddition += ChainBlockHeader; this.blockCache.OnAddition += ChainBlock; }
public TargetChainWorker(WorkerConfig workerConfig, Logger logger, IKernel kernel, IBlockchainRules rules, ChainedHeaderCache chainedHeaderCache, InvalidBlockCache invalidBlockCache) : base("TargetChainWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime, logger) { this.logger = logger; this.rules = rules; this.chainedHeaderCache = chainedHeaderCache; this.invalidBlockCache = invalidBlockCache; this.rescanEvent = new AutoResetEvent(false); this.targetBlockWorker = kernel.Get <TargetBlockWorker>( new ConstructorArgument("workerConfig", new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.Zero, maxIdleTime: TimeSpan.MaxValue))); this.targetBlockWorker.OnTargetBlockChanged += HandleTargetBlockChanged; this.chainedHeaderCache.OnAddition += HandleChainedHeader; this.invalidBlockCache.OnAddition += HandleInvalidBlock; }
public TargetBlockWorker(WorkerConfig workerConfig, Logger logger, ChainedHeaderCache chainedHeaderCache, InvalidBlockCache invalidBlockCache) : base("TargetBlockWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime, logger) { this.chainedHeaderCache = chainedHeaderCache; this.invalidBlockCache = invalidBlockCache; this.targetBlock = null; this.targetBlockLock = new ReaderWriterLockSlim(); this.chainedHeaderQueue = new ConcurrentQueue <ChainedHeader>(); this.rescanEvent = new AutoResetEvent(false); // wire up cache events this.chainedHeaderCache.OnAddition += CheckChainedHeader; this.invalidBlockCache.OnAddition += HandleInvalidBlock; }
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; } }
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); }