public TargetChainWorker(WorkerConfig workerConfig, IBlockchainRules rules, CoreStorage coreStorage) : base("TargetChainWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime) { this.rules = rules; this.coreStorage = coreStorage; this.coreStorage.ChainedHeaderAdded += HandleChainedHeaderAdded; this.coreStorage.BlockInvalidated += HandleBlockInvalidated; }
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 PruningWorker(WorkerConfig workerConfig, Func <ChainStateBuilder> getChainStateBuilder, Logger logger, IBlockchainRules rules, BlockTxHashesCache blockTxHashesCache, TransactionCache transactionCache, SpentTransactionsCache spentTransactionsCache, SpentOutputsCache spentOutputsCache) : base("PruningWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime, logger) { this.getChainStateBuilder = getChainStateBuilder; this.rules = rules; this.blockTxHashesCache = blockTxHashesCache; this.transactionCache = transactionCache; this.spentTransactionsCache = spentTransactionsCache; this.spentOutputsCache = spentOutputsCache; this.Mode = PruningMode.SpentOnly; }
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 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 MainWindow() { try { //TODO //MainnetRules.BypassValidation = true; //MainnetRules.BypassExecuteScript = true; ScriptEngine.BypassVerifySignature = true; #if SQLITE var storageContext = new SQLiteStorageContext(); var knownAddressStorage = new BitSharp.Storage.SQLite.KnownAddressStorage(storageContext); this.storageContext = storageContext; #elif FIREBIRD var storageContext = new FirebirdStorageContext(); var knownAddressStorage = new BitSharp.Storage.Firebird.KnownAddressStorage(storageContext); this.storageContext = storageContext; #elif SQL_SERVER var storageContext = new SqlServerStorageContext(); var knownAddressStorage = new BitSharp.Storage.SqlServer.KnownAddressStorage(storageContext); this.storageContext = storageContext; #endif this.cacheContext = new CacheContext(this.storageContext); this.rules = new MainnetRules(this.cacheContext); this.blockchainDaemon = new BlockchainDaemon(this.rules, this.cacheContext); this.localClient = new LocalClient(LocalClientType.MainNet, this.blockchainDaemon, knownAddressStorage); // setup view model this.viewModel = new MainWindowViewModel(this.blockchainDaemon); InitializeComponent(); // start the blockchain daemon this.blockchainDaemon.Start(); this.viewModel.ViewBlockchainLast(); // start p2p client this.localClient.Start(); this.DataContext = this.viewModel; } catch (Exception e) { Debug.WriteLine(e); throw; } }
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 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 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 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 ChainStateWorker(WorkerConfig workerConfig, TargetChainWorker targetChainWorker, ChainStateBuilder chainStateBuilder, IBlockchainRules 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.targetChainWorker.OnTargetChainChanged += HandleChanged; }
private static TransformManyBlock<LoadedTx, Tuple<LoadedTx, int>> InitTxValidator(IBlockchainRules rules, ChainedHeader chainedHeader, CancellationToken cancelToken) { return new TransformManyBlock<LoadedTx, Tuple<LoadedTx, int>>( loadedTx => { rules.ValidateTransaction(chainedHeader, loadedTx); if (!rules.IgnoreScripts && !loadedTx.IsCoinbase) { var scripts = new Tuple<LoadedTx, int>[loadedTx.Transaction.Inputs.Length]; for (var i = 0; i < loadedTx.Transaction.Inputs.Length; i++) scripts[i] = Tuple.Create(loadedTx, i); return scripts; } else return new Tuple<LoadedTx, int>[0]; }, new ExecutionDataflowBlockOptions { CancellationToken = cancelToken, MaxDegreeOfParallelism = Environment.ProcessorCount }); }
public ChainStateWorker(WorkerConfig workerConfig, TargetChainWorker targetChainWorker, ChainStateBuilder chainStateBuilder, Logger logger, IBlockchainRules rules, CoreStorage coreStorage) : base("ChainStateWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime, logger) { this.logger = logger; 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 = this.chainStateBuilder.Chain; this.coreStorage.BlockInvalidated += HandleChanged; this.coreStorage.BlockTxesAdded += HandleChanged; this.coreStorage.BlockTxesMissed += HandleChanged; this.coreStorage.BlockTxesRemoved += HandleChanged; this.coreStorage.ChainedHeaderAdded += HandleChanged; this.targetChainWorker.OnTargetChainChanged += HandleChanged; }
public ChainStateWorker(TargetChainWorker targetChainWorker, ChainStateBuilder chainStateBuilder, Func <Chain> getTargetChain, WorkerConfig workerConfig, Logger logger, IKernel kernel, IBlockchainRules rules, BlockCache blockCache, SpentTransactionsCache spentTransactionsCache, InvalidBlockCache invalidBlockCache) : base("ChainStateWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime, logger) { this.logger = logger; this.getTargetChain = getTargetChain; this.kernel = kernel; this.rules = rules; this.blockCache = blockCache; this.spentTransactionsCache = spentTransactionsCache; this.invalidBlockCache = invalidBlockCache; this.blockProcessingDurationMeasure = new DurationMeasure(); this.targetChainWorker = targetChainWorker; this.chainStateBuilder = chainStateBuilder; this.currentChain = this.chainStateBuilder.Chain.ToImmutable(); this.pruningWorker = kernel.Get <PruningWorker>( new ConstructorArgument("workerConfig", new WorkerConfig(initialNotify: false, minIdleTime: TimeSpan.FromSeconds(30), maxIdleTime: TimeSpan.FromMinutes(5))), new ConstructorArgument("getChainStateBuilder", (Func <ChainStateBuilder>)(() => this.chainStateBuilder))); }
public static async Task ValidateBlockAsync(ICoreStorage coreStorage, IBlockchainRules rules, ChainedHeader chainedHeader, ISourceBlock<LoadedTx> loadedTxes, CancellationToken cancelToken = default(CancellationToken)) { // validate merkle root var merkleStream = new MerkleStream(); var merkleValidator = InitMerkleValidator(chainedHeader, merkleStream, cancelToken); // begin feeding the merkle validator loadedTxes.LinkTo(merkleValidator, new DataflowLinkOptions { PropagateCompletion = true }); // validate transactions var txValidator = InitTxValidator(rules, chainedHeader, cancelToken); // begin feeding the tx validator merkleValidator.LinkTo(txValidator, new DataflowLinkOptions { PropagateCompletion = true }); // validate scripts var scriptValidator = InitScriptValidator(rules, chainedHeader, cancelToken); // begin feeding the script validator txValidator.LinkTo(scriptValidator, new DataflowLinkOptions { PropagateCompletion = true }); await merkleValidator.Completion; await txValidator.Completion; await scriptValidator.Completion; if (!rules.BypassPrevTxLoading) { try { merkleStream.FinishPairing(); } //TODO catch (InvalidOperationException) { throw CreateMerkleRootException(chainedHeader); } if (merkleStream.RootNode.Hash != chainedHeader.MerkleRoot) throw CreateMerkleRootException(chainedHeader); } }
public ChainStateBuilder(ChainBuilder chain, Utxo parentUtxo, Logger logger, IKernel kernel, IBlockchainRules rules, BlockHeaderCache blockHeaderCache, BlockCache blockCache, SpentTransactionsCache spentTransactionsCache, SpentOutputsCache spentOutputsCache) { this.logger = logger; this.sha256 = new SHA256Managed(); this.rules = rules; this.blockHeaderCache = blockHeaderCache; this.blockCache = blockCache; this.spentTransactionsCache = spentTransactionsCache; this.spentOutputsCache = spentOutputsCache; this.chainStateMonitor = new ChainStateMonitor(this.logger); this.scriptValidator = new ScriptValidator(this.logger, this.rules); this.chainStateMonitor.Subscribe(this.scriptValidator); this.chain = chain; this.chainStateBuilderStorage = kernel.Get <IChainStateBuilderStorage>(new ConstructorArgument("parentUtxo", parentUtxo.Storage)); this.spentTransactions = ImmutableList.CreateBuilder <KeyValuePair <UInt256, SpentTx> >(); this.spentOutputs = ImmutableList.CreateBuilder <KeyValuePair <TxOutputKey, TxOutput> >(); this.stats = new BuilderStats(); }
public CoreDaemon(IBlockchainRules rules, IStorageManager storageManager) { this.rules = rules; this.storageManager = storageManager; this.coreStorage = new CoreStorage(storageManager); // create chain state builder this.chainStateBuilder = new ChainStateBuilder(this.rules, this.coreStorage, this.storageManager); // create workers this.targetChainWorker = new TargetChainWorker( new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMilliseconds(50), maxIdleTime: TimeSpan.FromSeconds(30)), this.rules, this.coreStorage); this.chainStateWorker = new ChainStateWorker( new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMilliseconds(0), maxIdleTime: TimeSpan.FromSeconds(5)), this.targetChainWorker, this.chainStateBuilder, this.rules, this.coreStorage); this.pruningWorker = new PruningWorker( new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromSeconds(0), maxIdleTime: TimeSpan.FromMinutes(5)), this, this.storageManager, this.chainStateWorker); this.defragWorker = new DefragWorker( new WorkerConfig(initialNotify: true, minIdleTime: TimeSpan.FromMinutes(5), maxIdleTime: TimeSpan.FromMinutes(5)), this.storageManager); this.gcWorker = new WorkerMethod("GC Worker", GcWorker, initialNotify: true, minIdleTime: TimeSpan.FromMinutes(5), maxIdleTime: TimeSpan.FromMinutes(5)); this.utxoScanWorker = new WorkerMethod("UTXO Scan Worker", UtxoScanWorker, initialNotify: true, minIdleTime: TimeSpan.FromSeconds(60), maxIdleTime: TimeSpan.FromSeconds(60)); // wire events this.chainStateWorker.BlockMissed += HandleBlockMissed; this.targetChainWorker.OnTargetChainChanged += HandleTargetChainChanged; this.chainStateWorker.OnChainStateChanged += HandleChainStateChanged; this.pruningWorker.OnWorkFinished += this.defragWorker.NotifyWork; }
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); }
private static ActionBlock<Tuple<LoadedTx, int>> InitScriptValidator(IBlockchainRules rules, ChainedHeader chainedHeader, CancellationToken cancelToken) { return new ActionBlock<Tuple<LoadedTx, int>>( tuple => { var loadedTx = tuple.Item1; var inputIndex = tuple.Item2; var txInput = loadedTx.Transaction.Inputs[inputIndex]; var prevTxOutput = loadedTx.GetInputPrevTxOutput(inputIndex); if (!rules.IgnoreScriptErrors) { rules.ValidationTransactionScript(chainedHeader, loadedTx.Transaction, loadedTx.TxIndex, txInput, inputIndex, prevTxOutput); } else { try { rules.ValidationTransactionScript(chainedHeader, loadedTx.Transaction, loadedTx.TxIndex, txInput, inputIndex, prevTxOutput); } catch (Exception ex) { var aggEx = ex as AggregateException; logger.Debug($"Ignoring script errors in block: {chainedHeader.Height,9:N0}, errors: {(aggEx?.InnerExceptions.Count ?? -1):N0}"); } } }, new ExecutionDataflowBlockOptions { CancellationToken = cancelToken, MaxDegreeOfParallelism = Environment.ProcessorCount }); }
public BlockchainCalculator(IBlockchainRules rules, CacheContext cacheContext, CancellationToken shutdownToken) { this._rules = rules; this._cacheContext = cacheContext; this.shutdownToken = shutdownToken; }
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); }
public BlockchainDaemon(IBlockchainRules rules, CacheContext cacheContext) { this.shutdownToken = new CancellationTokenSource(); this._rules = rules; this._cacheContext = cacheContext; this._calculator = new BlockchainCalculator(this._rules, this._cacheContext, this.shutdownToken.Token); this._winningBlock = this._rules.GenesisChainedBlock; this._winningBlockchain = ImmutableArray.Create(this._rules.GenesisChainedBlock); this.winningBlockchainLock = new ReaderWriterLockSlim(); this._currentBlockchain = this._rules.GenesisBlockchain; this.currentBlockchainLock = new ReaderWriterLockSlim(); //TODO this.lastCurrentBlockchainWrite = Guid.NewGuid(); this.missingBlocks = new ConcurrentSetBuilder <UInt256>(); this.unchainedBlocks = new ConcurrentSetBuilder <UInt256>(); this.missingChainedBlocks = new ConcurrentSet <UInt256>(); this.missingTransactions = new ConcurrentSet <UInt256>(); // write genesis block out to storage this._cacheContext.BlockCache.UpdateValue(this._rules.GenesisBlock.Hash, this._rules.GenesisBlock); this._cacheContext.ChainedBlockCache.UpdateValue(this._rules.GenesisChainedBlock.BlockHash, this._rules.GenesisChainedBlock); // wait for genesis block to be flushed this._cacheContext.BlockCache.WaitForStorageFlush(); this._cacheContext.ChainedBlockCache.WaitForStorageFlush(); // pre-fill the chained block and header caches //this._cacheContext.BlockHeaderCache.FillCache(); this._cacheContext.ChainedBlockCache.FillCache(); // wire up cache events this._cacheContext.BlockHeaderCache.OnAddition += OnBlockHeaderAddition; this._cacheContext.BlockHeaderCache.OnModification += OnBlockHeaderModification; this._cacheContext.BlockCache.OnAddition += OnBlockAddition; this._cacheContext.BlockCache.OnModification += OnBlockModification; this._cacheContext.ChainedBlockCache.OnAddition += OnChainedBlockAddition; this._cacheContext.ChainedBlockCache.OnModification += OnChainedBlockModification; this.unchainedBlocks.UnionWith(this.CacheContext.BlockHeaderCache.GetAllKeys()); this.unchainedBlocks.ExceptWith(this.CacheContext.ChainedBlockCache.GetAllKeys()); // create workers this.chainingWorker = new Worker("BlockchainDaemon.ChainingWorker", ChainingWorker, runOnStart: true, waitTime: TimeSpan.FromSeconds(1), maxIdleTime: TimeSpan.FromSeconds(30)); this.winnerWorker = new Worker("BlockchainDaemon.WinnerWorker", WinnerWorker, runOnStart: true, waitTime: TimeSpan.FromSeconds(1), maxIdleTime: TimeSpan.FromSeconds(30)); this.validationWorker = new Worker("BlockchainDaemon.ValidationWorker", ValidationWorker, runOnStart: true, waitTime: TimeSpan.FromSeconds(10), maxIdleTime: TimeSpan.FromMinutes(5)); this.blockchainWorker = new Worker("BlockchainDaemon.BlockchainWorker", BlockchainWorker, runOnStart: true, waitTime: TimeSpan.FromSeconds(5), maxIdleTime: TimeSpan.FromMinutes(5)); this.validateCurrentChainWorker = new Worker("BlockchainDaemon.ValidateCurrentChainWorker", ValidateCurrentChainWorker, runOnStart: true, waitTime: TimeSpan.FromMinutes(30), maxIdleTime: TimeSpan.FromMinutes(30)); this.writeBlockchainWorker = new Worker("BlockchainDaemon.WriteBlockchainWorker", WriteBlockchainWorker, runOnStart: true, waitTime: TimeSpan.FromMinutes(5), maxIdleTime: TimeSpan.FromMinutes(30)); }
public ScriptValidator(Logger logger, IBlockchainRules rules) : base("ScriptValidator", isConcurrent: true, logger: logger) { this.rules = rules; }
public BlockchainDaemon(IBlockchainRules rules, CacheContext cacheContext) { this.shutdownToken = new CancellationTokenSource(); this._rules = rules; this._cacheContext = cacheContext; this._calculator = new BlockchainCalculator(this._rules, this._cacheContext, this.shutdownToken.Token); this._winningBlock = this._rules.GenesisChainedBlock; this._winningBlockchain = ImmutableArray.Create(this._rules.GenesisChainedBlock); this.winningBlockchainLock = new ReaderWriterLockSlim(); this._currentBlockchain = this._rules.GenesisBlockchain; this.currentBlockchainLock = new ReaderWriterLockSlim(); //TODO this.lastCurrentBlockchainWrite = Guid.NewGuid(); this.missingBlocks = new ConcurrentSetBuilder<UInt256>(); this.unchainedBlocks = new ConcurrentSetBuilder<UInt256>(); this.missingChainedBlocks = new ConcurrentSet<UInt256>(); this.missingTransactions = new ConcurrentSet<UInt256>(); // write genesis block out to storage this._cacheContext.BlockCache.UpdateValue(this._rules.GenesisBlock.Hash, this._rules.GenesisBlock); this._cacheContext.ChainedBlockCache.UpdateValue(this._rules.GenesisChainedBlock.BlockHash, this._rules.GenesisChainedBlock); // wait for genesis block to be flushed this._cacheContext.BlockCache.WaitForStorageFlush(); this._cacheContext.ChainedBlockCache.WaitForStorageFlush(); // pre-fill the chained block and header caches //this._cacheContext.BlockHeaderCache.FillCache(); this._cacheContext.ChainedBlockCache.FillCache(); // wire up cache events this._cacheContext.BlockHeaderCache.OnAddition += OnBlockHeaderAddition; this._cacheContext.BlockHeaderCache.OnModification += OnBlockHeaderModification; this._cacheContext.BlockCache.OnAddition += OnBlockAddition; this._cacheContext.BlockCache.OnModification += OnBlockModification; this._cacheContext.ChainedBlockCache.OnAddition += OnChainedBlockAddition; this._cacheContext.ChainedBlockCache.OnModification += OnChainedBlockModification; this.unchainedBlocks.UnionWith(this.CacheContext.BlockHeaderCache.GetAllKeys()); this.unchainedBlocks.ExceptWith(this.CacheContext.ChainedBlockCache.GetAllKeys()); // create workers this.chainingWorker = new Worker("BlockchainDaemon.ChainingWorker", ChainingWorker, runOnStart: true, waitTime: TimeSpan.FromSeconds(1), maxIdleTime: TimeSpan.FromSeconds(30)); this.winnerWorker = new Worker("BlockchainDaemon.WinnerWorker", WinnerWorker, runOnStart: true, waitTime: TimeSpan.FromSeconds(1), maxIdleTime: TimeSpan.FromSeconds(30)); this.validationWorker = new Worker("BlockchainDaemon.ValidationWorker", ValidationWorker, runOnStart: true, waitTime: TimeSpan.FromSeconds(10), maxIdleTime: TimeSpan.FromMinutes(5)); this.blockchainWorker = new Worker("BlockchainDaemon.BlockchainWorker", BlockchainWorker, runOnStart: true, waitTime: TimeSpan.FromSeconds(5), maxIdleTime: TimeSpan.FromMinutes(5)); this.validateCurrentChainWorker = new Worker("BlockchainDaemon.ValidateCurrentChainWorker", ValidateCurrentChainWorker, runOnStart: true, waitTime: TimeSpan.FromMinutes(30), maxIdleTime: TimeSpan.FromMinutes(30)); this.writeBlockchainWorker = new Worker("BlockchainDaemon.WriteBlockchainWorker", WriteBlockchainWorker, runOnStart: true, waitTime: TimeSpan.FromMinutes(5), maxIdleTime: TimeSpan.FromMinutes(30)); }