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 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); }