Example #1
0
        public void CanPersistMainchain()
        {
            var          main = new ConcurrentChain(LoadMainChain(), Network.Main);
            MemoryStream ms   = new MemoryStream();

            main.WriteTo(ms);
            ms.Position = 0;
            main.SetTip(main.Genesis);
            main.Load(ms);
            Assert.True(main.Tip.HasHeader);

            var original = main;

            foreach (var options in new[] {
                new ConcurrentChain.ChainSerializationFormat()
                {
                    SerializeBlockHeader = true,
                    SerializePrecomputedBlockHash = true,
                },
                new ConcurrentChain.ChainSerializationFormat()
                {
                    SerializeBlockHeader = true,
                    SerializePrecomputedBlockHash = false,
                },
                new ConcurrentChain.ChainSerializationFormat()
                {
                    SerializeBlockHeader = false,
                    SerializePrecomputedBlockHash = true,
                }
            })
            {
                main = new ConcurrentChain();
                main.SetTip(original.Tip);
                ms = new MemoryStream();
                main.WriteTo(ms, options);
                ms.Position = 0;
                main.SetTip(main.Genesis);
                main.Load(ms, Network.Main, options);
                Assert.Equal(options.SerializeBlockHeader, main.Tip.HasHeader);
                if (main.Tip.HasHeader)
                {
                    Assert.True(main.Tip.TryGetHeader(out var unused));
                }
                else
                {
                    Assert.False(main.Tip.TryGetHeader(out var unused));
                    Assert.Throws <InvalidOperationException>(() => main.Tip.Header);
                }
                Assert.Equal(original.Tip.HashBlock, main.Tip.HashBlock);
            }

            Assert.Throws <InvalidOperationException>(() =>
            {
                main.WriteTo(new MemoryStream(), new ConcurrentChain.ChainSerializationFormat()
                {
                    SerializeBlockHeader          = false,
                    SerializePrecomputedBlockHash = false,
                });
            });
        }
 private static void SaveChainCache(ConcurrentChain chain, string cacheLocation)
 {
     if (string.IsNullOrEmpty(cacheLocation))
     {
         return;
     }
     try
     {
         var cacheFile    = new FileInfo(cacheLocation);
         var cacheFileNew = new FileInfo(cacheLocation + ".new");
         using (var fs = new FileStream(cacheFileNew.FullName, FileMode.Create, FileAccess.Write, FileShare.None, 1024 * 1024 * 5))
         {
             chain.WriteTo(fs);
         }
         if (!cacheFile.Exists || cacheFile.Length < cacheFileNew.Length)
         {
             if (cacheFile.Exists)
             {
                 cacheFile.Delete();
             }
             cacheFileNew.MoveTo(cacheLocation);
         }
         else
         {
             cacheFileNew.Delete();
         }
     }
     catch             //Don't care if fail
     {
     }
 }
        public async Task SetToPersistentCacheAsync(ConcurrentChain chain)
        {
            var memorySteam = new MemoryStream();

            chain.WriteTo(memorySteam);

            await _blobStorage.SaveBlobAsync(BlobContainerName, _appSettings.BcnExploler.UsedNetwork().ToString(), memorySteam);
        }
Example #4
0
 private void SaveChain()
 {
     if (!Directory.Exists(_appDir))
     {
         Directory.CreateDirectory(_appDir);
     }
     using (var fs = File.Open(ChainFile(), FileMode.Create))
     {
         _chain.WriteTo(fs);
     }
 }
        private void CreateWrongChain()
        {
            string          walletFolderPath = WalletFileTools.GetWalletFolder(_wallet.Id);
            var             chainFilePath    = Path.Combine(walletFolderPath, "chain.dat");
            var             wrongNetwork     = Network.Main; // _wallet.NetworkChoice = Network.Testnet
            ConcurrentChain mainChain        = new ConcurrentChain(wrongNetwork);

            using (var fs = File.Open(chainFilePath, FileMode.Create))
            {
                mainChain.WriteTo(fs);
            }
        }
Example #6
0
        private void SaveChainInCache()
        {
            var suffix        = _Network.CryptoCode == "BTC" ? "" : _Network.CryptoCode;
            var cachePath     = Path.Combine(_Configuration.DataDir, $"{suffix}chain.dat");
            var cachePathTemp = Path.Combine(_Configuration.DataDir, $"{suffix}chain.dat.temp");

            Logs.Configuration.LogInformation($"{_Network.CryptoCode}: Saving chain to cache...");
            using (var fs = new FileStream(cachePathTemp, FileMode.Create, FileAccess.Write, FileShare.None, 1024 * 1024))
            {
                _Chain.WriteTo(fs);
                fs.Flush();
            }

            if (File.Exists(cachePath))
            {
                File.Delete(cachePath);
            }
            File.Move(cachePathTemp, cachePath);
            Logs.Configuration.LogInformation($"{_Network.CryptoCode}: Chain cached");
        }
Example #7
0
 private static void SaveChainCache(ConcurrentChain chain, string cacheLocation)
 {
     if (string.IsNullOrEmpty(cacheLocation))
     {
         return;
     }
     try
     {
         var file = new FileInfo(cacheLocation);
         if (!file.Exists || (DateTime.UtcNow - file.LastWriteTimeUtc) > TimeSpan.FromDays(1))
         {
             using (var fs = File.Open(cacheLocation, FileMode.Create))
             {
                 chain.WriteTo(fs);
             }
         }
     }
     catch //Don't care if fail
     {
     }
 }
Example #8
0
        private void SaveChainInCache()
        {
            var suffix        = _Network.CryptoCode == "BTC" ? "" : _Network.CryptoCode;
            var cachePath     = Path.Combine(_Configuration.DataDir, $"{suffix}chain-stripped.dat");
            var cachePathTemp = Path.Combine(_Configuration.DataDir, $"{suffix}chain-stripped.dat.temp");

            Logs.Configuration.LogInformation($"{_Network.CryptoCode}: Saving chain to cache...");
            using (var fs = new FileStream(cachePathTemp, FileMode.Create, FileAccess.Write, FileShare.None, 1024 * 1024))
            {
                _Chain.WriteTo(fs, new ConcurrentChain.ChainSerializationFormat()
                {
                    SerializeBlockHeader          = false,
                    SerializePrecomputedBlockHash = true
                });
                fs.Flush();
            }

            if (File.Exists(cachePath))
            {
                File.Delete(cachePath);
            }
            File.Move(cachePathTemp, cachePath);
            Logs.Configuration.LogInformation($"{_Network.CryptoCode}: Chain cached");
        }
Example #9
0
        /// <summary>
        /// Peridically persists any updated blockchain headers to disk.
        /// </summary>
        private static void PersistChain(ConcurrentChain chain, CancellationToken ct)
        {
            logger.DebugFormat("Starting persist blockchain task.");

            ct.ThrowIfCancellationRequested();

            int chainHeight = (chain != null) ? chain.Height : 0;

            while (ct.IsCancellationRequested == false)
            {
                if (chain.Height != chainHeight)
                {
                    using (var fs = File.Open(_chainFile, FileMode.Create))
                    {
                        chain.WriteTo(fs);
                    }

                    logger.DebugFormat("Chain height increased to {0} ({1})", chain.Height, DateTime.Now.ToString("HH:mm:ss"));
                    chainHeight = chain.Height;
                }

                Task.Delay(5000, ct).Wait();
            }
        }
        public async Task StartAsync()
        {
            if (_Disposed)
            {
                throw new ObjectDisposedException(nameof(NBxplorerInitializer));
            }
            _Starting.Reset();
            try
            {
                if (_Network.IsRegTest)
                {
                    if (await _RPC.GetBlockCountAsync() < 100)
                    {
                        Logs.Configuration.LogInformation($"Less than 100 blocks, mining some block for regtest");
                        await _RPC.GenerateAsync(101);
                    }
                    else
                    {
                        var header = await _RPC.GetBlockHeaderAsync(await _RPC.GetBestBlockHashAsync());

                        if ((DateTimeOffset.UtcNow - header.BlockTime) > TimeSpan.FromSeconds(24 * 60 * 60))
                        {
                            Logs.Configuration.LogInformation($"It has been a while nothing got mined on regtest... mining 10 blocks");
                            await _RPC.GenerateAsync(10);
                        }
                    }
                }

                var cachePath = Path.Combine(_Configuration.DataDir, "chain.dat");
                if (_Configuration.CacheChain && File.Exists(cachePath))
                {
                    Logs.Configuration.LogInformation($"Loading chain from cache...");
                    _Chain.Load(File.ReadAllBytes(cachePath));
                    Logs.Configuration.LogInformation($"Height: " + _Chain.Height);
                }

                var heightBefore = _Chain.Height;
                Logs.Configuration.LogInformation($"Loading chain from node...");
                using (var node = Node.Connect(_Network.Network, _Configuration.NodeEndpoint))
                {
                    var cts = new CancellationTokenSource();
                    cts.CancelAfter(5000);
                    node.VersionHandshake(cts.Token);
                    node.SynchronizeChain(_Chain);
                }
                Logs.Configuration.LogInformation("Height: " + _Chain.Height);

                if (_Configuration.CacheChain && heightBefore != _Chain.Height)
                {
                    Logs.Configuration.LogInformation($"Saving chain to cache...");
                    var ms = new MemoryStream();
                    _Chain.WriteTo(ms);
                    File.WriteAllBytes(cachePath, ms.ToArray());
                    Logs.Configuration.LogInformation($"Saved");
                }


                AddressManager manager = new AddressManager();
                manager.Add(new NetworkAddress(_Configuration.NodeEndpoint), IPAddress.Loopback);
                NodesGroup group = new NodesGroup(_Network.Network, new NodeConnectionParameters()
                {
                    Services          = NodeServices.Nothing,
                    IsRelay           = true,
                    TemplateBehaviors =
                    {
                        new AddressManagerBehavior(manager)
                        {
                            PeersToDiscover = 1,
                            Mode            = AddressManagerBehaviorMode.None
                        },
                        new ExplorerBehavior(_Repository, _Chain, _Invoker, _Events)
                        {
                            StartHeight = _Configuration.StartHeight
                        },
                        new ChainBehavior(_Chain)
                        {
                            CanRespondToGetHeaders = false
                        }
                    }
                });
                group.AllowSameGroup        = true;
                group.MaximumNodeConnection = 1;
                group.Connect();
                _Group = group;
            }
            finally { _Starting.Set(); }
        }
Example #11
0
        public ExplorerRuntime(ExplorerConfiguration configuration)
        {
            if (configuration == null)
            {
                throw new ArgumentNullException("configuration");
            }
            Network      = configuration.Network;
            Chain        = new ConcurrentChain(Network.GetGenesis().Header);
            RPC          = configuration.RPC.ConfigureRPCClient(configuration.Network);
            NodeEndpoint = configuration.NodeEndpoint;
            ServerUrls   = configuration.GetUrls();

            var cachePath = Path.Combine(configuration.DataDir, "chain.dat");

            if (configuration.CacheChain)
            {
                Logs.Configuration.LogInformation($"Loading chain from cache...");
                if (File.Exists(cachePath))
                {
                    Chain.Load(File.ReadAllBytes(cachePath));
                }
            }

            Logs.Configuration.LogInformation($"Loading chain from node...");
            var heightBefore = Chain.Height;

            try
            {
                if (!configuration.RPC.NoTest)
                {
                    Logs.Configuration.LogInformation("Trying to connect to node: " + configuration.NodeEndpoint);
                    using (var node = Node.Connect(Network, configuration.NodeEndpoint))
                    {
                        var cts = new CancellationTokenSource();
                        cts.CancelAfter(5000);
                        node.VersionHandshake(cts.Token);
                        node.SynchronizeChain(Chain);
                    }
                    Logs.Configuration.LogInformation("Node connection successfull");
                }
            }
            catch (Exception ex)
            {
                Logs.Configuration.LogError("Error while connecting to node: " + ex.Message);
                throw new ConfigException();
            }

            Logs.Configuration.LogInformation($"Chain loaded from node");

            if (configuration.CacheChain && heightBefore != Chain.Height)
            {
                Logs.Configuration.LogInformation($"Saving chain to cache...");
                var ms = new MemoryStream();
                Chain.WriteTo(ms);
                File.WriteAllBytes(cachePath, ms.ToArray());
            }

            var dbPath = Path.Combine(configuration.DataDir, "db");

            Repository = new Repository(dbPath, true);
            if (configuration.Rescan)
            {
                Logs.Configuration.LogInformation("Rescanning...");
                Repository.SetIndexProgress(null);
            }
        }