private void LoadChainFromCache() { var suffix = _Network.CryptoCode == "BTC" ? "" : _Network.CryptoCode; { var legacyCachePath = Path.Combine(_Configuration.DataDir, $"{suffix}chain.dat"); if (_Configuration.CacheChain && File.Exists(legacyCachePath)) { Logs.Configuration.LogInformation($"{_Network.CryptoCode}: Loading chain from cache..."); var chain = new ConcurrentChain(_Network.NBitcoinNetwork); chain.Load(File.ReadAllBytes(legacyCachePath), _Network.NBitcoinNetwork); LoadSlimAndSaveToSlimFormat(chain); File.Delete(legacyCachePath); Logs.Configuration.LogInformation($"{_Network.CryptoCode}: Height: " + _Chain.Height); return; } } { var cachePath = Path.Combine(_Configuration.DataDir, $"{suffix}chain-stripped.dat"); if (_Configuration.CacheChain && File.Exists(cachePath)) { Logs.Configuration.LogInformation($"{_Network.CryptoCode}: Loading chain from cache..."); var chain = new ConcurrentChain(_Network.NBitcoinNetwork); chain.Load(File.ReadAllBytes(cachePath), _Network.NBitcoinNetwork, new ConcurrentChain.ChainSerializationFormat() { SerializeBlockHeader = false, SerializePrecomputedBlockHash = true, }); LoadSlimAndSaveToSlimFormat(chain); File.Delete(cachePath); Logs.Configuration.LogInformation($"{_Network.CryptoCode}: Height: " + _Chain.Height); return; } } { var slimCachePath = Path.Combine(_Configuration.DataDir, $"{suffix}chain-slim.dat"); if (_Configuration.CacheChain && File.Exists(slimCachePath)) { Logs.Configuration.LogInformation($"{_Network.CryptoCode}: Loading chain from cache..."); using (var file = new FileStream(slimCachePath, FileMode.Open, FileAccess.Read, FileShare.None, 1024 * 1024)) { _Chain.Load(file); } Logs.Configuration.LogInformation($"{_Network.CryptoCode}: Height: " + _Chain.Height); return; } } }
public void CanHandshakeWithSeveralTemplateBehaviors() { using (var builder = NodeBuilderEx.Create()) { var node = builder.CreateNode(true); node.Generate(101); AddressManager manager = new AddressManager(); manager.Add(new NetworkAddress(node.NodeEndpoint), IPAddress.Loopback); var chain = new SlimChain(builder.Network.GenesisHash); NodesGroup group = new NodesGroup(builder.Network, new NodeConnectionParameters() { Services = NodeServices.Nothing, IsRelay = true, TemplateBehaviors = { new AddressManagerBehavior(manager) { PeersToDiscover = 1, Mode = AddressManagerBehaviorMode.None }, new SlimChainBehavior(chain), new PingPongBehavior() } }); group.AllowSameGroup = true; group.MaximumNodeConnection = 1; var connecting = WaitConnected(group); try { group.Connect(); connecting.GetAwaiter().GetResult(); Eventually(() => { Assert.Equal(101, chain.Height); }); var ms = new MemoryStream(); chain.Save(ms); var chain2 = new SlimChain(chain.Genesis); ms.Position = 0; chain2.Load(ms); Assert.Equal(chain.Tip, chain2.Tip); using (var fs = new FileStream("test.slim.dat", FileMode.Create, FileAccess.Write, FileShare.None, 1024 * 1024)) { chain.Save(fs); fs.Flush(); } chain.ResetToGenesis(); using (var fs = new FileStream("test.slim.dat", FileMode.Open, FileAccess.Read, FileShare.None, 1024 * 1024)) { chain.Load(fs); } Assert.Equal(101, chain2.Height); chain.ResetToGenesis(); } finally { group.Disconnect(); } } }
public void CanBuildSlimChain() { var b0 = RandomUInt256(); SlimChain chain = new SlimChain(b0); var b1 = RandomUInt256(); Assert.Throws <ArgumentException>(() => chain.TrySetTip(b0, b0)); Assert.True(chain.TrySetTip(b1, b0)); var b2 = RandomUInt256(); Assert.True(chain.TrySetTip(b2, b1)); Assert.True(chain.TrySetTip(b2, b1)); Assert.Equal(b0, chain.Genesis); Assert.Equal(b2, chain.Tip); Assert.True(chain.Contains(b2)); Assert.Equal(2, chain.Height); Assert.False(chain.TrySetTip(b1, b0, true)); Assert.True(chain.TrySetTip(b1, b0, false)); Assert.Equal(b1, chain.Tip); Assert.False(chain.TryGetHeight(b2, out int height)); Assert.False(chain.Contains(b2)); Assert.True(chain.TryGetHeight(b1, out height)); Assert.Equal(1, height); Assert.True(chain.TrySetTip(b2, b1)); Assert.Throws <ArgumentException>(() => chain.TrySetTip(b1, b2)); // Incoherent Assert.Throws <ArgumentException>(() => chain.TrySetTip(b0, b1, true)); // Genesis block should not have previosu Assert.Throws <ArgumentException>(() => chain.TrySetTip(b0, b1, false)); Assert.True(chain.TrySetTip(b0, null)); Assert.Equal(0, chain.Height); Assert.True(chain.TrySetTip(b1, b0, true)); Assert.True(chain.TrySetTip(b2, b1)); var b3 = RandomUInt256(); var block = chain.GetBlock(b2); Assert.Equal(b2, block.Hash); Assert.Equal(b1, block.Previous); Assert.Equal(2, block.Height); Assert.Null(chain.GetBlock(b3)); block = chain.GetBlock(2); Assert.Equal(b2, block.Hash); Assert.Equal(b1, block.Previous); Assert.Equal(2, block.Height); Assert.Null(chain.GetBlock(3)); Assert.Null(chain.GetBlock(-1)); block = chain.GetBlock(0); Assert.Equal(b0, block.Hash); Assert.Null(block.Previous); Assert.Equal(0, block.Height); var chain2 = new SlimChain(RandomUInt256()); var ms = new MemoryStream(); chain.Save(ms); ms.Position = 0; // Not good genesis Assert.Throws <InvalidOperationException>(() => chain2.Load(ms)); chain2 = new SlimChain(b0); ms.Position = 0; chain2.Load(ms); Assert.Equal(chain.Tip, chain2.Tip); Assert.Equal(2, chain2.Height); }