示例#1
0
        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> >();
        }
示例#2
0
        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;
        }
示例#3
0
        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;
        }
示例#4
0
        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;
        }
示例#5
0
        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;
            }
        }
示例#6
0
        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);
        }