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); }
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); } }
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"); }
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 { } }
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"); }
/// <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(); } }
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); } }