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); }
public TargetChainWorker(WorkerConfig workerConfig, Logger logger, IBlockchainRules rules, CoreStorage coreStorage) : base("TargetChainWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime, logger) { this.logger = logger; this.rules = rules; this.coreStorage = coreStorage; this.coreStorage.ChainedHeaderAdded += HandleChainedHeaderAdded; this.coreStorage.BlockInvalidated += HandleBlockInvalidated; }
public TargetChainWorker(WorkerConfig workerConfig, IChainParams chainParams, CoreStorage coreStorage) : base("TargetChainWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime) { this.chainParams = chainParams; this.coreStorage = coreStorage; this.coreStorage.ChainedHeaderAdded += HandleChanged; this.coreStorage.ChainedHeaderRemoved += HandleChanged; this.coreStorage.BlockInvalidated += HandleChanged; }
public TestDaemon(Block genesisBlock = null, INinjectModule loggingModule = null, INinjectModule[] storageModules = null) { // initialize storage folder this.baseDirectoryCleanup = TempDirectory.CreateTempDirectory(out this.baseDirectory); // initialize kernel this.kernel = new StandardKernel(); // add logging module this.kernel.Load(loggingModule ?? new ConsoleLoggingModule()); // log startup this.logger = LogManager.GetCurrentClassLogger(); this.logger.Info($"Starting up: {DateTime.Now}"); // initialize test blocks this.testBlocks = new TestBlocks(genesisBlock); // add storage module this.kernel.Load(storageModules ?? new[] { new MemoryStorageModule() }); // initialize unit test rules, allow validation methods to run testBlocks.Rules.ValidateTransactionAction = null; testBlocks.Rules.ValidationTransactionScriptAction = null; this.kernel.Bind <ChainType>().ToConstant(ChainType.Regtest); this.kernel.Bind <ICoreRules>().ToConstant(testBlocks.Rules); this.kernel.Bind <IChainParams>().ToConstant(testBlocks.ChainParams); // by default, don't run scripts in unit tests testBlocks.Rules.IgnoreScripts = true; // initialize the blockchain daemon this.kernel.Bind <CoreDaemon>().ToSelf().InSingletonScope(); this.coreDaemon = this.kernel.Get <CoreDaemon>(); try { this.coreStorage = this.coreDaemon.CoreStorage; // start the blockchain daemon this.coreDaemon.Start(); // wait for initial work this.coreDaemon.WaitForUpdate(); // verify initial state Assert.AreEqual(0, this.coreDaemon.TargetChainHeight); Assert.AreEqual(testBlocks.ChainParams.GenesisBlock.Hash, this.coreDaemon.TargetChain.LastBlock.Hash); Assert.AreEqual(testBlocks.ChainParams.GenesisBlock.Hash, this.coreDaemon.CurrentChain.LastBlock.Hash); } catch (Exception) { this.coreDaemon.Dispose(); throw; } }
public UnconfirmedTxesWorker(WorkerConfig workerConfig, ChainStateWorker chainStateWorker, UnconfirmedTxesBuilder unconfirmedTxesBuilder, CoreStorage coreStorage) : base("UnconfirmedTxesWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime) { this.coreStorage = coreStorage; this.chainStateWorker = chainStateWorker; this.unconfirmedTxesBuilder = unconfirmedTxesBuilder; this.currentChain = new Lazy <Chain>(() => this.unconfirmedTxesBuilder.Chain); this.chainStateWorker.OnChainStateChanged += HandleChanged; }
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; } }
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 PruningWorker(WorkerConfig workerConfig, CoreStorage coreStorage, ChainStateWorker chainStateWorker, ChainStateBuilder chainStateBuilder, Logger logger, IBlockchainRules rules) : base("PruningWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime, logger) { this.logger = logger; this.coreStorage = coreStorage; this.chainStateWorker = chainStateWorker; this.chainStateBuilder = chainStateBuilder; this.rules = rules; this.lastPruneHeight = 0; this.Mode = PruningMode.RollbackAndBlocks; }
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 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 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>(); }
public BlockValidator(CoreStorage coreStorage, IBlockchainRules rules, Logger logger) { this.logger = logger; this.coreStorage = coreStorage; this.rules = rules; // thread count for i/o task (TxLoader) var ioThreadCount = 4; // thread count for cpu tasks (TxValidator, ScriptValidator) var cpuThreadCount = Environment.ProcessorCount * 2; this.txLoader = new ParallelConsumer <TxWithPrevOutputKeys>("ChainStateBuilder.TxLoader", ioThreadCount, logger); this.txValidator = new ParallelConsumer <TxWithPrevOutputs>("ChainStateBuilder.TxValidator", cpuThreadCount, logger); this.scriptValidator = new ParallelConsumer <TxInputWithPrevOutput>("ChainStateBuilder.ScriptValidator", cpuThreadCount, logger); }
public ChainStateBuilder(Logger logger, IBlockchainRules rules, CoreStorage coreStorage) { this.logger = logger; this.sha256 = new SHA256Managed(); this.rules = rules; this.coreStorage = coreStorage; this.blockValidator = new BlockValidator(this.coreStorage, this.rules, this.logger); this.chainStateCursorHandle = coreStorage.OpenChainStateCursor(); this.chainStateCursor = this.chainStateCursorHandle.Item; this.chain = new ChainBuilder(chainStateCursor.ReadChain()); this.utxoBuilder = new UtxoBuilder(chainStateCursor, logger); this.commitLock = new ReaderWriterLockSlim(); this.stats = new BuilderStats(); }
public MainnetSimulator() { this.random = new Random(); this.blockProvider = new MainnetBlockProvider(); // initialize kernel this.kernel = new StandardKernel(); // add logging module this.kernel.Load(new ConsoleLoggingModule()); // log startup this.logger = kernel.Get <Logger>(); this.logger.Info("Starting up: {0}".Format2(DateTime.Now)); // add storage module this.kernel.Load(new MemoryStorageModule()); // add rules module this.kernel.Load(new RulesModule(RulesEnum.MainNet)); // TODO ignore script errors in test daemon until scripting engine is completed var rules = this.kernel.Get <IBlockchainRules>(); rules.IgnoreScriptErrors = true; // initialize the blockchain daemon this.kernel.Bind <CoreDaemon>().ToSelf().InSingletonScope(); this.coreDaemon = this.kernel.Get <CoreDaemon>(); this.coreStorage = this.coreDaemon.CoreStorage; // start the blockchain daemon this.coreDaemon.Start(); // wait for initial work this.coreDaemon.WaitForUpdate(); // verify initial state Assert.AreEqual(0, this.coreDaemon.TargetChainHeight); Assert.AreEqual(rules.GenesisBlock.Hash, this.coreDaemon.TargetChain.LastBlockHash); Assert.AreEqual(rules.GenesisBlock.Hash, this.coreDaemon.CurrentChain.LastBlockHash); }
public Simulator(ChainType chainType) { // initialize kernel this.kernel = new StandardKernel(); // add logging module this.kernel.Load(new ConsoleLoggingModule()); // log startup this.logger = LogManager.GetCurrentClassLogger(); this.logger.Info($"Starting up: {DateTime.Now}"); this.random = new Random(); this.blockProvider = TestBlockProvider.CreateForRules(chainType); // add storage module this.kernel.Load(new MemoryStorageModule()); // add rules module this.kernel.Load(new RulesModule(chainType)); // by default, don't run scripts in unit tests var rules = this.kernel.Get <ICoreRules>(); rules.IgnoreScripts = true; // initialize the blockchain daemon this.kernel.Bind <CoreDaemon>().ToSelf().InSingletonScope(); this.coreDaemon = this.kernel.Get <CoreDaemon>(); this.coreStorage = this.coreDaemon.CoreStorage; // start the blockchain daemon this.coreDaemon.Start(); // wait for initial work this.coreDaemon.WaitForUpdate(); // verify initial state Assert.AreEqual(0, this.coreDaemon.TargetChainHeight); Assert.AreEqual(rules.ChainParams.GenesisBlock.Hash, this.coreDaemon.TargetChain.LastBlock.Hash); Assert.AreEqual(rules.ChainParams.GenesisBlock.Hash, this.coreDaemon.CurrentChain.LastBlock.Hash); }
public ChainStateWorker(WorkerConfig workerConfig, TargetChainWorker targetChainWorker, ChainStateBuilder chainStateBuilder, ICoreRules rules, CoreStorage coreStorage) : base("ChainStateWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime) { this.rules = rules; this.coreStorage = coreStorage; this.blockProcessingDurationMeasure = new DurationMeasure(sampleCutoff: TimeSpan.FromMinutes(5)); this.blockMissCountMeasure = new CountMeasure(TimeSpan.FromSeconds(30)); this.targetChainWorker = targetChainWorker; this.chainStateBuilder = chainStateBuilder; this.currentChain = new Lazy <Chain>(() => this.chainStateBuilder.Chain); this.coreStorage.BlockInvalidated += HandleChanged; this.coreStorage.BlockTxesAdded += HandleChanged; this.coreStorage.BlockTxesRemoved += HandleChanged; this.coreStorage.ChainedHeaderAdded += HandleChanged; this.coreStorage.ChainedHeaderRemoved += HandleChanged; this.targetChainWorker.OnTargetChainChanged += HandleChanged; }
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 TestDaemon(Block genesisBlock = null) { this.random = new Random(); // initialize kernel this.kernel = new StandardKernel(); // add logging module this.kernel.Load(new ConsoleLoggingModule()); // create the key pair that block rewards will be sent to this.txManager = this.kernel.Get <TransactionManager>(); var keyPair = this.txManager.CreateKeyPair(); this.coinbasePrivateKey = keyPair.Item1; this.coinbasePublicKey = keyPair.Item2; // initialize miner this.miner = this.kernel.Get <Miner>(); // create and mine the genesis block this.genesisBlock = genesisBlock ?? MineEmptyBlock(0); // log startup this.logger = kernel.Get <Logger>(); this.logger.Info("Starting up: {0}".Format2(DateTime.Now)); // add storage module this.kernel.Load(new MemoryStorageModule()); // initialize unit test rules this.rules = this.kernel.Get <UnitTestRules>(); this.rules.SetGenesisBlock(this.genesisBlock); this.kernel.Bind <RulesEnum>().ToConstant(RulesEnum.TestNet2); this.kernel.Bind <IBlockchainRules>().ToConstant(rules); // TODO ignore script errors in test daemon until scripting engine is completed this.rules.IgnoreScriptErrors = true; // initialize the blockchain daemon this.kernel.Bind <CoreDaemon>().ToSelf().InSingletonScope(); this.coreDaemon = this.kernel.Get <CoreDaemon>(); try { this.coreStorage = this.coreDaemon.CoreStorage; // start the blockchain daemon this.coreDaemon.Start(); // wait for initial work this.coreDaemon.WaitForUpdate(); // verify initial state Assert.AreEqual(0, this.coreDaemon.TargetChainHeight); Assert.AreEqual(this.genesisBlock.Hash, this.coreDaemon.TargetChain.LastBlockHash); Assert.AreEqual(this.genesisBlock.Hash, this.coreDaemon.CurrentChain.LastBlockHash); } catch (Exception) { this.coreDaemon.Dispose(); throw; } }
public DefragWorker(WorkerConfig workerConfig, CoreStorage coreStorage, Logger logger) : base("DefragWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime, logger) { this.logger = logger; this.coreStorage = coreStorage; }
private void TestRollback(ITestStorageProvider provider) { ConsoleLoggingModule.Configure(); var logger = LogManager.GetCurrentClassLogger(); var blockCount = 10.THOUSAND(); var checkUtxoHashFrequencey = 1000; var blockProvider = new TestNet3BlockProvider(); var blocks = blockProvider.ReadBlocks().Take(blockCount).ToList(); var genesisBlock = blocks[0]; var genesisHeader = new ChainedHeader(genesisBlock.Header, height: 0, totalWork: 0, dateSeen: DateTimeOffset.Now); var genesisChain = Chain.CreateForGenesisBlock(genesisHeader); var chainParams = new Testnet3Params(); var rules = new CoreRules(chainParams) { IgnoreScripts = true, IgnoreSignatures = true, IgnoreScriptErrors = true }; using (var storageManager = provider.OpenStorageManager()) using (var coreStorage = new CoreStorage(storageManager)) using (var chainStateBuilder = new ChainStateBuilder(rules, coreStorage, storageManager)) { // add blocks to storage coreStorage.AddGenesisBlock(ChainedHeader.CreateForGenesisBlock(blocks[0].Header)); foreach (var block in blocks) { coreStorage.TryAddBlock(block); } // store empty utxo hash var expectedUtxoHashes = new List <UInt256>(); using (var chainState = chainStateBuilder.ToImmutable()) expectedUtxoHashes.Add(UtxoCommitment.ComputeHash(chainState)); // calculate utxo forward and store its state at each step along the way for (var blockIndex = 0; blockIndex < blocks.Count; blockIndex++) { logger.Info($"Adding: {blockIndex:N0}"); var block = blocks[blockIndex]; var chainedHeader = new ChainedHeader(block.Header, blockIndex, 0, DateTimeOffset.Now); chainStateBuilder.AddBlockAsync(chainedHeader, block.Transactions.Select( (tx, txIndex) => BlockTx.Create(txIndex, tx))).Wait(); if (blockIndex % checkUtxoHashFrequencey == 0 || blockIndex == blocks.Count - 1) { using (var chainState = chainStateBuilder.ToImmutable()) expectedUtxoHashes.Add(UtxoCommitment.ComputeHash(chainState)); } } // verify the utxo state before rolling back var expectedLastUtxoHash = UInt256.ParseHex("5f155c7d8a5c850d5fb2566aec5110caa40e270184126d17022ae9780fd65fd9"); Assert.AreEqual(expectedLastUtxoHash, expectedUtxoHashes.Last()); expectedUtxoHashes.RemoveAt(expectedUtxoHashes.Count - 1); // roll utxo backwards and validate its state at each step along the way for (var blockIndex = blocks.Count - 1; blockIndex >= 0; blockIndex--) { logger.Info($"Rolling back: {blockIndex:N0}"); var block = blocks[blockIndex]; var chainedHeader = new ChainedHeader(block.Header, blockIndex, 0, DateTimeOffset.Now); var blockTxes = block.Transactions.Select((tx, txIndex) => BlockTx.Create(txIndex, tx)); chainStateBuilder.RollbackBlock(chainedHeader, blockTxes); if ((blockIndex - 1) % checkUtxoHashFrequencey == 0 || blockIndex == 0) { var expectedUtxoHash = expectedUtxoHashes.Last(); expectedUtxoHashes.RemoveAt(expectedUtxoHashes.Count - 1); using (var chainState = chainStateBuilder.ToImmutable()) Assert.AreEqual(expectedUtxoHash, UtxoCommitment.ComputeHash(chainState)); } } // verify chain state was rolled all the way back Assert.AreEqual(-1, chainStateBuilder.Chain.Height); Assert.AreEqual(0, expectedUtxoHashes.Count); // calculate utxo forward again for (var blockIndex = 0; blockIndex < blocks.Count; blockIndex++) { logger.Info($"Adding: {blockIndex:N0}"); var block = blocks[blockIndex]; var chainedHeader = new ChainedHeader(block.Header, blockIndex, 0, DateTimeOffset.Now); chainStateBuilder.AddBlockAsync(chainedHeader, block.Transactions.Select( (tx, txIndex) => BlockTx.Create(txIndex, tx))).Wait(); } // verify final utxo state again using (var chainState = chainStateBuilder.ToImmutable()) Assert.AreEqual(expectedLastUtxoHash, UtxoCommitment.ComputeHash(chainState)); } }
public RevalidateWorker(Logger logger, CoreStorage coreStorage) : base("RevalidateWorker", initialNotify: false, minIdleTime: TimeSpan.Zero, maxIdleTime: TimeSpan.MaxValue, logger: logger) { this.logger = logger; this.coreStorage = coreStorage; }
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); }
private void TestRollback(ITestStorageProvider provider) { var logger = LogManager.CreateNullLogger(); var sha256 = new SHA256Managed(); var blockProvider = new MainnetBlockProvider(); var blocks = Enumerable.Range(0, 500).Select(x => blockProvider.GetBlock(x)).ToList(); var genesisBlock = blocks[0]; var genesisHeader = new ChainedHeader(genesisBlock.Header, height: 0, totalWork: 0); var genesisChain = Chain.CreateForGenesisBlock(genesisHeader); var rules = new MainnetRules(logger); using (var storageManager = provider.OpenStorageManager()) using (var coreStorage = new CoreStorage(storageManager, logger)) using (var chainStateBuilder = new ChainStateBuilder(logger, rules, coreStorage)) { // add blocks to storage coreStorage.AddGenesisBlock(ChainedHeader.CreateForGenesisBlock(blocks[0].Header)); foreach (var block in blocks) { coreStorage.TryAddBlock(block); } // calculate utxo forward and store its state at each step along the way var expectedUtxos = new List <List <UnspentTx> >(); for (var blockIndex = 0; blockIndex < blocks.Count; blockIndex++) { var block = blocks[blockIndex]; var chainedHeader = new ChainedHeader(block.Header, blockIndex, 0); chainStateBuilder.AddBlock(chainedHeader, block.Transactions); using (var chainState = chainStateBuilder.ToImmutable()) { expectedUtxos.Add(chainState.ReadUnspentTransactions().ToList()); } } // verify the utxo state before rolling back //TODO verify the UTXO hash hard-coded here is correct var expectedUtxoHash = UInt256.Parse("609eb5882e0b71a707fb876c844fbfe6b4579e04eb27c7c0cefbb7478bac737b", NumberStyles.HexNumber); using (var utxoStream = new UtxoStream(logger, expectedUtxos.Last())) { var utxoHash = new UInt256(sha256.ComputeDoubleHash(utxoStream)); Assert.AreEqual(expectedUtxoHash, utxoHash); } expectedUtxos.RemoveAt(expectedUtxos.Count - 1); // roll utxo backwards and validate its state at each step along the way for (var blockIndex = blocks.Count - 1; blockIndex >= 1; blockIndex--) { var block = blocks[blockIndex]; var chainedHeader = new ChainedHeader(block.Header, blockIndex, 0); var blockTxes = block.Transactions.Select((tx, txIndex) => new BlockTx(txIndex, 0, tx.Hash, /*pruned:*/ false, tx)); chainStateBuilder.RollbackBlock(chainedHeader, blockTxes); var expectedUtxo = expectedUtxos.Last(); expectedUtxos.RemoveAt(expectedUtxos.Count - 1); List <UnspentTx> actualUtxo; using (var chainState = chainStateBuilder.ToImmutable()) { actualUtxo = chainState.ReadUnspentTransactions().ToList(); } CollectionAssert.AreEqual(expectedUtxo, actualUtxo, "UTXO differs at height: {0}".Format2(blockIndex)); } } }
public MainWindowViewModel(IKernel kernel, WalletMonitor walletMonitor = null) { this.dispatcher = Dispatcher.CurrentDispatcher; this.kernel = kernel; this.coreDaemon = kernel.Get <CoreDaemon>(); this.coreStorage = this.coreDaemon.CoreStorage; this.localClient = kernel.Get <LocalClient>(); this.startTime = DateTime.UtcNow; this.runningTimeTimer = new DispatcherTimer(); runningTimeTimer.Tick += (sender, e) => { var runningTime = (DateTime.UtcNow - this.startTime); this.RunningTime = "{0:#,#00}:{1:mm':'ss}".Format2(Math.Floor(runningTime.TotalHours), runningTime); }; runningTimeTimer.Interval = TimeSpan.FromMilliseconds(100); runningTimeTimer.Start(); this.ratesTimer = new DispatcherTimer(); ratesTimer.Tick += (sender, e) => { this.BlockRate = this.coreDaemon.GetBlockRate(TimeSpan.FromSeconds(1)); this.TransactionRate = this.coreDaemon.GetTxRate(TimeSpan.FromSeconds(1)); this.InputRate = this.coreDaemon.GetInputRate(TimeSpan.FromSeconds(1)); this.BlockDownloadRate = this.localClient.GetBlockDownloadRate(TimeSpan.FromSeconds(1)); this.DuplicateBlockDownloadCount = this.localClient.GetDuplicateBlockDownloadCount(); this.BlockMissCount = this.localClient.GetBlockMissCount(); }; ratesTimer.Interval = TimeSpan.FromSeconds(1); ratesTimer.Start(); this.viewChain = this.coreDaemon.CurrentChain; this.WinningBlockchainHeight = this.coreDaemon.TargetChainHeight; this.CurrentBlockchainHeight = this.coreDaemon.CurrentChain.Height; this.DownloadedBlockCount = this.coreStorage.BlockWithTxesCount; this.coreStorage.BlockTxesAdded += (chainedHeader) => DownloadedBlockCount = this.coreStorage.BlockWithTxesCount; this.coreStorage.BlockTxesRemoved += (blockHash) => DownloadedBlockCount = this.coreStorage.BlockWithTxesCount; this.coreDaemon.OnTargetChainChanged += (sender, block) => WinningBlockchainHeight = this.coreDaemon.TargetChainHeight; this.coreDaemon.OnChainStateChanged += (sender, chainState) => CurrentBlockchainHeight = this.coreDaemon.CurrentChain.Height; if (walletMonitor != null) { this.walletMonitor = walletMonitor; this.WalletEntries = new ObservableCollection <WalletEntry>(); this.walletMonitor.OnEntryAdded += HandleOnWalletEntryAdded; } }