From 5a5e6c5ce9505449e414ab7335d2c773c127954b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=BCseyin=20Uslu?= Date: Thu, 4 Sep 2014 10:41:52 +0300 Subject: [PATCH 01/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d8fa41503..61e2737a7 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ CoiniumServ supports storage layer interfaces that you can extend to implement y * __MPOS Layer__: a compatibility layer based on mysql that supports MPOS whenever you want payments to be handled by MPOS. ###### Development Model -* Strictly [follows](https://github.com/CoiniumServ/CoiniumServ/tree/develop/src/Tests) the [Test Driven Development](http://en.wikipedia.org/wiki/Test-driven_development) model. We have implemented extensive [tests](https://github.com/CoiniumServ/CoiniumServ/tree/develop/src/Tests) for all important functionality and never merge in code that breaks tests and stuff. Yet again, when a new functionality is introduced we also expect proper tests to be implemented within the PR. In simple words, most probably you won't notice any functionality-breaking changes within the repository. +* We have implemented extensive [tests](https://github.com/CoiniumServ/CoiniumServ/tree/develop/src/Tests) for all important functionality and never merge in code that breaks tests and stuff. Yet again, when a new functionality is introduced we also expect proper tests to be implemented within the PR. In simple words, most probably you won't notice any functionality-breaking changes within the repository. * A strict ruleset for the [Development Model](https://github.com/CoiniumServ/CoiniumServ/wiki/Development-Model). You can follow our bleeding-edge [Develop](https://github.com/CoiniumServ/CoiniumServ) branch or stay with-in the stable [Master](https://github.com/CoiniumServ/CoiniumServ/tree/master) branch. From d3e22e2708f1162b83dd1a0b6acbdc60ac60aa44 Mon Sep 17 00:00:00 2001 From: bonesoul Date: Thu, 4 Sep 2014 11:11:42 +0300 Subject: [PATCH 02/14] Fixed a bug in HybridStorageLayer.cs:UpdateBlock() where blocks were not correctly set as confirmed once they were actually so. --- src/CoiniumServ/Persistance/Layers/Hybrid/HybridStorageLayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CoiniumServ/Persistance/Layers/Hybrid/HybridStorageLayer.cs b/src/CoiniumServ/Persistance/Layers/Hybrid/HybridStorageLayer.cs index e8b3e2ab9..a7bd0b508 100644 --- a/src/CoiniumServ/Persistance/Layers/Hybrid/HybridStorageLayer.cs +++ b/src/CoiniumServ/Persistance/Layers/Hybrid/HybridStorageLayer.cs @@ -280,7 +280,7 @@ public void UpdateBlock(IPaymentRound round) { orphaned = round.Block.Status == BlockStatus.Orphaned, confirmed = round.Block.Status == BlockStatus.Confirmed, - height = round.Block.Status + height = round.Block.Height }); } } From 483f6f80a5e67503a2cf5dad5f3044a1ef0d45b4 Mon Sep 17 00:00:00 2001 From: bonesoul Date: Thu, 4 Sep 2014 12:32:20 +0300 Subject: [PATCH 03/14] re-added nancy.viewengine.razor --- src/CoiniumServ/App.config | 23 ++++++++++++----------- src/CoiniumServ/CoiniumServ.csproj | 12 ++++++++++++ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/CoiniumServ/App.config b/src/CoiniumServ/App.config index 547ad3c5c..4bc915578 100644 --- a/src/CoiniumServ/App.config +++ b/src/CoiniumServ/App.config @@ -5,19 +5,12 @@
+ - - - - - - - - - - + + @@ -26,4 +19,12 @@ - + + + + + + + + + diff --git a/src/CoiniumServ/CoiniumServ.csproj b/src/CoiniumServ/CoiniumServ.csproj index 4a2a75fcf..9711925ae 100644 --- a/src/CoiniumServ/CoiniumServ.csproj +++ b/src/CoiniumServ/CoiniumServ.csproj @@ -848,6 +848,7 @@ PreserveNewest + PreserveNewest @@ -1045,6 +1046,17 @@ if $(ConfigurationName) == Debug ( xcopy /s /y /R "$(SolutionDir)packages\Nancy.Viewengines.Razor.0.23.2\BuildProviders\Nancy.ViewEngines.Razor.BuildProviders.dll" "$(ProjectDir)bin\" xcopy /s /y /R "$(SolutionDir)packages\Nancy.Viewengines.Razor.0.23.2\lib\net40\Nancy.ViewEngines.Razor.dll" "$(ProjectDir)bin\" +) + + + +if $(ConfigurationName) == Debug ( +xcopy /s /y /R "$(SolutionDir)packages\Nancy.Viewengines.Razor.0.23.2\BuildProviders\Nancy.ViewEngines.Razor.BuildProviders.dll" "$(ProjectDir)bin\" +xcopy /s /y /R "$(SolutionDir)packages\Nancy.Viewengines.Razor.0.23.2\lib\net40\Nancy.ViewEngines.Razor.dll" "$(ProjectDir)bin\" +) +if $(ConfigurationName) == Debug ( +xcopy /s /y /R "$(SolutionDir)packages\Nancy.Viewengines.Razor.0.23.2\BuildProviders\Nancy.ViewEngines.Razor.BuildProviders.dll" "$(ProjectDir)bin\" +xcopy /s /y /R "$(SolutionDir)packages\Nancy.Viewengines.Razor.0.23.2\lib\Net40\Nancy.ViewEngines.Razor.dll" "$(ProjectDir)bin\" )
-

Per Pool Statistics

+

Per Pool Statistics

@@ -152,6 +151,7 @@ Workers Algorithm Current Block + Status @@ -160,14 +160,14 @@ @pool.Config.Coin.Name @pool.Hashrate.GetReadableHashrate() - @pool.NetworkStats.Hashrate.GetReadableHashrate() - @pool.NetworkStats.Difficulty + @pool.NetworkInfo.Hashrate.GetReadableHashrate() + @pool.NetworkInfo.Difficulty @pool.MinerManager.Count @pool.Config.Coin.Algorithm - @pool.NetworkStats.Round + @pool.NetworkInfo.Round + @(pool.NetworkInfo.Healthy ? "healty" : "warnings!") - } - + }
diff --git a/src/CoiniumServ/web/default/pool.cshtml b/src/CoiniumServ/web/default/pool.cshtml index 274cf278d..e7b39885d 100644 --- a/src/CoiniumServ/web/default/pool.cshtml +++ b/src/CoiniumServ/web/default/pool.cshtml @@ -5,67 +5,112 @@ @{ Layout = "layout.cshtml"; }
-
-
+ + -
-
+
+
-

Block Stats

+

Block Stats

@@ -77,7 +122,7 @@
-

Latest Blocks

+

Latest Blocks

From e2e688b55b28bdc19462dcd5ea63e140edbf8621 Mon Sep 17 00:00:00 2001 From: bonesoul Date: Thu, 4 Sep 2014 16:47:51 +0300 Subject: [PATCH 08/14] Re-added hashrate calculation support. Implemented hybrid-layer hashrate calculation support and needs to be tested. MPOS layer also needs to be worked (#407). Removed SupportsShareStorage, SupportsBlockStorage, SupportsPaymentsStorage properties from IStorageLayer as they were not being used. Moved config.json website:stats section to upper level and renamed as statistics - need to fix the code too. --- .../Layers/Empty/EmptyStorageLayer.cs | 13 +++-- .../Layers/Hybrid/HybridStorageLayer.cs | 52 +++++++++++++++++-- .../Persistance/Layers/IStorageLayer.cs | 10 ++-- .../Layers/Mpos/MposStorageLayer.cs | 13 +++-- src/CoiniumServ/Pools/Pool.cs | 32 +++++++----- src/CoiniumServ/Server/Web/WebServer.cs | 2 + src/CoiniumServ/Server/Web/WebServerConfig.cs | 2 +- src/CoiniumServ/config/config-example.json | 20 ++++--- src/Tests/Pools/PoolTests.cs | 16 ++++-- 9 files changed, 121 insertions(+), 39 deletions(-) diff --git a/src/CoiniumServ/Persistance/Layers/Empty/EmptyStorageLayer.cs b/src/CoiniumServ/Persistance/Layers/Empty/EmptyStorageLayer.cs index 2616dcb90..6084ec723 100644 --- a/src/CoiniumServ/Persistance/Layers/Empty/EmptyStorageLayer.cs +++ b/src/CoiniumServ/Persistance/Layers/Empty/EmptyStorageLayer.cs @@ -32,9 +32,6 @@ namespace CoiniumServ.Persistance.Layers.Empty public class EmptyStorageLayer : IStorageLayer { public bool IsEnabled { get; private set; } - public bool SupportsShareStorage { get { return false; } } - public bool SupportsBlockStorage { get { return false; } } - public bool SupportsPaymentsStorage { get { return false; } } public void AddShare(IShare share) { @@ -66,6 +63,16 @@ public Dictionary> GetShares(IList>(); // return an empty dictionary. } + public void DeleteExpiredHashrateData(int until) + { + return; // just skip. + } + + public IDictionary GetHashrateData(int since) + { + return new Dictionary(); // return an empty dictionary. + } + public void AddBlock(IShare share) { return; // just skip. diff --git a/src/CoiniumServ/Persistance/Layers/Hybrid/HybridStorageLayer.cs b/src/CoiniumServ/Persistance/Layers/Hybrid/HybridStorageLayer.cs index a7bd0b508..109e5d1e4 100644 --- a/src/CoiniumServ/Persistance/Layers/Hybrid/HybridStorageLayer.cs +++ b/src/CoiniumServ/Persistance/Layers/Hybrid/HybridStorageLayer.cs @@ -46,9 +46,6 @@ namespace CoiniumServ.Persistance.Layers.Hybrid public class HybridStorageLayer : IStorageLayer { public bool IsEnabled { get; private set; } - public bool SupportsShareStorage { get { return true; } } - public bool SupportsBlockStorage { get { return true; } } - public bool SupportsPaymentsStorage { get { return true; } } private readonly IDaemonClient _daemonClient; @@ -238,6 +235,55 @@ public Dictionary> GetShares(IList GetHashrateData(int since) + { + var hashrates = new Dictionary(); + + try + { + if (!IsEnabled || !_redisProvider.IsConnected) + return hashrates; + + var key = string.Format("{0}:hashrate", _coin); + + var results = _redisProvider.Client.ZRangeByScore(key, since, double.PositiveInfinity); + + foreach (var result in results) + { + var data = result.Split(':'); + var share = double.Parse(data[0].Replace(',', '.'), CultureInfo.InvariantCulture); + var worker = data[1]; + + if (!hashrates.ContainsKey(worker)) + hashrates.Add(worker, 0); + + hashrates[worker] += share; + } + } + catch (Exception e) + { + _logger.Error("An exception occured while getting hashrate data: {0:l}", e.Message); + } + + return hashrates; + } + public void AddBlock(IShare share) { try diff --git a/src/CoiniumServ/Persistance/Layers/IStorageLayer.cs b/src/CoiniumServ/Persistance/Layers/IStorageLayer.cs index cc71736e5..c7762f8ab 100644 --- a/src/CoiniumServ/Persistance/Layers/IStorageLayer.cs +++ b/src/CoiniumServ/Persistance/Layers/IStorageLayer.cs @@ -37,8 +37,6 @@ public interface IStorageLayer #region share storage - bool SupportsShareStorage { get; } - void AddShare(IShare share); void RemoveShares(IPaymentRound round); @@ -51,12 +49,14 @@ public interface IStorageLayer Dictionary> GetShares(IList rounds); + void DeleteExpiredHashrateData(int until); + + IDictionary GetHashrateData(int since); + #endregion #region block storage - bool SupportsBlockStorage { get; } - void AddBlock(IShare share); void UpdateBlock(IPaymentRound round); @@ -78,8 +78,6 @@ public interface IStorageLayer #region payments storage - bool SupportsPaymentsStorage { get; } - Dictionary GetPreviousBalances(); void SetBalances(IList workerBalances); diff --git a/src/CoiniumServ/Persistance/Layers/Mpos/MposStorageLayer.cs b/src/CoiniumServ/Persistance/Layers/Mpos/MposStorageLayer.cs index 1055c5170..4b5c906fc 100644 --- a/src/CoiniumServ/Persistance/Layers/Mpos/MposStorageLayer.cs +++ b/src/CoiniumServ/Persistance/Layers/Mpos/MposStorageLayer.cs @@ -42,9 +42,6 @@ namespace CoiniumServ.Persistance.Layers.Mpos public class MposStorageLayer : IStorageLayer { public bool IsEnabled { get; private set; } - public bool SupportsShareStorage { get { return true; } } - public bool SupportsBlockStorage { get { return true; } } - public bool SupportsPaymentsStorage { get { return true; } } private readonly IMySqlProvider _mySqlProvider; @@ -152,6 +149,16 @@ public Dictionary> GetShares(IList GetHashrateData(int since) + { + throw new NotImplementedException(); + } + public void AddBlock(IShare share) { // Blocks are handled by MPOS by itself, we don't need to persist found block data. diff --git a/src/CoiniumServ/Pools/Pool.cs b/src/CoiniumServ/Pools/Pool.cs index 7147fd41e..f69dedbce 100644 --- a/src/CoiniumServ/Pools/Pool.cs +++ b/src/CoiniumServ/Pools/Pool.cs @@ -25,10 +25,9 @@ using System.Linq; using System.Security.Cryptography; using CoiniumServ.Banning; -using CoiniumServ.Coin.Helpers; +using CoiniumServ.Configuration; using CoiniumServ.Cryptology.Algorithms; using CoiniumServ.Daemon; -using CoiniumServ.Daemon.Exceptions; using CoiniumServ.Factories; using CoiniumServ.Jobs.Manager; using CoiniumServ.Miners; @@ -41,7 +40,7 @@ using CoiniumServ.Server.Mining; using CoiniumServ.Server.Mining.Service; using CoiniumServ.Shares; -using CoiniumServ.Statistics; +using CoiniumServ.Utils.Helpers.Time; using CoiniumServ.Utils.Helpers.Validation; using Newtonsoft.Json; using Serilog; @@ -75,8 +74,12 @@ public class Pool : IPool private IStorageLayer _storageLayer; + private readonly IConfigManager _configManager; + private Dictionary _servers; + private double _shareMultiplier; // share multiplier to be used in hashrate calculation. + private readonly ILogger _logger; /// @@ -88,12 +91,15 @@ public class Pool : IPool /// Initializes a new instance of the class. /// /// + /// /// - public Pool(IPoolConfig poolConfig, IObjectFactory objectFactory) + public Pool(IPoolConfig poolConfig, IConfigManager configManager, IObjectFactory objectFactory) { - Enforce.ArgumentNotNull(() => poolConfig); // make sure we have a config instance supplied. + Enforce.ArgumentNotNull(() => poolConfig); // make sure we have a pool-config instance supplied. + Enforce.ArgumentNotNull(() => configManager); // make sure we have a config-manager instance supplied. Enforce.ArgumentNotNull(() => objectFactory); // make sure we have a objectFactory instance supplied. + _configManager = configManager; _objectFactory = objectFactory; // TODO: validate pool central wallet & rewards within the startup. @@ -120,7 +126,9 @@ private void InitDaemon() _daemonClient = _objectFactory.GetDaemonClient(Config); HashAlgorithm = _objectFactory.GetHashAlgorithm(Config.Coin.Algorithm); - NetworkInfo = _objectFactory.GetNetworkInfo(_daemonClient, HashAlgorithm, Config); + NetworkInfo = _objectFactory.GetNetworkInfo(_daemonClient, HashAlgorithm, Config); + + _shareMultiplier = Math.Pow(2, 32) / HashAlgorithm.Multiplier; // will be used in hashrate calculation. } private void InitStorage() @@ -247,13 +255,13 @@ private void RecacheRound() private void CalculateHashrate() { - //// read hashrate stats. - //var windowTime = TimeHelpers.NowInUnixTime() - _statisticsConfig.HashrateWindow; - //_storage.DeleteExpiredHashrateData(windowTime); - //var hashrates = _storage.GetHashrateData(windowTime); + // read hashrate stats. + var windowTime = TimeHelpers.NowInUnixTime() - _configManager.WebServerConfig.Statistics.HashrateWindow; + _storageLayer.DeleteExpiredHashrateData(windowTime); + var hashrates = _storageLayer.GetHashrateData(windowTime); - //double total = hashrates.Sum(pair => pair.Value); - //Hashrate = Convert.ToUInt64(_shareMultiplier * total / _statisticsConfig.HashrateWindow); + double total = hashrates.Sum(pair => pair.Value); + Hashrate = Convert.ToUInt64(_shareMultiplier * total / _configManager.WebServerConfig.Statistics.HashrateWindow); } } } diff --git a/src/CoiniumServ/Server/Web/WebServer.cs b/src/CoiniumServ/Server/Web/WebServer.cs index 877718f9e..d4167c32f 100644 --- a/src/CoiniumServ/Server/Web/WebServer.cs +++ b/src/CoiniumServ/Server/Web/WebServer.cs @@ -33,6 +33,8 @@ public class WebServer : HttpServer, IWebServer public WebServer(INancyBootstrapper webBootstrapper, IConfigManager configManager) : base(webBootstrapper) { + // todo: instead require webserver config. + var config = configManager.WebServerConfig; BindIP = config.BindInterface; Port = config.Port; diff --git a/src/CoiniumServ/Server/Web/WebServerConfig.cs b/src/CoiniumServ/Server/Web/WebServerConfig.cs index 5807dff14..b810b58d2 100644 --- a/src/CoiniumServ/Server/Web/WebServerConfig.cs +++ b/src/CoiniumServ/Server/Web/WebServerConfig.cs @@ -32,7 +32,7 @@ public class WebServerConfig : IWebServerConfig public bool Enabled { get; private set; } public string BindInterface { get; private set; } public int Port { get; private set; } - public IStatisticsConfig Statistics { get; private set; } + public IStatisticsConfig Statistics { get; private set; } // todo: move this out of webserver config. public IBackendConfig Backend { get; private set; } public bool Valid { get; private set; } public WebServerConfig(dynamic config) diff --git a/src/CoiniumServ/config/config-example.json b/src/CoiniumServ/config/config-example.json index d184f67b4..ff256b05e 100644 --- a/src/CoiniumServ/config/config-example.json +++ b/src/CoiniumServ/config/config-example.json @@ -9,6 +9,18 @@ "name": "CoiniumServ.com" }, + # ------------------------------- + # Statistics Configuration + # ------------------------------- + + # updateInterval: interval for recaching statistics. + # hashrateWindow: how many seconds worth of shares should be gathered to generate hashrate. + + "statistics": { + "updateInterval": 60, + "hashrateWindow": 300 + }, + # ------------------------------- # Website Configuration # ------------------------------- @@ -16,22 +28,14 @@ # enabled: set this true to enable frontend. # bind: interface to bind webserver. # port: port to listen for http connections. - # stats: - # updateInterval: interval for recaching statistics. - # hashrateWindow: how many seconds worth of shares should be gathered to generate hashrate. # backend: # enabled: set this true to enable admin backend. # password: password for enabling administrator - # website configuration "website": { "enabled": true, "bind": "127.0.0.1", "port": 80, - "stats": { - "updateInterval": 60, - "hashrateWindow": 300 - }, "backend" : { "metrics": { "enabled": false diff --git a/src/Tests/Pools/PoolTests.cs b/src/Tests/Pools/PoolTests.cs index fe99d5a82..bf51d188a 100644 --- a/src/Tests/Pools/PoolTests.cs +++ b/src/Tests/Pools/PoolTests.cs @@ -22,6 +22,7 @@ #endregion using System; +using CoiniumServ.Configuration; using CoiniumServ.Daemon; using CoiniumServ.Daemon.Responses; using CoiniumServ.Factories; @@ -37,6 +38,7 @@ public class PoolTests // object mocks. private readonly IObjectFactory _objectFactory; private readonly IDaemonClient _daemonClient; + private readonly IConfigManager _configManager; private readonly IPoolConfig _config; /// @@ -47,6 +49,9 @@ public PoolTests() // factory mockup. _objectFactory = Substitute.For(); + // config-manager mockup + _configManager = Substitute.For(); + // pool-config mockup. _config = Substitute.For(); _config.Daemon.Valid.Returns(true); @@ -64,7 +69,7 @@ public PoolTests() [Fact] public void ConstructorTest_NonNullParams_ShouldSuccess() { - var pool = new Pool(_config, _objectFactory); // create the pool instance. + var pool = new Pool(_config,_configManager, _objectFactory); // create the pool instance. pool.Should().Not.Be.Null(); pool.InstanceId.Should().Be.GreaterThan((UInt32)0); // pool should be already created an instance id. @@ -78,12 +83,17 @@ public void ConstructorTest_NullParams_ShouldThrowException() { Assert.Throws(() => { - new Pool(null, _objectFactory); + new Pool(null, _configManager, _objectFactory); }).Message.Should().Contain("poolConfig"); Assert.Throws(() => { - new Pool(_config, null); + new Pool(_config, null, _objectFactory); + }).Message.Should().Contain("configManager"); + + Assert.Throws(() => + { + new Pool(_config, _configManager, null); }).Message.Should().Contain("objectFactory"); } } From b07d1b6be2d16de8179bdd102070bbca21bcc2ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=BCseyin=20Uslu?= Date: Thu, 4 Sep 2014 21:07:41 +0300 Subject: [PATCH 09/14] Moved StatisticsConfig.cs out of WebServerConfig.cs. --- .../Configuration/ConfigManager.cs | 5 +- .../Configuration/IConfigManager.cs | 7 +- .../Container/Registries/ClassRegistry.cs | 5 +- .../Container/Registries/ManagerRegistry.cs | 15 ++-- .../Container/Registries/StorageRegistry.cs | 2 - src/CoiniumServ/Factories/IObjectFactory.cs | 46 ++++++------ src/CoiniumServ/Factories/ObjectFactory.cs | 73 +++++++++---------- src/CoiniumServ/Pools/Pool.cs | 4 +- .../Server/Web/IWebServerConfig.cs | 5 +- src/CoiniumServ/Server/Web/WebServer.cs | 4 - src/CoiniumServ/Server/Web/WebServerConfig.cs | 3 - .../Statistics/StatisticsManager.cs | 9 ++- 12 files changed, 86 insertions(+), 92 deletions(-) diff --git a/src/CoiniumServ/Configuration/ConfigManager.cs b/src/CoiniumServ/Configuration/ConfigManager.cs index db33d1ca7..a80d22f3b 100644 --- a/src/CoiniumServ/Configuration/ConfigManager.cs +++ b/src/CoiniumServ/Configuration/ConfigManager.cs @@ -29,6 +29,7 @@ using CoiniumServ.Logging; using CoiniumServ.Pools; using CoiniumServ.Server.Web; +using CoiniumServ.Statistics; using CoiniumServ.Utils.Helpers.IO; using Serilog; @@ -36,9 +37,10 @@ namespace CoiniumServ.Configuration { public class ConfigManager:IConfigManager { + public IStackConfig StackConfig { get; private set; } + public IStatisticsConfig StatisticsConfig { get; private set; } public IWebServerConfig WebServerConfig { get; private set; } public ILogConfig LogConfig { get; private set; } - public IStackConfig StackConfig { get; private set; } public List PoolConfigs { get; private set; } private const string GlobalConfigFilename = "config/config.json"; // global config filename. @@ -76,6 +78,7 @@ private void ReadGlobalConfig() } StackConfig = new StackConfig(data.stack); + StatisticsConfig = new StatisticsConfig(data.statistics); WebServerConfig = new WebServerConfig(data.website); LogConfig = new LogConfig(data.logging); } diff --git a/src/CoiniumServ/Configuration/IConfigManager.cs b/src/CoiniumServ/Configuration/IConfigManager.cs index 98fa4f1e2..791440e45 100644 --- a/src/CoiniumServ/Configuration/IConfigManager.cs +++ b/src/CoiniumServ/Configuration/IConfigManager.cs @@ -24,17 +24,20 @@ using CoiniumServ.Logging; using CoiniumServ.Pools; using CoiniumServ.Server.Web; +using CoiniumServ.Statistics; namespace CoiniumServ.Configuration { public interface IConfigManager { + IStackConfig StackConfig { get; } + + IStatisticsConfig StatisticsConfig { get; } + IWebServerConfig WebServerConfig { get; } ILogConfig LogConfig { get; } - IStackConfig StackConfig { get; } - List PoolConfigs { get; } void Initialize(); diff --git a/src/CoiniumServ/Container/Registries/ClassRegistry.cs b/src/CoiniumServ/Container/Registries/ClassRegistry.cs index aa4a3eda6..8dfccc9a6 100644 --- a/src/CoiniumServ/Container/Registries/ClassRegistry.cs +++ b/src/CoiniumServ/Container/Registries/ClassRegistry.cs @@ -45,7 +45,7 @@ public ClassRegistry(IApplicationContext applicationContext) public void RegisterInstances() { - // pool + // per-pool objects _applicationContext.Container.Register().AsMultiInstance(); _applicationContext.Container.Register().AsMultiInstance(); _applicationContext.Container.Register().AsMultiInstance(); @@ -54,9 +54,6 @@ public void RegisterInstances() _applicationContext.Container.Register().AsMultiInstance(); _applicationContext.Container.Register().AsMultiInstance(); - // statistics - _applicationContext.Container.Register().AsSingleton(); - // config _applicationContext.Container.Register().AsMultiInstance(); _applicationContext.Container.Register().AsMultiInstance(); diff --git a/src/CoiniumServ/Container/Registries/ManagerRegistry.cs b/src/CoiniumServ/Container/Registries/ManagerRegistry.cs index b78980786..c75439867 100644 --- a/src/CoiniumServ/Container/Registries/ManagerRegistry.cs +++ b/src/CoiniumServ/Container/Registries/ManagerRegistry.cs @@ -29,6 +29,7 @@ using CoiniumServ.Miners; using CoiniumServ.Pools; using CoiniumServ.Shares; +using CoiniumServ.Statistics; using CoiniumServ.Vardiff; namespace CoiniumServ.Container.Registries @@ -44,16 +45,20 @@ public ManagerRegistry(IApplicationContext applicationContext) public void RegisterInstances() { + // global singleton managers. + _applicationContext.Container.Register().AsSingleton(); + _applicationContext.Container.Register().AsSingleton(); + _applicationContext.Container.Register().AsSingleton(); + _applicationContext.Container.Register().AsSingleton(); + _applicationContext.Container.Register().AsSingleton(); + + // per-pool managers _applicationContext.Container.Register().AsMultiInstance(); _applicationContext.Container.Register().AsMultiInstance(); _applicationContext.Container.Register().AsMultiInstance(); _applicationContext.Container.Register().AsMultiInstance(); - _applicationContext.Container.Register().AsSingleton(); _applicationContext.Container.Register().AsMultiInstance(); - _applicationContext.Container.Register().AsMultiInstance(); - _applicationContext.Container.Register().AsSingleton(); - _applicationContext.Container.Register().AsSingleton(); - _applicationContext.Container.Register().AsSingleton(); + _applicationContext.Container.Register().AsMultiInstance(); } } } diff --git a/src/CoiniumServ/Container/Registries/StorageRegistry.cs b/src/CoiniumServ/Container/Registries/StorageRegistry.cs index ffaf9a895..5528cf64c 100644 --- a/src/CoiniumServ/Container/Registries/StorageRegistry.cs +++ b/src/CoiniumServ/Container/Registries/StorageRegistry.cs @@ -21,11 +21,9 @@ // #endregion using CoiniumServ.Container.Context; -using CoiniumServ.Persistance; using CoiniumServ.Persistance.Layers; using CoiniumServ.Persistance.Layers.Empty; using CoiniumServ.Persistance.Layers.Hybrid; -using CoiniumServ.Persistance.Layers.Hybrid.Migrations; using CoiniumServ.Persistance.Layers.Mpos; using CoiniumServ.Persistance.Providers; using CoiniumServ.Persistance.Providers.MySql; diff --git a/src/CoiniumServ/Factories/IObjectFactory.cs b/src/CoiniumServ/Factories/IObjectFactory.cs index 1aee0eebb..a4dfb3262 100644 --- a/src/CoiniumServ/Factories/IObjectFactory.cs +++ b/src/CoiniumServ/Factories/IObjectFactory.cs @@ -42,7 +42,6 @@ using CoiniumServ.Shares; using CoiniumServ.Statistics; using CoiniumServ.Vardiff; -using HashLib; using Nancy.Bootstrapper; namespace CoiniumServ.Factories @@ -52,21 +51,17 @@ namespace CoiniumServ.Factories /// public interface IObjectFactory { - #region hash algorithms + #region global objects + IPoolManager GetPoolManager(); - /// - /// Returns instance of the given hash algorithm - /// - /// - /// - IHashAlgorithm GetHashAlgorithm(string algorithm); + IStatisticsManager GetStatisticsManager(); + + ILogManager GetLogManager(); #endregion #region pool objects - IPoolManager GetPoolManager(); - IPool GetPool(IPoolConfig poolConfig); /// @@ -77,8 +72,7 @@ public interface IObjectFactory IMinerManager GetMinerManager(IPoolConfig poolConfig, IStorageLayer storageLayer); - IJobManager GetJobManager(IPoolConfig poolConfig, IDaemonClient daemonClient, IJobTracker jobTracker, IShareManager shareManager, - IMinerManager minerManager, IHashAlgorithm hashAlgorithm); + IJobManager GetJobManager(IPoolConfig poolConfig, IDaemonClient daemonClient, IJobTracker jobTracker, IShareManager shareManager, IMinerManager minerManager, IHashAlgorithm hashAlgorithm); IJobTracker GetJobTracker(); @@ -94,24 +88,24 @@ IJobManager GetJobManager(IPoolConfig poolConfig, IDaemonClient daemonClient, IJ INetworkInfo GetNetworkInfo(IDaemonClient daemonClient, IHashAlgorithm hashAlgorithm, IPoolConfig poolConfig); - IAlgorithmManager GetAlgorithmManager(IPoolManager poolManager); - IBlocksCache GetBlocksCache(IStorageLayer storageLayer); - IStatisticsManager GetStatisticsManager(); - - #endregion + IMiningServer GetMiningServer(string type, IPoolConfig poolConfig, IPool pool, IMinerManager minerManager, IJobManager jobManager,IBanManager banManager); - #region server & service objects + IRpcService GetMiningService(string type, IPoolConfig poolConfig, IShareManager shareManager, IDaemonClient daemonClient); - IMiningServer GetMiningServer(string type, IPoolConfig poolConfig, IPool pool, IMinerManager minerManager, IJobManager jobManager, - IBanManager banManager); + #endregion - IRpcService GetMiningService(string type, IPoolConfig poolConfig, IShareManager shareManager, IDaemonClient daemonClient); + #region hash algorithms - IWebServer GetWebServer(); + /// + /// Returns instance of the given hash algorithm + /// + /// + /// + IHashAlgorithm GetHashAlgorithm(string algorithm); - INancyBootstrapper GetWebBootstrapper(); + IAlgorithmManager GetAlgorithmManager(IPoolManager poolManager); #endregion @@ -125,9 +119,11 @@ IMiningServer GetMiningServer(string type, IPoolConfig poolConfig, IPool pool, I #endregion - #region other objects + #region web-server objects - ILogManager GetLogManager(); + IWebServer GetWebServer(); + + INancyBootstrapper GetWebBootstrapper(); IMetricsManager GetMetricsManager(); diff --git a/src/CoiniumServ/Factories/ObjectFactory.cs b/src/CoiniumServ/Factories/ObjectFactory.cs index fdd49c473..ac6ddc74d 100644 --- a/src/CoiniumServ/Factories/ObjectFactory.cs +++ b/src/CoiniumServ/Factories/ObjectFactory.cs @@ -71,23 +71,27 @@ public ObjectFactory(IApplicationContext applicationContext) #endregion - #region hash algorithms + #region global objects - /// - /// Returns instance of the given hash algorithm. - /// - /// - /// - public IHashAlgorithm GetHashAlgorithm(string algorithm) + public IPoolManager GetPoolManager() { - return _applicationContext.Container.Resolve(algorithm); + return _applicationContext.Container.Resolve(); } - public IPoolManager GetPoolManager() + public IStatisticsManager GetStatisticsManager() { - return _applicationContext.Container.Resolve(); + return _applicationContext.Container.Resolve(); } + public ILogManager GetLogManager() + { + return _applicationContext.Container.Resolve(); + } + + #endregion + + #region pool objects + public IPool GetPool(IPoolConfig poolConfig) { var @params = new NamedParameterOverloads @@ -98,10 +102,6 @@ public IPool GetPool(IPoolConfig poolConfig) return _applicationContext.Container.Resolve(@params); } - #endregion - - #region pool objects - /// /// Returns a new instance of daemon client. /// @@ -220,11 +220,6 @@ public INetworkInfo GetNetworkInfo(IDaemonClient daemonClient, IHashAlgorithm ha return _applicationContext.Container.Resolve(@params); } - public IAlgorithmManager GetAlgorithmManager(IPoolManager poolManager) - { - return _applicationContext.Container.Resolve(); - } - public IBlocksCache GetBlocksCache(IStorageLayer storageLayer) { var @params = new NamedParameterOverloads @@ -235,17 +230,7 @@ public IBlocksCache GetBlocksCache(IStorageLayer storageLayer) return _applicationContext.Container.Resolve(@params); } - public IStatisticsManager GetStatisticsManager() - { - return _applicationContext.Container.Resolve(); - } - - #endregion - - #region server & service objects - - public IMiningServer GetMiningServer(string type, IPoolConfig poolConfig, IPool pool, IMinerManager minerManager, IJobManager jobManager, - IBanManager banManager) + public IMiningServer GetMiningServer(string type, IPoolConfig poolConfig, IPool pool, IMinerManager minerManager, IJobManager jobManager, IBanManager banManager) { var @params = new NamedParameterOverloads { @@ -271,14 +256,23 @@ public IRpcService GetMiningService(string type, IPoolConfig poolConfig, IShareM return _applicationContext.Container.Resolve(type, @params); } - public IWebServer GetWebServer() + #endregion + + #region hash algorithms + + /// + /// Returns instance of the given hash algorithm. + /// + /// + /// + public IHashAlgorithm GetHashAlgorithm(string algorithm) { - return _applicationContext.Container.Resolve(); + return _applicationContext.Container.Resolve(algorithm); } - public INancyBootstrapper GetWebBootstrapper() + public IAlgorithmManager GetAlgorithmManager(IPoolManager poolManager) { - return _applicationContext.Container.Resolve(); + return _applicationContext.Container.Resolve(); } #endregion @@ -323,11 +317,16 @@ public IMigrationManager GetMigrationManager(IMySqlProvider provider, IPoolConfi #endregion - #region other objects + #region web-server objects - public ILogManager GetLogManager() + public IWebServer GetWebServer() { - return _applicationContext.Container.Resolve(); + return _applicationContext.Container.Resolve(); + } + + public INancyBootstrapper GetWebBootstrapper() + { + return _applicationContext.Container.Resolve(); } public IMetricsManager GetMetricsManager() diff --git a/src/CoiniumServ/Pools/Pool.cs b/src/CoiniumServ/Pools/Pool.cs index f69dedbce..33c5a0cf8 100644 --- a/src/CoiniumServ/Pools/Pool.cs +++ b/src/CoiniumServ/Pools/Pool.cs @@ -256,12 +256,12 @@ private void RecacheRound() private void CalculateHashrate() { // read hashrate stats. - var windowTime = TimeHelpers.NowInUnixTime() - _configManager.WebServerConfig.Statistics.HashrateWindow; + var windowTime = TimeHelpers.NowInUnixTime() - _configManager.StatisticsConfig.HashrateWindow; _storageLayer.DeleteExpiredHashrateData(windowTime); var hashrates = _storageLayer.GetHashrateData(windowTime); double total = hashrates.Sum(pair => pair.Value); - Hashrate = Convert.ToUInt64(_shareMultiplier * total / _configManager.WebServerConfig.Statistics.HashrateWindow); + Hashrate = Convert.ToUInt64(_shareMultiplier * total / _configManager.StatisticsConfig.HashrateWindow); } } } diff --git a/src/CoiniumServ/Server/Web/IWebServerConfig.cs b/src/CoiniumServ/Server/Web/IWebServerConfig.cs index 1fb011dff..b8d64e458 100644 --- a/src/CoiniumServ/Server/Web/IWebServerConfig.cs +++ b/src/CoiniumServ/Server/Web/IWebServerConfig.cs @@ -20,9 +20,8 @@ // license or white-label it as set out in licenses/commercial.txt. // #endregion -using System; + using CoiniumServ.Configuration; -using CoiniumServ.Statistics; namespace CoiniumServ.Server.Web { @@ -40,8 +39,6 @@ public interface IWebServerConfig:IConfig /// int Port { get; } - IStatisticsConfig Statistics { get; } - IBackendConfig Backend { get; } } } diff --git a/src/CoiniumServ/Server/Web/WebServer.cs b/src/CoiniumServ/Server/Web/WebServer.cs index d4167c32f..bd0f79cf2 100644 --- a/src/CoiniumServ/Server/Web/WebServer.cs +++ b/src/CoiniumServ/Server/Web/WebServer.cs @@ -33,8 +33,6 @@ public class WebServer : HttpServer, IWebServer public WebServer(INancyBootstrapper webBootstrapper, IConfigManager configManager) : base(webBootstrapper) { - // todo: instead require webserver config. - var config = configManager.WebServerConfig; BindIP = config.BindInterface; Port = config.Port; @@ -43,8 +41,6 @@ public WebServer(INancyBootstrapper webBootstrapper, IConfigManager configManage if (config.Enabled) Start(); - else - _logger.Verbose("Skipping web-server initialization as it disabled."); } } } diff --git a/src/CoiniumServ/Server/Web/WebServerConfig.cs b/src/CoiniumServ/Server/Web/WebServerConfig.cs index b810b58d2..ff974e947 100644 --- a/src/CoiniumServ/Server/Web/WebServerConfig.cs +++ b/src/CoiniumServ/Server/Web/WebServerConfig.cs @@ -32,7 +32,6 @@ public class WebServerConfig : IWebServerConfig public bool Enabled { get; private set; } public string BindInterface { get; private set; } public int Port { get; private set; } - public IStatisticsConfig Statistics { get; private set; } // todo: move this out of webserver config. public IBackendConfig Backend { get; private set; } public bool Valid { get; private set; } public WebServerConfig(dynamic config) @@ -43,9 +42,7 @@ public WebServerConfig(dynamic config) Enabled = config.enabled; BindInterface = string.IsNullOrEmpty(config.bind) ? "127.0.0.1" : config.bind; Port = config.port == 0 ? 80 : config.port; - Statistics = new StatisticsConfig(config.stats); Backend = new BackendConfig(config.backend); - Valid = true; } catch (Exception e) diff --git a/src/CoiniumServ/Statistics/StatisticsManager.cs b/src/CoiniumServ/Statistics/StatisticsManager.cs index 919959f14..20e5cd53b 100644 --- a/src/CoiniumServ/Statistics/StatisticsManager.cs +++ b/src/CoiniumServ/Statistics/StatisticsManager.cs @@ -34,22 +34,25 @@ namespace CoiniumServ.Statistics public class StatisticsManager:IStatisticsManager { public ulong Hashrate { get; private set; } + public int MinerCount { get; private set; } public DateTime LastUpdate { get; private set; } + public IAlgorithmManager Algorithms { get; private set; } + public IPoolManager Pools { get; private set; } + private readonly IStatisticsConfig _config; + private readonly Timer _recacheTimer; // timer for recaching stastics. private readonly Stopwatch _stopWatch = new Stopwatch(); - private readonly IStatisticsConfig _config; - private readonly ILogger _logger; public StatisticsManager(IConfigManager configManager, IPoolManager poolManager, IAlgorithmManager algorithmManager) { - _config = configManager.WebServerConfig.Statistics; + _config = configManager.StatisticsConfig; Pools = poolManager; Algorithms = algorithmManager; From 844ef6419e2309261b52714501831d6824d85510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=BCseyin=20Uslu?= Date: Thu, 4 Sep 2014 22:20:16 +0300 Subject: [PATCH 10/14] JobTracker can now clean expired-jobs - fixes #359. IJob has now Creationtime property. Moved json-properties to IMiner.cs and IStratumMiner.cs from StartumMiner.cs. --- src/CoiniumServ/Factories/IObjectFactory.cs | 2 +- src/CoiniumServ/Factories/ObjectFactory.cs | 9 ++- src/CoiniumServ/Jobs/IJob.cs | 55 ++++++++++++++- src/CoiniumServ/Jobs/Job.cs | 69 +++---------------- src/CoiniumServ/Jobs/Manager/JobManager.cs | 12 ++-- src/CoiniumServ/Jobs/Tracker/JobTracker.cs | 40 ++++++++++- src/CoiniumServ/Miners/IMiner.cs | 3 + src/CoiniumServ/Pools/IPool.cs | 7 +- src/CoiniumServ/Pools/Pool.cs | 9 ++- .../Server/Mining/Stratum/IStratumMiner.cs | 3 + .../Server/Mining/Stratum/StratumMiner.cs | 9 ++- .../Statistics/StatisticsManager.cs | 12 ++-- src/Tests/Jobs/JobTests.cs | 2 +- 13 files changed, 139 insertions(+), 93 deletions(-) diff --git a/src/CoiniumServ/Factories/IObjectFactory.cs b/src/CoiniumServ/Factories/IObjectFactory.cs index a4dfb3262..1ce0efb5c 100644 --- a/src/CoiniumServ/Factories/IObjectFactory.cs +++ b/src/CoiniumServ/Factories/IObjectFactory.cs @@ -74,7 +74,7 @@ public interface IObjectFactory IJobManager GetJobManager(IPoolConfig poolConfig, IDaemonClient daemonClient, IJobTracker jobTracker, IShareManager shareManager, IMinerManager minerManager, IHashAlgorithm hashAlgorithm); - IJobTracker GetJobTracker(); + IJobTracker GetJobTracker(IPoolConfig poolConfig); IShareManager GetShareManager(IPoolConfig poolConfig, IDaemonClient daemonClient, IJobTracker jobTracker, IStorageLayer storageLayer, IBlockProcessor blockProcessor); diff --git a/src/CoiniumServ/Factories/ObjectFactory.cs b/src/CoiniumServ/Factories/ObjectFactory.cs index ac6ddc74d..20dbcaa1f 100644 --- a/src/CoiniumServ/Factories/ObjectFactory.cs +++ b/src/CoiniumServ/Factories/ObjectFactory.cs @@ -143,9 +143,14 @@ public IJobManager GetJobManager(IPoolConfig poolConfig, IDaemonClient daemonCli return _applicationContext.Container.Resolve(@params); } - public IJobTracker GetJobTracker() + public IJobTracker GetJobTracker(IPoolConfig poolConfig) { - return _applicationContext.Container.Resolve(); + var @params = new NamedParameterOverloads + { + {"poolConfig", poolConfig}, + }; + + return _applicationContext.Container.Resolve(@params); } public IShareManager GetShareManager(IPoolConfig poolConfig, IDaemonClient daemonClient, IJobTracker jobTracker, IStorageLayer storageLayer, IBlockProcessor blockProcessor) diff --git a/src/CoiniumServ/Jobs/IJob.cs b/src/CoiniumServ/Jobs/IJob.cs index cb039b3a0..7e2f6344c 100644 --- a/src/CoiniumServ/Jobs/IJob.cs +++ b/src/CoiniumServ/Jobs/IJob.cs @@ -28,41 +28,94 @@ using CoiniumServ.Shares; using CoiniumServ.Transactions; using CoiniumServ.Utils.Numerics; +using Newtonsoft.Json; namespace CoiniumServ.Jobs { + + [JsonArray] public interface IJob : IEnumerable { + /// + /// ID of the job. Use this ID while submitting share generated from this job. + /// UInt64 Id { get; } + /// + /// Height of the block we are looking for. + /// int Height { get; } + /// + /// Hash of previous block. + /// string PreviousBlockHash { get; } string PreviousBlockHashReversed { get; } + /// + /// Initial part of coinbase transaction. + /// The miner inserts ExtraNonce1 and ExtraNonce2 after this section of the coinbase. (https://www.btcguild.com/new_protocol.php) + /// string CoinbaseInitial { get; } + /// + /// Final part of coinbase transaction. + /// The miner appends this after the first part of the coinbase and the two ExtraNonce values. (https://www.btcguild.com/new_protocol.php) + /// string CoinbaseFinal { get; } + /// + /// Coin's block version. + /// string Version { get; } + /// + /// Encoded current network difficulty. + /// string EncodedDifficulty { get; } BigInteger Target { get; } + /// + /// Job difficulty. + /// double Difficulty { get; } - string nTime { get; } + /// + /// The current time. nTime rolling should be supported, but should not increase faster than actual time. + /// + string NTime { get; } + /// + /// When true, server indicates that submitting shares from previous jobs don't have a sense and such shares will be rejected. When this flag is set, miner should also drop all previous jobs, so job_ids can be eventually rotated. (http://mining.bitcoin.cz/stratum-mining) + /// f true, miners should abort their current work and immediately use the new job. If false, they can still use the current job, but should move to the new one after exhausting the current nonce range. (https://www.btcguild.com/new_protocol.php) + /// bool CleanJobs { get; set; } + /// + /// Creation time of the job. + /// + int CreationTime { get; } + + /// + /// The assigned hash algorithm for the job. + /// IHashAlgorithm HashAlgorithm { get; } + /// + /// Associated block template. + /// IBlockTemplate BlockTemplate { get; } + /// + /// Associated generation transaction. + /// IGenerationTransaction GenerationTransaction { get; } + /// + /// Merkle tree associated to blockTemplate transactions. + /// IMerkleTree MerkleTree { get; } new IEnumerator GetEnumerator(); diff --git a/src/CoiniumServ/Jobs/Job.cs b/src/CoiniumServ/Jobs/Job.cs index 42268ae37..2beec8ea0 100644 --- a/src/CoiniumServ/Jobs/Job.cs +++ b/src/CoiniumServ/Jobs/Job.cs @@ -32,98 +32,46 @@ using CoiniumServ.Transactions; using CoiniumServ.Transactions.Utils; using CoiniumServ.Utils.Extensions; +using CoiniumServ.Utils.Helpers.Time; using CoiniumServ.Utils.Numerics; using Gibbed.IO; -using Newtonsoft.Json; namespace CoiniumServ.Jobs { - [JsonArray] public class Job : IJob { - /// - /// ID of the job. Use this ID while submitting share generated from this job. - /// - [JsonIgnore] public UInt64 Id { get; private set; } - /// - /// Height of the block we are looking for. - /// public int Height { get; private set; } public string PreviousBlockHash { get; private set; } - /// - /// Hash of previous block. - /// - [JsonIgnore] public string PreviousBlockHashReversed { get; private set; } - /// - /// Initial part of coinbase transaction. - /// The miner inserts ExtraNonce1 and ExtraNonce2 after this section of the coinbase. (https://www.btcguild.com/new_protocol.php) - /// - [JsonIgnore] public string CoinbaseInitial { get; private set; } - /// - /// Final part of coinbase transaction. - /// The miner appends this after the first part of the coinbase and the two ExtraNonce values. (https://www.btcguild.com/new_protocol.php) - /// - [JsonIgnore] public string CoinbaseFinal { get; private set; } - /// - /// Coin's block version. - /// - [JsonIgnore] public string Version { get; private set; } - /// - /// Encoded current network difficulty. - /// - [JsonIgnore] public string EncodedDifficulty { get; private set; } public BigInteger Target { get; private set; } - /// - /// Job difficulty. - /// public double Difficulty { get; private set; } - /// - /// The current time. nTime rolling should be supported, but should not increase faster than actual time. - /// - [JsonIgnore] - public string nTime { get; private set; } + public string NTime { get; private set; } - /// - /// When true, server indicates that submitting shares from previous jobs don't have a sense and such shares will be rejected. When this flag is set, miner should also drop all previous jobs, so job_ids can be eventually rotated. (http://mining.bitcoin.cz/stratum-mining) - /// f true, miners should abort their current work and immediately use the new job. If false, they can still use the current job, but should move to the new one after exhausting the current nonce range. (https://www.btcguild.com/new_protocol.php) - /// - [JsonIgnore] public bool CleanJobs { get; set; } - /// - /// The assigned hash algorithm for the job. - /// + public int CreationTime { get; private set; } + public IHashAlgorithm HashAlgorithm { get; private set; } - /// - /// Associated block template. - /// public IBlockTemplate BlockTemplate { get; private set; } - /// - /// Associated generation transaction. - /// public IGenerationTransaction GenerationTransaction { get; private set; } - /// - /// Merkle tree associated to blockTemplate transactions. - /// public IMerkleTree MerkleTree { get; private set; } /// @@ -146,12 +94,13 @@ public Job(UInt64 id, IHashAlgorithm algorithm, IBlockTemplate blockTemplate, IG BlockTemplate = blockTemplate; Height = blockTemplate.Height; GenerationTransaction = generationTransaction; - _shares = new List(); - PreviousBlockHash = blockTemplate.PreviousBlockHash.HexToByteArray().ToHexString(); PreviousBlockHashReversed = blockTemplate.PreviousBlockHash.HexToByteArray().ReverseByteOrder().ToHexString(); CoinbaseInitial = generationTransaction.Initial.ToHexString(); CoinbaseFinal = generationTransaction.Final.ToHexString(); + CreationTime = TimeHelpers.NowInUnixTime(); + + _shares = new List(); // calculate the merkle tree MerkleTree = new MerkleTree(BlockTemplate.Transactions.GetHashList()); @@ -171,7 +120,7 @@ public Job(UInt64 id, IHashAlgorithm algorithm, IBlockTemplate blockTemplate, IG Difficulty = ((double)new BigRational(AlgorithmManager.Diff1, Target)); // set the ntime - nTime = BitConverter.GetBytes(blockTemplate.CurTime.BigEndian()).ToHexString(); + NTime = BitConverter.GetBytes(blockTemplate.CurTime.BigEndian()).ToHexString(); } public IEnumerator GetEnumerator() @@ -185,7 +134,7 @@ public IEnumerator GetEnumerator() MerkleTree.Branches, Version, EncodedDifficulty, - nTime, + NTime, CleanJobs }; diff --git a/src/CoiniumServ/Jobs/Manager/JobManager.cs b/src/CoiniumServ/Jobs/Manager/JobManager.cs index 56004a00e..0925dbeb7 100644 --- a/src/CoiniumServ/Jobs/Manager/JobManager.cs +++ b/src/CoiniumServ/Jobs/Manager/JobManager.cs @@ -52,8 +52,6 @@ public class JobManager : IJobManager private readonly IPoolConfig _poolConfig; - private readonly IJobConfig _jobConfig; - private IExtraNonce _extraNonce; // todo: check this. private readonly ILogger _logger; @@ -72,9 +70,7 @@ public JobManager(IPoolConfig poolConfig, IDaemonClient daemonClient, IJobTracke _shareManager = shareManager; _minerManager = minerManager; _hashAlgorithm = hashAlgorithm; - _poolConfig = poolConfig; - _jobConfig = poolConfig.Job; _jobCounter = new JobCounter(); // todo make this ioc based too. @@ -123,7 +119,7 @@ private void BlockPoller(object stats) } catch (RpcException) { } // just skip any exceptions caused by the block-pooler queries. - _blockPollerTimer.Change(_jobConfig.BlockRefreshInterval, Timeout.Infinite); // reset the block-poller timer so we can keep polling. + _blockPollerTimer.Change(_poolConfig.Job.BlockRefreshInterval, Timeout.Infinite); // reset the block-poller timer so we can keep polling. } private void CreateAndBroadcastNewJob(bool initiatedByTimer) @@ -134,16 +130,16 @@ private void CreateAndBroadcastNewJob(bool initiatedByTimer) { var count = BroadcastJob(job); // broadcast to miners. - _blockPollerTimer.Change(_jobConfig.BlockRefreshInterval, Timeout.Infinite); // reset the block-poller timer so we can start or keep polling for a new block in the network. + _blockPollerTimer.Change(_poolConfig.Job.BlockRefreshInterval, Timeout.Infinite); // reset the block-poller timer so we can start or keep polling for a new block in the network. if (initiatedByTimer) - _logger.Information("Broadcasted new job 0x{0:x} to {1} subscribers as no new blocks found for last {2} seconds", job.Id, count, _jobConfig.RebroadcastTimeout); + _logger.Information("Broadcasted new job 0x{0:x} to {1} subscribers as no new blocks found for last {2} seconds", job.Id, count, _poolConfig.Job.RebroadcastTimeout); else _logger.Information("Broadcasted new job 0x{0:x} to {1} subscribers as network found a new block {2}", job.Id, count, job.Height); } // no matter we created a job successfully or not, reset the rebroadcast timer, so we can keep trying. - _reBroadcastTimer.Change(_jobConfig.RebroadcastTimeout * 1000, Timeout.Infinite); + _reBroadcastTimer.Change(_poolConfig.Job.RebroadcastTimeout * 1000, Timeout.Infinite); } private IJob GetNewJob() diff --git a/src/CoiniumServ/Jobs/Tracker/JobTracker.cs b/src/CoiniumServ/Jobs/Tracker/JobTracker.cs index a3a5e8a6b..7c8f15a2c 100644 --- a/src/CoiniumServ/Jobs/Tracker/JobTracker.cs +++ b/src/CoiniumServ/Jobs/Tracker/JobTracker.cs @@ -22,18 +22,35 @@ #endregion using System; using System.Collections.Generic; +using System.Linq; +using System.Threading; +using CoiniumServ.Pools; +using CoiniumServ.Utils.Helpers.Time; +using Serilog; namespace CoiniumServ.Jobs.Tracker { public class JobTracker:IJobTracker { - private readonly Dictionary _jobs; + private Dictionary _jobs; + + private readonly Timer _cleanupTimer; // timer for cleaning old jobs. + + private readonly ILogger _logger; public IJob Current { get; private set; } - public JobTracker() + private const int MinimumJobBacklog = 3; // number of jobs to leave in. + private readonly int _cleanupFrequency; // frequency to cleanup jobs in seconds. + + public JobTracker(IPoolConfig poolConfig) { _jobs = new Dictionary(); + _logger = Log.ForContext().ForContext("Component", poolConfig.Coin.Name); + + _cleanupFrequency = MinimumJobBacklog*poolConfig.Job.RebroadcastTimeout; // calculate the cleanup frequency = number of jobs in backlog * rebroad-timeout + _cleanupTimer = new Timer(CleanUp, null, Timeout.Infinite, Timeout.Infinite); // create the timer as disabled. + _cleanupTimer.Change(_cleanupFrequency * 1000, Timeout.Infinite); // adjust the timer's next run. } public IJob Get(UInt64 id) @@ -47,6 +64,23 @@ public void Add(IJob job) Current = job; } - // TODO: remove expired jobs. + private void CleanUp(object state) + { + var startingCount = _jobs.Count; + + // calculate the cleanup delta time - jobs created before this will be cleaned up. + var delta = TimeHelpers.NowInUnixTime() - _cleanupFrequency; + + // find expired jobs that were created before our calcualted delta time. + _jobs = _jobs.Where(j => j.Value.CreationTime >= delta || j.Value == Current) + .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); + + var cleanedCount = startingCount - _jobs.Count; + + if(cleanedCount > 0) + _logger.Debug("Cleaned-up {0} expired jobs", cleanedCount); + + _cleanupTimer.Change(_cleanupFrequency * 1000, Timeout.Infinite); // reset the cleanup timer. + } } } diff --git a/src/CoiniumServ/Miners/IMiner.cs b/src/CoiniumServ/Miners/IMiner.cs index 757e534d8..1610a19be 100644 --- a/src/CoiniumServ/Miners/IMiner.cs +++ b/src/CoiniumServ/Miners/IMiner.cs @@ -35,11 +35,13 @@ public interface IMiner /// /// Unique subscription id for identifying the miner. /// + [JsonProperty("id")] int Id { get; } /// /// Username of the miner. /// + [JsonProperty("username")] string Username { get; } /// @@ -50,6 +52,7 @@ public interface IMiner /// /// Is the miner authenticated. /// + [JsonProperty("authenticated")] bool Authenticated { get; set; } int ValidShares { get; set; } diff --git a/src/CoiniumServ/Pools/IPool.cs b/src/CoiniumServ/Pools/IPool.cs index 725f9c6be..de186724f 100644 --- a/src/CoiniumServ/Pools/IPool.cs +++ b/src/CoiniumServ/Pools/IPool.cs @@ -25,7 +25,6 @@ using CoiniumServ.Cryptology.Algorithms; using CoiniumServ.Miners; using CoiniumServ.Server.Web.Service; -using CoiniumServ.Statistics; using Newtonsoft.Json; namespace CoiniumServ.Pools @@ -33,15 +32,15 @@ namespace CoiniumServ.Pools [JsonObject(MemberSerialization.OptIn)] public interface IPool: IJsonService { - [JsonProperty("config")] - IPoolConfig Config { get; } - [JsonProperty("hashrate")] UInt64 Hashrate { get; } [JsonProperty("round")] Dictionary RoundShares { get; } + [JsonProperty("config")] + IPoolConfig Config { get; } + IHashAlgorithm HashAlgorithm { get; } [JsonProperty("miners")] diff --git a/src/CoiniumServ/Pools/Pool.cs b/src/CoiniumServ/Pools/Pool.cs index 33c5a0cf8..cf2182302 100644 --- a/src/CoiniumServ/Pools/Pool.cs +++ b/src/CoiniumServ/Pools/Pool.cs @@ -52,12 +52,17 @@ namespace CoiniumServ.Pools /// public class Pool : IPool { - public IPoolConfig Config { get; private set; } public ulong Hashrate { get; private set; } public Dictionary RoundShares { get; private set; } + + public IPoolConfig Config { get; private set; } + public IHashAlgorithm HashAlgorithm { get; private set; } + public IMinerManager MinerManager { get; private set; } + public INetworkInfo NetworkInfo { get; private set; } + public IBlocksCache BlocksCache { get; private set; } // object factory. @@ -161,7 +166,7 @@ private void InitManagers() BlocksCache = _objectFactory.GetBlocksCache(_storageLayer); MinerManager = _objectFactory.GetMinerManager(Config, _storageLayer); - var jobTracker = _objectFactory.GetJobTracker(); + var jobTracker = _objectFactory.GetJobTracker(Config); var blockProcessor = _objectFactory.GetBlockProcessor(Config, _daemonClient); _shareManager = _objectFactory.GetShareManager(Config, _daemonClient, jobTracker, _storageLayer, blockProcessor); _objectFactory.GetVardiffManager(Config, _shareManager); diff --git a/src/CoiniumServ/Server/Mining/Stratum/IStratumMiner.cs b/src/CoiniumServ/Server/Mining/Stratum/IStratumMiner.cs index 217a5b92c..5c28181c6 100644 --- a/src/CoiniumServ/Server/Mining/Stratum/IStratumMiner.cs +++ b/src/CoiniumServ/Server/Mining/Stratum/IStratumMiner.cs @@ -24,9 +24,11 @@ using CoiniumServ.Jobs; using CoiniumServ.Miners; using CoiniumServ.Vardiff; +using Newtonsoft.Json; namespace CoiniumServ.Server.Mining.Stratum { + [JsonObject(MemberSerialization.OptIn)] public interface IStratumMiner:IMiner, IVardiffMiner { /// @@ -39,6 +41,7 @@ public interface IStratumMiner:IMiner, IVardiffMiner /// bool Subscribed { get; } + [JsonProperty("difficulty")] float Difficulty { get; } float PreviousDifficulty { get; } diff --git a/src/CoiniumServ/Server/Mining/Stratum/StratumMiner.cs b/src/CoiniumServ/Server/Mining/Stratum/StratumMiner.cs index 7fd6b1d87..8764a411e 100644 --- a/src/CoiniumServ/Server/Mining/Stratum/StratumMiner.cs +++ b/src/CoiniumServ/Server/Mining/Stratum/StratumMiner.cs @@ -54,13 +54,11 @@ public class StratumMiner : IClient, IStratumMiner /// /// Unique subscription id for identifying the miner. /// - [JsonProperty("id")] public int Id { get; private set; } /// /// Username of the miner. /// - [JsonProperty("username")] public string Username { get; private set; } /// @@ -71,7 +69,6 @@ public class StratumMiner : IClient, IStratumMiner /// /// Is the miner authenticated? /// - [JsonProperty("authenticated")] public bool Authenticated { get; set; } public int ValidShares { get; set; } @@ -79,9 +76,9 @@ public class StratumMiner : IClient, IStratumMiner public int InvalidShares { get; set; } public IPool Pool { get; private set; } - - [JsonProperty("difficulty")] + public float Difficulty { get; set; } + public float PreviousDifficulty { get; set; } /// @@ -90,7 +87,9 @@ public class StratumMiner : IClient, IStratumMiner public uint ExtraNonce { get; private set; } public int LastVardiffTimestamp { get; set; } + public int LastVardiffRetarget { get; set; } + public IRingBuffer VardiffBuffer { get; set; } private readonly IMinerManager _minerManager; diff --git a/src/CoiniumServ/Statistics/StatisticsManager.cs b/src/CoiniumServ/Statistics/StatisticsManager.cs index 20e5cd53b..73cc2c0a6 100644 --- a/src/CoiniumServ/Statistics/StatisticsManager.cs +++ b/src/CoiniumServ/Statistics/StatisticsManager.cs @@ -52,10 +52,10 @@ public class StatisticsManager:IStatisticsManager public StatisticsManager(IConfigManager configManager, IPoolManager poolManager, IAlgorithmManager algorithmManager) { - _config = configManager.StatisticsConfig; Pools = poolManager; Algorithms = algorithmManager; + _config = configManager.StatisticsConfig; _logger = Log.ForContext(); _recacheTimer = new Timer(Recache, null, Timeout.Infinite, Timeout.Infinite); // create the timer as disabled. @@ -83,11 +83,6 @@ public void Recache() _recacheTimer.Change(_config.UpdateInterval * 1000, Timeout.Infinite); // reset the recache timer. } - - private void Recache(object state) - { - Recache(); - } private void RecacheGlobal() { @@ -100,5 +95,10 @@ private void RecacheGlobal() MinerCount += pool.MinerManager.Count; } } + + private void Recache(object state) + { + Recache(); + } } } diff --git a/src/Tests/Jobs/JobTests.cs b/src/Tests/Jobs/JobTests.cs index 345289e5f..0fcb082dc 100644 --- a/src/Tests/Jobs/JobTests.cs +++ b/src/Tests/Jobs/JobTests.cs @@ -197,7 +197,7 @@ public void TestJob() job.EncodedDifficulty.Should().Equal("1d2bd7c3"); // test the current time - job.nTime.Should().Equal("539ee666"); + job.NTime.Should().Equal("539ee666"); // test the clean jobs flag job.CleanJobs.Should().Equal(true); From 7b62006217ad2c7700337cf20c47913ca1fc6f99 Mon Sep 17 00:00:00 2001 From: bonesoul Date: Fri, 5 Sep 2014 10:16:31 +0300 Subject: [PATCH 11/14] Fixed a bug in MposStorageLayer.cs. Implemented MposStorageLayer.cs:GetHashrateData(). --- .../Layers/Mpos/MposStorageLayer.cs | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/CoiniumServ/Persistance/Layers/Mpos/MposStorageLayer.cs b/src/CoiniumServ/Persistance/Layers/Mpos/MposStorageLayer.cs index 4b5c906fc..55a2d0f01 100644 --- a/src/CoiniumServ/Persistance/Layers/Mpos/MposStorageLayer.cs +++ b/src/CoiniumServ/Persistance/Layers/Mpos/MposStorageLayer.cs @@ -56,6 +56,8 @@ public MposStorageLayer(IEnumerable providers, PoolConfig pool if (provider is IMySqlProvider) _mySqlProvider = (IMySqlProvider) provider; } + + IsEnabled = _mySqlProvider != null; } public void AddShare(IShare share) @@ -151,12 +153,34 @@ public Dictionary> GetShares(IList GetHashrateData(int since) { - throw new NotImplementedException(); + var hashrateData = new Dictionary(); + + try + { + if (!IsEnabled) + return hashrateData; + + using (var connection = new MySqlConnection(_mySqlProvider.ConnectionString)) + { + var results = connection.Query(@"select username, sum(difficulty) as shares from shares where our_result='Y' group by username"); + + foreach (var row in results) + { + hashrateData.Add(row.username, row.shares); + } + } + } + catch (Exception e) + { + _logger.Error("An exception occured while getting share data: {0:l}", e.Message); + } + + return hashrateData; } public void AddBlock(IShare share) @@ -283,6 +307,9 @@ public bool Authenticate(IMiner miner) { try { + if (!IsEnabled) + return false; + using (var connection = new MySqlConnection(_mySqlProvider.ConnectionString)) { // query the username against mpos pool_worker table. @@ -306,6 +333,9 @@ public void UpdateDifficulty(IStratumMiner miner) { try { + if (!IsEnabled) + return; + using (var connection = new MySqlConnection(_mySqlProvider.ConnectionString)) { connection.Execute( From 8cb5c1f8f0f66db12f4f4719bd05e736ce522369 Mon Sep 17 00:00:00 2001 From: bonesoul Date: Fri, 5 Sep 2014 10:32:23 +0300 Subject: [PATCH 12/14] Updated to 0.1.5 --- src/CoiniumServ/Utils/Versions/VersionInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CoiniumServ/Utils/Versions/VersionInfo.cs b/src/CoiniumServ/Utils/Versions/VersionInfo.cs index d7a9ce419..9c00e625a 100644 --- a/src/CoiniumServ/Utils/Versions/VersionInfo.cs +++ b/src/CoiniumServ/Utils/Versions/VersionInfo.cs @@ -41,7 +41,7 @@ public static class Assembly /// /// Main assemby version. /// - public const string Version = "0.1.4.*"; + public const string Version = "0.1.5.*"; } } } From ad189519eb7d8e685ae56cc90427e4b7a26f6936 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=BCseyin=20Uslu?= Date: Fri, 5 Sep 2014 10:41:48 +0300 Subject: [PATCH 13/14] Update Changelog.md --- Changelog.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Changelog.md b/Changelog.md index bfe774e62..20c242e68 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,28 @@ +##### [v0.1.5 alpha](https://github.com/CoiniumServ/CoiniumServ/releases/tag/v0.1.5-alpha) - 05.09.2014 + +**Payments** +* Fixed a bug in hybrid-storage layer where blocks were not correctly set as confirmed once they were actually so. + +**Web** +* Fixed a bug in embedded web-server where some users were not able to use the interface. +* Updated web-site tempaltes which reflects newest API changes. + +**Storage** +* Fixed a bug in migration-manager where if it couldn't connect to MySQL would cause program to crash & terminate. + +**API** +* Improved pool API. + +**Pools** +* Pools can now determine if connection to coin network is healthy. +* Fixed hashrate calculation bug. + +**Jobs** +* JobTracker can now clean expired jobs. + +**Configuration** +* Moved config.json "website:stats" section to upper level and renamed as "statistics". You have to apply the change to your existing config.json file! + ##### [v0.1.4 alpha](https://github.com/CoiniumServ/CoiniumServ/releases/tag/v0.1.4-alpha) - 03.09.2014 **Storage** From 3ea966e999e872c512e1d4a2705a3aa7dae0803f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=BCseyin=20Uslu?= Date: Fri, 5 Sep 2014 10:42:21 +0300 Subject: [PATCH 14/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 61e2737a7..c8ab4a1c1 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ You can send tips and furher support the project or get tips for contributing by ### Status -[v0.1.4 alpha](https://github.com/CoiniumServ/CoiniumServ/releases/tag/v0.1.4-alpha) released +[v0.1.5 alpha](https://github.com/CoiniumServ/CoiniumServ/releases/tag/v0.1.5-alpha) released ### Features