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

            // add cache module
            this.kernel.Load(new CoreCacheModule());

            // initialize block view
            this.blockCache = this.kernel.Get <BlockCache>();

            // store genesis block
            this.blockCache[this.genesisBlock.Hash] = this.genesisBlock;

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

            // initialize the blockchain daemon
            this.kernel.Bind <CoreDaemon>().ToSelf().InSingletonScope();
            this.blockchainDaemon = this.kernel.Get <CoreDaemon>();

            // start the blockchain daemon
            this.blockchainDaemon.Start();

            // wait for initial work
            this.blockchainDaemon.ForceWorkAndWait();

            // verify initial state
            Assert.AreEqual(0, this.blockchainDaemon.TargetBlock.Height);
            Assert.AreEqual(this.genesisBlock.Hash, this.blockchainDaemon.TargetChain.LastBlockHash);
            Assert.AreEqual(this.genesisBlock.Hash, this.blockchainDaemon.CurrentChain.LastBlockHash);
        }
示例#3
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> >();
        }
示例#4
0
        private CoreDaemon CreateExampleDaemon(out BlockProvider embeddedBlocks, out IStorageManager storageManager, int?maxHeight = null)
        {
            // retrieve first 10,000 testnet3 blocks
            embeddedBlocks = new BlockProvider("BitSharp.Examples.Blocks.TestNet3.zip");

            // initialize in-memory storage
            storageManager = new MemoryStorageManager();

            // intialize testnet3 rules (ignore script errors, script engine is not and is not intended to be complete)
            var chainParams = new Testnet3Params();
            var rules       = new CoreRules(chainParams)
            {
                IgnoreScriptErrors = true
            };

            // initialize & start core daemon
            var coreDaemon = new CoreDaemon(rules, storageManager)
            {
                MaxHeight = maxHeight, IsStarted = true
            };

            // add embedded blocks
            coreDaemon.CoreStorage.AddBlocks(embeddedBlocks.ReadBlocks());

            // wait for core daemon to finish processing any available data
            coreDaemon.WaitForUpdate();

            return(coreDaemon);
        }
示例#5
0
 public PeerWorker(WorkerConfig workerConfig, Logger logger, LocalClient localClient, CoreDaemon coreDaemon)
     : base("PeerWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime, logger)
 {
     this.logger      = logger;
     this.localClient = localClient;
     this.coreDaemon  = coreDaemon;
 }
示例#6
0
        public MainWindowViewModel(IKernel kernel, WalletMonitor walletMonitor = null)
        {
            this.dispatcher = Dispatcher.CurrentDispatcher;

            this.kernel           = kernel;
            this.blockchainDaemon = kernel.Get <CoreDaemon>();
            this.localClient      = kernel.Get <LocalClient>();
            this.blockCache       = kernel.Get <BlockCache>();

            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.blockchainDaemon.GetBlockRate(TimeSpan.FromSeconds(1));
                this.TransactionRate            = this.blockchainDaemon.GetTxRate(TimeSpan.FromSeconds(1));
                this.InputRate                  = this.blockchainDaemon.GetInputRate(TimeSpan.FromSeconds(1));
                this.BlockDownloadRate          = this.localClient.GetBlockDownloadRate(TimeSpan.FromSeconds(1));
                this.DuplicateBlockDownloadRate = this.localClient.GetDuplicateBlockDownloadRate(TimeSpan.FromSeconds(1));
            };
            ratesTimer.Interval = TimeSpan.FromSeconds(1);
            ratesTimer.Start();

            this.viewChain = this.blockchainDaemon.CurrentChain;

            this.WinningBlockchainHeight = this.blockchainDaemon.TargetBlockHeight;
            this.CurrentBlockchainHeight = this.blockchainDaemon.CurrentChain.Height;
            this.DownloadedBlockCount    = this.blockCache.Count;

            this.blockCache.OnAddition +=
                (blockHash, block) =>
                DownloadedBlockCount = this.blockCache.Count;

            this.blockCache.OnRemoved +=
                (blockHash) =>
                DownloadedBlockCount = this.blockCache.Count;

            this.blockchainDaemon.OnTargetBlockChanged +=
                (sender, block) =>
                WinningBlockchainHeight = this.blockchainDaemon.TargetBlockHeight;

            this.blockchainDaemon.OnChainStateChanged +=
                (sender, chainState) =>
                CurrentBlockchainHeight = this.blockchainDaemon.CurrentChain.Height;

            if (walletMonitor != null)
            {
                this.walletMonitor = walletMonitor;
                this.WalletEntries = new ObservableCollection <WalletEntry>();
                this.walletMonitor.OnEntryAdded += HandleOnWalletEntryAdded;
            }
        }
示例#7
0
 internal PeerWorker(WorkerConfig workerConfig, LocalClient localClient, CoreDaemon coreDaemon, HeadersRequestWorker headersRequestWorker)
     : base("PeerWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime)
 {
     this.localClient          = localClient;
     this.coreDaemon           = coreDaemon;
     this.headersRequestWorker = headersRequestWorker;
 }
示例#8
0
 public async Task StartAsync()
 {
     await Task.WhenAll(
         // start the blockchain daemon
         Task.Run(() => CoreDaemon.Start()),
         // start p2p client
         Task.Run(() => LocalClient.Start(nodeConfig.ConnectToPeers)));
 }
示例#9
0
        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;
            }
        }
示例#10
0
        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;
            }
        }
示例#11
0
        protected virtual void Dispose(bool disposing)
        {
            if (!disposed && disposing)
            {
                // shutdown
                LocalClient.Dispose();
                CoreDaemon.Dispose();
                Kernel.Dispose();

                disposed = true;
            }
        }
示例#12
0
        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;
            }
        }
示例#13
0
        public WalletMonitor(CoreDaemon coreDaemon, bool keepEntries = true)
            : base("WalletMonitor", initialNotify: true, minIdleTime: TimeSpan.FromMilliseconds(0), maxIdleTime: TimeSpan.MaxValue)
        {
            this.coreDaemon = coreDaemon;

            this.addressesByOutputScriptHash = new Dictionary <UInt256, List <MonitoredWalletAddress> >();
            this.matcherAddresses            = new List <MonitoredWalletAddress>();
            this.keepEntries = keepEntries;
            this.entries     = ImmutableList.CreateBuilder <WalletEntry>();
            this.bitBalance  = 0;

            this.coreDaemon.OnChainStateChanged += HandleChainStateChanged;
        }
示例#14
0
        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;
            }
        }
示例#15
0
        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();
        }
示例#16
0
        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>();
        }
示例#17
0
        public HeadersRequestWorker(Logger logger, WorkerConfig workerConfig, LocalClient localClient, CoreDaemon blockchainDaemon, BlockHeaderCache blockHeaderCache)
            : base("HeadersRequestWorker", workerConfig.initialNotify, workerConfig.minIdleTime, workerConfig.maxIdleTime, logger)
        {
            this.logger           = logger;
            this.localClient      = localClient;
            this.blockchainDaemon = blockchainDaemon;
            this.blockHeaderCache = blockHeaderCache;

            this.headersRequestsByPeer = new ConcurrentDictionary <IPEndPoint, DateTime>();

            this.localClient.OnBlockHeaders            += HandleBlockHeaders;
            this.blockchainDaemon.OnTargetChainChanged += HandleTargetChainChanged;

            this.flushWorker = new WorkerMethod("HeadersRequestWorker.FlushWorker", FlushWorkerMethod, initialNotify: true, minIdleTime: TimeSpan.Zero, maxIdleTime: TimeSpan.MaxValue, logger: this.logger);
            this.flushQueue  = new ConcurrentQueue <Tuple <RemoteNode, IImmutableList <BlockHeader> > >();
        }
示例#18
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;
            }
        }
示例#19
0
        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 cache module
            this.kernel.Load(new CoreCacheModule());

            // initialize block view
            this.blockCache = this.kernel.Get <BlockCache>();

            // add rules module
            this.kernel.Load(new RulesModule(RulesEnum.MainNet));
            MainnetRules.IgnoreScriptErrors = true;

            // initialize the blockchain daemon
            this.kernel.Bind <CoreDaemon>().ToSelf().InSingletonScope();
            this.coreDaemon = this.kernel.Get <CoreDaemon>();

            // start the blockchain daemon
            this.coreDaemon.Start();

            // wait for initial work
            this.coreDaemon.ForceWorkAndWait();

            // verify initial state
            Assert.AreEqual(0, this.coreDaemon.TargetBlock.Height);
            //Assert.AreEqual(this.genesisBlock.Hash, this.blockchainDaemon.TargetChain.LastBlock.Hash);
            //Assert.AreEqual(this.genesisBlock.Hash, this.blockchainDaemon.ChainState.LastBlockHash);
        }
示例#20
0
        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);
        }
示例#21
0
        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);
        }
示例#22
0
        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);
        }
示例#23
0
        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));
        }
示例#24
0
 public DummyMonitor(CoreDaemon coreDaemon)
     : base(coreDaemon, keepEntries: false)
 {
     AddAddress(new First10000Address());
     AddAddress(new Top10000Address());
 }
示例#25
0
 public static void AssertDaemonAtBlock(int expectedHeight, UInt256 expectedBlockHash, CoreDaemon daemon)
 {
     Assert.AreEqual(expectedHeight, daemon.TargetBlock.Height);
     Assert.AreEqual(expectedHeight, daemon.TargetChain.Height);
     Assert.AreEqual(expectedBlockHash, daemon.TargetChain.LastBlock.Hash);
     Assert.AreEqual(expectedHeight, daemon.CurrentChain.Height);
     Assert.AreEqual(expectedBlockHash, daemon.CurrentChain.LastBlockHash);
 }
示例#26
0
        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;
            }
        }
示例#27
0
 public CoreRpcServer(CoreDaemon coreDaemon, int port)
 {
     this.coreDaemon = coreDaemon;
     this.listener   = new ListenerWorker(this, port);
 }
示例#28
0
 public CoreRpcServer(CoreDaemon coreDaemon, int port)
 {
     this.coreDaemon = coreDaemon;
     this.listener = new ListenerWorker(this, port);
 }
示例#29
0
        public MainWindow()
        {
            try
            {
                //TODO
                //**************************************************************
                var rulesType = RulesEnum.TestNet3;
                //var rulesType = RulesEnum.MainNet;

                var bypassValidation   = false;
                var ignoreScripts      = false;
                var ignoreSignatures   = false;
                var ignoreScriptErrors = true;

                var enablePruning = false;

                var cleanData       = false;
                var cleanChainState = false;

                //NOTE: Running with a cleaned chained state against a pruned blockchain does not work.
                //      It will see the data is missing, but won't redownload the blocks.
                //**************************************************************

                // directories
                var baseDirectory = Config.LocalStoragePath;
                if (false && Debugger.IsAttached)
                {
                    baseDirectory = Path.Combine(baseDirectory, "Debugger");
                }

                //TODO
                if (cleanData)
                {
                    try { Directory.Delete(Path.Combine(baseDirectory, "Data", rulesType.ToString()), recursive: true); }
                    catch (IOException) { }
                }
                else if (cleanChainState)
                {
                    try { Directory.Delete(Path.Combine(baseDirectory, "Data", rulesType.ToString(), "ChainState"), recursive: true); }
                    catch (IOException) { }
                }

                // initialize kernel
                this.kernel = new StandardKernel();

                // add logging module
                this.kernel.Load(new LoggingModule(baseDirectory, LogLevel.Info));

                // log startup
                this.logger = kernel.Get <Logger>();
                this.logger.Info("Starting up: {0}".Format2(DateTime.Now));

                var modules = new List <INinjectModule>();

                // add storage module
#if TEST_TOOL
                modules.Add(new MemoryStorageModule());
#elif MEMORY
                modules.Add(new MemoryStorageModule());
#else
                modules.Add(new EsentStorageModule(baseDirectory, rulesType, cacheSizeMaxBytes: int.MaxValue - 1));
                //ChainStateCursor.IndexOutputs = true;
#endif

                // add cache modules
                modules.Add(new NodeCacheModule());

                // add rules module
                modules.Add(new RulesModule(rulesType));

                // load modules
                this.kernel.Load(modules.ToArray());

                // initialize rules
                var rules = this.kernel.Get <IBlockchainRules>();
                rules.BypassValidation   = bypassValidation;
                rules.IgnoreScripts      = ignoreScripts;
                rules.IgnoreSignatures   = ignoreSignatures;
                rules.IgnoreScriptErrors = ignoreScriptErrors;

                // initialize the blockchain daemon
                this.coreDaemon = this.kernel.Get <CoreDaemon>();
                this.kernel.Bind <CoreDaemon>().ToConstant(this.coreDaemon).InTransientScope();

#if DUMMY_MONITOR
                var dummyMonitor = new DummyMonitor(this.logger);
                blockchainDaemon.SubscribeChainStateVisitor(dummyMonitor);
#endif

                // initialize p2p client
                this.localClient = this.kernel.Get <LocalClient>();
                this.kernel.Bind <LocalClient>().ToConstant(this.localClient).InTransientScope();

                // setup view model
#if DUMMY_MONITOR
                this.viewModel = new MainWindowViewModel(this.kernel, dummyMonitor);
#else
                this.viewModel = new MainWindowViewModel(this.kernel);
#endif
                InitializeComponent();
                this.viewModel.ViewBlockchainLast();

                // start the blockchain daemon
                this.coreDaemon.Start(enablePruning);

                // start p2p client
                var startThread = new Thread(() => this.localClient.Start());
                startThread.Name = "LocalClient.Start";
                startThread.Start();

                this.DataContext = this.viewModel;

#if TEST_TOOL
                var bitcoinjThread = new Thread(
                    () =>
                {
                    var projectFolder = Environment.CurrentDirectory;
                    while (projectFolder.Contains(@"\BitSharp.Client"))
                    {
                        projectFolder = Path.GetDirectoryName(projectFolder);
                    }

                    File.Delete(Path.Combine(projectFolder, "Bitcoinj-comparison.log"));

                    var javaProcessStartInfo = new ProcessStartInfo
                    {
                        FileName         = @"C:\Program Files\Java\jdk1.7.0_25\bin\java.exe",
                        WorkingDirectory = projectFolder,
                        Arguments        = @"-Djava.util.logging.config.file={0}\bitcoinj.log.properties -jar {0}\bitcoinj.jar".Format2(projectFolder),
                        UseShellExecute  = false
                    };

                    var javaProcess = Process.Start(javaProcessStartInfo);
                });
                bitcoinjThread.Start();
#endif
            }
            catch (Exception e)
            {
                if (this.logger != null)
                {
                    this.logger.Fatal("Application failed", e);
                    LogManager.Flush();
                }
                else
                {
                    Console.WriteLine(e);
                }

                Environment.Exit(-1);
            }
        }
示例#30
0
 public NodeRpcServer(CoreDaemon coreDaemon, int port)
     : base(coreDaemon, port)
 {
     this.coreDaemon = coreDaemon;
 }
示例#31
0
 public CoreRpcServer(Logger logger, CoreDaemon coreDaemon)
 {
     this.logger     = logger;
     this.coreDaemon = coreDaemon;
     this.listener   = new ListenerWorker(this, this.logger);
 }
示例#32
0
 public NodeRpcServer(Logger logger, CoreDaemon coreDaemon)
     : base(logger, coreDaemon)
 {
     this.coreDaemon = coreDaemon;
 }