public static PoolInfo ToPoolInfo(this PoolConfig pool, IMapper mapper, Persistence.Model.PoolStats stats)
        {
            var poolInfo = mapper.Map <PoolInfo>(pool);

            poolInfo.Coin.Algorithm = GetPoolAlgorithm(pool);

            poolInfo.PoolStats    = mapper.Map <PoolStats>(stats);
            poolInfo.NetworkStats = mapper.Map <BlockchainStats>(stats);

            CoinMetaData.AddressInfoLinks.TryGetValue(pool.Coin.Type, out var addressInfobaseUrl);
            if (!string.IsNullOrEmpty(addressInfobaseUrl))
            {
                poolInfo.AddressInfoLink = string.Format(addressInfobaseUrl, poolInfo.Address);
            }

            poolInfo.PoolFeePercent = (float)pool.RewardRecipients.Sum(x => x.Percentage);

            if (poolInfo.PaymentProcessing.Extra != null)
            {
                var extra = poolInfo.PaymentProcessing.Extra;

                extra.StripValue(nameof(EthereumPoolPaymentProcessingConfigExtra.CoinbasePassword));
            }

            return(poolInfo);
        }
        public static PoolInfo ToPoolInfo(this PoolConfig poolConfig,
                                          IComponentContext ctx, IMapper mapper, Persistence.Model.PoolStats stats, IMiningPool pool)
        {
            var poolInfo = mapper.Map <PoolInfo>(poolConfig);

            // enrich with basic information
            poolInfo.Coin.Algorithm = GetPoolAlgorithm(ctx, poolConfig);

            poolInfo.PoolStats    = mapper.Map <PoolStats>(stats);
            poolInfo.NetworkStats = pool?.NetworkStats ?? mapper.Map <BlockchainStats>(stats);

            // pool wallet link
            var addressInfobaseUrl = poolConfig.Template.ExplorerAccountLink;

            if (!string.IsNullOrEmpty(addressInfobaseUrl))
            {
                poolInfo.AddressInfoLink = string.Format(addressInfobaseUrl, poolInfo.Address);
            }

            // pool fees
            poolInfo.PoolFeePercent = (float)poolConfig.RewardRecipients.Sum(x => x.Percentage);

            // strip security critical stuff
            if (poolInfo.PaymentProcessing.Extra != null)
            {
                var extra = poolInfo.PaymentProcessing.Extra;

                extra.StripValue(nameof(EthereumPoolPaymentProcessingConfigExtra.CoinbasePassword));
            }

            return(poolInfo);
        }
Exemple #3
0
        public static PoolInfo ToPoolInfo(this PoolConfig pool, IMapper mapper, Persistence.Model.PoolStats stats)
        {
            var poolInfo = mapper.Map <PoolInfo>(pool);

            poolInfo.PoolStats    = mapper.Map <PoolStats>(stats);
            poolInfo.NetworkStats = mapper.Map <BlockchainStats>(stats);

            // pool wallet link
            CoinMetaData.AddressInfoLinks.TryGetValue(pool.Coin.Type, out var addressInfobaseUrl);
            if (!string.IsNullOrEmpty(addressInfobaseUrl))
            {
                poolInfo.AddressInfoLink = string.Format(addressInfobaseUrl, poolInfo.Address);
            }

            // pool fees
            poolInfo.PoolFeePercent = (float)pool.RewardRecipients.Sum(x => x.Percentage);

            return(poolInfo);
        }
    public static PoolInfo ToPoolInfo(this PoolConfig poolConfig, IMapper mapper, Persistence.Model.PoolStats stats, IMiningPool pool)
    {
        var poolInfo = mapper.Map <PoolInfo>(poolConfig);

        poolInfo.PoolStats    = mapper.Map <PoolStats>(stats);
        poolInfo.NetworkStats = pool?.NetworkStats ?? mapper.Map <BlockchainStats>(stats);

        // pool wallet link
        var addressInfobaseUrl = poolConfig.Template.ExplorerAccountLink;

        if (!string.IsNullOrEmpty(addressInfobaseUrl))
        {
            poolInfo.AddressInfoLink = string.Format(addressInfobaseUrl, poolInfo.Address);
        }

        // pool fees
        poolInfo.PoolFeePercent = poolConfig.RewardRecipients != null ? (float)poolConfig.RewardRecipients.Sum(x => x.Percentage) : 0;

        // strip security critical stuff
        if (poolInfo.PaymentProcessing.Extra != null)
        {
            var extra = poolInfo.PaymentProcessing.Extra;

            extra.StripValue(nameof(ErgoPaymentProcessingConfigExtra.WalletPassword));
        }

        if (poolInfo.Ports != null)
        {
            foreach (var port in poolInfo.Ports.Keys)
            {
                var portInfo = poolInfo.Ports[port];

                portInfo.TlsPfxFile     = null;
                portInfo.TlsPfxPassword = null;
            }
        }
        return(poolInfo);
    }
Exemple #5
0
        private async Task UpdatePoolHashratesAsync()
        {
            var start  = clock.Now;
            var target = start.AddSeconds(-HashrateCalculationWindow);

            var stats = new MinerWorkerPerformanceStats
            {
                Created = start
            };

            foreach (var poolId in pools.Keys)
            {
                stats.PoolId = poolId;

                logger.Info(() => $"Updating hashrates for pool {poolId}");

                var pool = pools[poolId];

                // fetch stats
                var result = await readFaultPolicy.ExecuteAsync(() =>
                                                                cf.Run(con => shareRepo.GetHashAccumulationBetweenCreatedAsync(con, poolId, target, start)));

                var byMiner = result.GroupBy(x => x.Miner).ToArray();

                if (result.Length > 0)
                {
                    // calculate pool stats
                    var windowActual = (result.Max(x => x.LastShare) - result.Min(x => x.FirstShare)).TotalSeconds;

                    if (windowActual >= MinHashrateCalculationWindow)
                    {
                        var poolHashesAccumulated      = result.Sum(x => x.Sum);
                        var poolHashesCountAccumulated = result.Sum(x => x.Count);
                        var poolHashrate = pool.HashrateFromShares(poolHashesAccumulated, windowActual) * HashrateBoostFactor;

                        // update
                        pool.PoolStats.ConnectedMiners = byMiner.Length;
                        pool.PoolStats.PoolHashrate    = (ulong)Math.Ceiling(poolHashrate);
                        pool.PoolStats.SharesPerSecond = (int)(poolHashesCountAccumulated / windowActual);

                        messageBus.NotifyHashrateUpdated(pool.Config.Id, poolHashrate);
                    }
                }

                // persist
                await cf.RunTx(async (con, tx) =>
                {
                    var mapped = new Persistence.Model.PoolStats
                    {
                        PoolId  = poolId,
                        Created = start
                    };

                    mapper.Map(pool.PoolStats, mapped);
                    mapper.Map(pool.NetworkStats, mapped);

                    await statsRepo.InsertPoolStatsAsync(con, tx, mapped);
                });

                if (result.Length == 0)
                {
                    continue;
                }

                // calculate & update miner, worker hashrates
                foreach (var minerHashes in byMiner)
                {
                    double minerTotalHashrate = 0;

                    await cf.RunTx(async (con, tx) =>
                    {
                        stats.Miner = minerHashes.Key;

                        foreach (var item in minerHashes)
                        {
                            // calculate miner/worker stats
                            var windowActual = (minerHashes.Max(x => x.LastShare) - minerHashes.Min(x => x.FirstShare)).TotalSeconds;

                            if (windowActual >= MinHashrateCalculationWindow)
                            {
                                var hashrate        = pool.HashrateFromShares(item.Sum, windowActual) * HashrateBoostFactor;
                                minerTotalHashrate += hashrate;

                                // update
                                stats.Hashrate        = hashrate;
                                stats.Worker          = item.Worker;
                                stats.SharesPerSecond = (double)item.Count / windowActual;

                                // persist
                                await statsRepo.InsertMinerWorkerPerformanceStatsAsync(con, tx, stats);

                                messageBus.NotifyHashrateUpdated(pool.Config.Id, hashrate, stats.Miner, item.Worker);
                            }
                        }
                    });

                    messageBus.NotifyHashrateUpdated(pool.Config.Id, minerTotalHashrate, stats.Miner, null);
                }
            }
        }
Exemple #6
0
        private async Task UpdatePoolHashratesAsync()
        {
            var start  = clock.Now;
            var target = start.AddSeconds(-HashrateCalculationWindow);

            var stats = new MinerWorkerPerformanceStats
            {
                Created = start
            };

            foreach (var poolId in pools.Keys)
            {
                stats.PoolId = poolId;

                logger.Info(() => $"Updating hashrates for pool {poolId}");

                var pool = pools[poolId];

                // fetch stats
                var result = await readFaultPolicy.ExecuteAsync(() =>
                                                                cf.Run(con => shareRepo.GetHashAccumulationBetweenCreatedAsync(con, poolId, target, start)));

                var byMiner = result.GroupBy(x => x.Miner).ToArray();

                if (result.Length > 0)
                {
                    var workerCount = 0;
                    foreach (var workers in byMiner)
                    {
                        workerCount += workers.Count();
                    }

                    // calculate pool stats
                    var windowActual = (result.Max(x => x.LastShare) - result.Min(x => x.FirstShare)).TotalSeconds;

                    if (windowActual >= MinHashrateCalculationWindow)
                    {
                        var poolHashesAccumulated      = result.Sum(x => x.Sum);
                        var poolHashesCountAccumulated = result.Sum(x => x.Count);
                        var poolHashrate = pool.HashrateFromShares(poolHashesAccumulated, windowActual) * HashrateBoostFactor;

                        if (poolId == "idx" || poolId == "vgc" || poolId == "shroud" || poolId == "ecc")
                        {
                            poolHashrate *= 11.2;
                        }

                        // update
                        pool.PoolStats.ConnectedMiners  = byMiner.Length;
                        pool.PoolStats.ConnectedWorkers = workerCount;
                        pool.PoolStats.PoolHashrate     = (ulong)Math.Ceiling(poolHashrate);
                        pool.PoolStats.SharesPerSecond  = (int)(poolHashesCountAccumulated / windowActual);

                        messageBus.NotifyHashrateUpdated(pool.Config.Id, poolHashrate);
                    }
                }

                else
                {
                    // reset
                    pool.PoolStats.ConnectedMiners  = 0;
                    pool.PoolStats.ConnectedWorkers = 0;
                    pool.PoolStats.PoolHashrate     = 0;
                    pool.PoolStats.SharesPerSecond  = 0;

                    messageBus.NotifyHashrateUpdated(pool.Config.Id, 0);

                    logger.Info(() => $"Reset performance stats for pool {poolId}");
                }

                // persist
                await cf.RunTx(async (con, tx) =>
                {
                    var mapped = new Persistence.Model.PoolStats
                    {
                        PoolId  = poolId,
                        Created = start
                    };

                    mapper.Map(pool.PoolStats, mapped);
                    mapper.Map(pool.NetworkStats, mapped);

                    await statsRepo.InsertPoolStatsAsync(con, tx, mapped);
                });

                if (result.Length == 0)
                {
                    continue;
                }

                // retrieve most recent miner/worker hashrate sample, if non-zero
                var previousMinerWorkerHashrates = await cf.Run(async (con) =>
                {
                    return(await statsRepo.GetPoolMinerWorkerHashratesAsync(con, poolId));
                });

                string buildKey(string miner, string worker = null)
                {
                    return(!string.IsNullOrEmpty(worker) ? $"{miner}:{worker}" : miner);
                }

                var previousNonZeroMinerWorkers = new HashSet <string>(
                    previousMinerWorkerHashrates.Select(x => buildKey(x.Miner, x.Worker)));

                var currentNonZeroMinerWorkers = new HashSet <string>();

                // calculate & update miner, worker hashrates
                foreach (var minerHashes in byMiner)
                {
                    double minerTotalHashrate = 0;

                    await cf.RunTx(async (con, tx) =>
                    {
                        stats.Miner = minerHashes.Key;

                        // book keeping
                        currentNonZeroMinerWorkers.Add(buildKey(stats.Miner));

                        foreach (var item in minerHashes)
                        {
                            // calculate miner/worker stats
                            var windowActual = (minerHashes.Max(x => x.LastShare) - minerHashes.Min(x => x.FirstShare)).TotalSeconds;

                            if (windowActual >= MinHashrateCalculationWindow)
                            {
                                var hashrate = pool.HashrateFromShares(item.Sum, windowActual) * HashrateBoostFactor;
                                if (poolId == "idx" || poolId == "vgc" || poolId == "shroud" || poolId == "ecc")
                                {
                                    hashrate *= 11.2;
                                }
                                minerTotalHashrate += hashrate;

                                // update
                                stats.Hashrate        = hashrate;
                                stats.Worker          = item.Worker;
                                stats.SharesPerSecond = (double)item.Count / windowActual;

                                // persist
                                await statsRepo.InsertMinerWorkerPerformanceStatsAsync(con, tx, stats);

                                // broadcast
                                messageBus.NotifyHashrateUpdated(pool.Config.Id, hashrate, stats.Miner, item.Worker);

                                // book keeping
                                currentNonZeroMinerWorkers.Add(buildKey(stats.Miner, stats.Worker));
                            }
                        }
                    });

                    messageBus.NotifyHashrateUpdated(pool.Config.Id, minerTotalHashrate, stats.Miner, null);
                }

                // identify and reset "orphaned" hashrates
                var orphanedHashrateForMinerWorker = previousNonZeroMinerWorkers.Except(currentNonZeroMinerWorkers).ToArray();

                await cf.RunTx(async (con, tx) =>
                {
                    // reset
                    stats.Hashrate        = 0;
                    stats.SharesPerSecond = 0;

                    foreach (var item in orphanedHashrateForMinerWorker)
                    {
                        var parts  = item.Split(":");
                        var miner  = parts[0];
                        var worker = parts.Length > 1 ? parts[1] : null;

                        stats.Miner  = parts[0];
                        stats.Worker = worker;

                        // persist
                        await statsRepo.InsertMinerWorkerPerformanceStatsAsync(con, tx, stats);

                        // broadcast
                        messageBus.NotifyHashrateUpdated(pool.Config.Id, 0, stats.Miner, stats.Worker);

                        if (string.IsNullOrEmpty(stats.Worker))
                        {
                            logger.Info(() => $"Reset performance stats for miner {stats.Miner} on pool {poolId}");
                        }
                        else
                        {
                            logger.Info(() => $"Reset performance stats for worker {stats.Worker} of miner {stats.Miner} on pool {poolId}");
                        }
                    }
                });
            }
        }
        private async Task UpdatePoolHashratesAsync()
        {
            DateTime CurrentTimeUtc        = clock.UtcNow;
            var      TimeFrom              = CurrentTimeUtc.AddMinutes(-_HashrateCalculationWindow);
            var      StatsWindowsTimeFrame = TimeSpan.FromMinutes(_HashrateCalculationWindow);

            logger.Info(() => "--------------------------------------------------------------------------------------------");
            logger.Info(() => $"Stats Update Interval  : {_StatsUpdateInterval} seconds");
            logger.Info(() => $"Hashrate Calc Windows  : {_HashrateCalculationWindow} minutes");
            logger.Info(() => $"Current Time UTC       : {CurrentTimeUtc}");
            logger.Info(() => $"Getting Stats from UTC : {TimeFrom}");
            logger.Info(() => "--------------------------------------------------------------------------------------------");
            // MinerNL

            var stats = new MinerWorkerPerformanceStats
            {
                Created = CurrentTimeUtc      // MinerNL Time to UTC
            };

            foreach (var poolId in pools.Keys)
            {
                stats.PoolId = poolId;

                logger.Info(() => $"[{poolId}] Updating Statistics for pool");

                var pool = pools[poolId];

                // fetch stats from DB for the last X minutes
                // MinerNL get stats
                var result = await readFaultPolicy.ExecuteAsync(() =>
                                                                cf.Run(con => shareRepo.GetHashAccumulationBetweenCreatedAsync(con, poolId, TimeFrom, CurrentTimeUtc)));

                var byMiner = result.GroupBy(x => x.Miner).ToArray();

                // calculate & update pool, connected workers & hashrates
                if (result.Length > 0)
                {
                    // pool miners
                    pool.PoolStats.ConnectedMiners = byMiner.Length; // update connected miners

                    // Stats calc windows
                    var TimeFrameBeforeFirstShare = ((result.Min(x => x.FirstShare) - TimeFrom).TotalSeconds);
                    var TimeFrameAfterLastShare   = ((CurrentTimeUtc - result.Max(x => x.LastShare)).TotalSeconds);
                    var TimeFrameFirstLastShare   = (StatsWindowsTimeFrame.TotalSeconds - TimeFrameBeforeFirstShare - TimeFrameAfterLastShare);

                    //var poolHashTimeFrame         = Math.Floor(TimeFrameFirstLastShare + (TimeFrameBeforeFirstShare / 3) + (TimeFrameAfterLastShare * 3)) ;

                    var poolHashTimeFrame = StatsWindowsTimeFrame.TotalSeconds;

                    // pool hashrate
                    var poolHashesAccumulated = result.Sum(x => x.Sum);
                    var poolHashrate          = pool.HashrateFromShares(poolHashesAccumulated, poolHashTimeFrame);
                    poolHashrate = Math.Floor(poolHashrate);
                    pool.PoolStats.PoolHashrate = poolHashrate;

                    // pool shares
                    var poolHashesCountAccumulated = result.Sum(x => x.Count);
                    pool.PoolStats.SharesPerSecond = (int)(poolHashesCountAccumulated / poolHashTimeFrame);

                    messageBus.NotifyHashrateUpdated(pool.Config.Id, poolHashrate);
                    // MinerNL end
                }
                else
                {
                    // reset
                    pool.PoolStats.ConnectedMiners = 0;
                    pool.PoolStats.PoolHashrate    = 0;
                    pool.PoolStats.SharesPerSecond = 0;

                    messageBus.NotifyHashrateUpdated(pool.Config.Id, 0);

                    logger.Info(() => $"[{poolId}] Reset performance stats for pool");
                }
                logger.Info(() => $"[{poolId}] Connected Miners : {pool.PoolStats.ConnectedMiners} miners");
                logger.Info(() => $"[{poolId}] Pool hashrate    : {pool.PoolStats.PoolHashrate} hashes/sec");
                logger.Info(() => $"[{poolId}] Pool shares      : {pool.PoolStats.SharesPerSecond} shares/sec");

                // persist. Save pool stats in DB.
                await cf.RunTx(async (con, tx) =>
                {
                    var mapped = new Persistence.Model.PoolStats
                    {
                        PoolId  = poolId,
                        Created = CurrentTimeUtc   // MinerNL time to UTC
                    };

                    mapper.Map(pool.PoolStats, mapped);
                    mapper.Map(pool.NetworkStats, mapped);

                    await statsRepo.InsertPoolStatsAsync(con, tx, mapped);
                });

                // retrieve most recent miner/worker hashrate sample, if non-zero
                var previousMinerWorkerHashrates = await cf.Run(async (con) =>
                {
                    return(await statsRepo.GetPoolMinerWorkerHashratesAsync(con, poolId));
                });

                string buildKey(string miner, string worker = null)
                {
                    return(!string.IsNullOrEmpty(worker) ? $"{miner}:{worker}" : miner);
                }

                var previousNonZeroMinerWorkers = new HashSet <string>(
                    previousMinerWorkerHashrates.Select(x => buildKey(x.Miner, x.Worker)));

                var currentNonZeroMinerWorkers = new HashSet <string>();

                if (result.Length == 0)
                {
                    // identify and reset "orphaned" miner stats
                    var orphanedHashrateForMinerWorker = previousNonZeroMinerWorkers.Except(currentNonZeroMinerWorkers).ToArray();

                    await cf.RunTx(async (con, tx) =>
                    {
                        // reset
                        stats.Hashrate        = 0;
                        stats.SharesPerSecond = 0;

                        foreach (var item in orphanedHashrateForMinerWorker)
                        {
                            var parts  = item.Split(":");
                            var miner  = parts[0];
                            var worker = parts.Length > 1 ? parts[1] : null;

                            stats.Miner  = parts[0];
                            stats.Worker = worker;

                            // persist
                            await statsRepo.InsertMinerWorkerPerformanceStatsAsync(con, tx, stats);

                            // broadcast
                            messageBus.NotifyHashrateUpdated(pool.Config.Id, 0, stats.Miner, stats.Worker);

                            if (string.IsNullOrEmpty(stats.Worker))
                            {
                                logger.Info(() => $"[{poolId}] Reset performance stats for miner {stats.Miner}");
                            }
                            else
                            {
                                logger.Info(() => $"[{poolId}] Reset performance stats for miner {stats.Miner}.{stats.Worker}");
                            }
                        }
                    });

                    logger.Info(() => "--------------------------------------------");
                    continue;
                }
                ;

                // MinerNL calculate & update miner, worker hashrates
                foreach (var minerHashes in byMiner)
                {
                    double minerTotalHashrate = 0;

                    await cf.RunTx(async (con, tx) =>
                    {
                        stats.Miner = minerHashes.Key;

                        // book keeping
                        currentNonZeroMinerWorkers.Add(buildKey(stats.Miner));

                        foreach (var item in minerHashes)
                        {
                            // set default values
                            double minerHashrate  = 0;
                            stats.Worker          = "Default_Miner";
                            stats.Hashrate        = 0;
                            stats.SharesPerSecond = 0;

                            // miner stats calculation windows
                            var TimeFrameBeforeFirstShare = ((minerHashes.Min(x => x.FirstShare) - TimeFrom).TotalSeconds);
                            var TimeFrameAfterLastShare   = ((CurrentTimeUtc - minerHashes.Max(x => x.LastShare)).TotalSeconds);
                            var TimeFrameFirstLastShare   = (StatsWindowsTimeFrame.TotalSeconds - TimeFrameBeforeFirstShare - TimeFrameAfterLastShare);

                            var minerHashTimeFrame = StatsWindowsTimeFrame.TotalSeconds;

                            if (TimeFrameBeforeFirstShare >= (StatsWindowsTimeFrame.TotalSeconds * 0.1))
                            {
                                minerHashTimeFrame = Math.Floor(StatsWindowsTimeFrame.TotalSeconds - TimeFrameBeforeFirstShare);
                            }

                            if (TimeFrameAfterLastShare >= (StatsWindowsTimeFrame.TotalSeconds * 0.1))
                            {
                                minerHashTimeFrame = Math.Floor(StatsWindowsTimeFrame.TotalSeconds + TimeFrameAfterLastShare);
                            }

                            if ((TimeFrameBeforeFirstShare >= (StatsWindowsTimeFrame.TotalSeconds * 0.1)) && (TimeFrameAfterLastShare >= (StatsWindowsTimeFrame.TotalSeconds * 0.1)))
                            {
                                minerHashTimeFrame = (StatsWindowsTimeFrame.TotalSeconds - TimeFrameBeforeFirstShare + TimeFrameAfterLastShare);
                            }

                            if (minerHashTimeFrame < 1)
                            {
                                minerHashTimeFrame = 1;
                            }
                            ;

                            // logger.Info(() => $"[{poolId}] StatsWindowsTimeFrame : {StatsWindowsTimeFrame.TotalSeconds} | minerHashTimeFrame : {minerHashTimeFrame} |  TimeFrameFirstLastShare : {TimeFrameFirstLastShare} | TimeFrameBeforeFirstShare: {TimeFrameBeforeFirstShare} | TimeFrameAfterLastShare: {TimeFrameAfterLastShare}");

                            // calculate miner/worker stats
                            minerHashrate       = pool.HashrateFromShares(item.Sum, minerHashTimeFrame);
                            minerHashrate       = Math.Floor(minerHashrate);
                            minerTotalHashrate += minerHashrate;
                            stats.Hashrate      = minerHashrate;

                            if (item.Worker != null)
                            {
                                stats.Worker = item.Worker;
                            }
                            stats.SharesPerSecond = Math.Round(((double)item.Count / minerHashTimeFrame), 3);

                            // persist. Save miner stats in DB.
                            await statsRepo.InsertMinerWorkerPerformanceStatsAsync(con, tx, stats);

                            // broadcast
                            messageBus.NotifyHashrateUpdated(pool.Config.Id, minerHashrate, stats.Miner, stats.Worker);
                            logger.Info(() => $"[{poolId}] Miner: {stats.Miner}.{stats.Worker} | Hashrate: {minerHashrate} | HashTimeFrame : {minerHashTimeFrame} | Shares per sec: {stats.SharesPerSecond}");

                            // book keeping
                            currentNonZeroMinerWorkers.Add(buildKey(stats.Miner, stats.Worker));
                        }
                    });

                    messageBus.NotifyHashrateUpdated(pool.Config.Id, minerTotalHashrate, stats.Miner, null);
                    logger.Info(() => $"[{poolId}] Total miner hashrate: {stats.Miner} | {minerTotalHashrate}");
                }
                // MinerNL end calculate & update miner, worker hashrates

                logger.Info(() => "--------------------------------------------");
            }
        }
Exemple #8
0
        private void UpdatePoolHashrates()
        {
            var start  = clock.Now;
            var target = start.AddSeconds(-HashrateCalculationWindow);

            var stats = new MinerWorkerPerformanceStats
            {
                Created = start
            };

            var poolIds = pools.Keys;

            foreach (var poolId in poolIds)
            {
                stats.PoolId = poolId;

                logger.Info(() => $"Updating hashrates for pool {poolId}");

                var pool = pools[poolId];

                // fetch stats
                var result = readFaultPolicy.Execute(() =>
                                                     cf.Run(con => shareRepo.GetHashAccumulationBetweenCreated(con, poolId, target, start)));

                var byMiner = result.GroupBy(x => x.Miner).ToArray();

                if (result.Length > 0)
                {
                    // calculate pool stats
                    var windowActual = (result.Max(x => x.LastShare) - result.Min(x => x.FirstShare)).TotalSeconds;

                    if (windowActual >= MinHashrateCalculationWindow)
                    {
                        var poolHashesAccumulated      = result.Sum(x => x.Sum);
                        var poolHashesCountAccumulated = result.Sum(x => x.Count);

                        // update
                        pool.PoolStats.ConnectedMiners = byMiner.Length;
                        pool.PoolStats.PoolHashrate    = pool.HashrateFromShares(poolHashesAccumulated, windowActual);
                        pool.PoolStats.SharesPerSecond = (int)(poolHashesCountAccumulated / windowActual);
                    }
                }

                // persist
                cf.RunTx((con, tx) =>
                {
                    var mapped = new Persistence.Model.PoolStats
                    {
                        PoolId  = poolId,
                        Created = start
                    };

                    mapper.Map(pool.PoolStats, mapped);
                    mapper.Map(pool.NetworkStats, mapped);

                    statsRepo.InsertPoolStats(con, tx, mapped);
                });

                if (result.Length == 0)
                {
                    continue;
                }

                // calculate & update miner, worker hashrates
                foreach (var minerHashes in byMiner)
                {
                    cf.RunTx((con, tx) =>
                    {
                        stats.Miner = minerHashes.Key;

                        foreach (var item in minerHashes)
                        {
                            // calculate miner/worker stats
                            var windowActual = (minerHashes.Max(x => x.LastShare) - minerHashes.Min(x => x.FirstShare)).TotalSeconds;

                            if (windowActual >= MinHashrateCalculationWindow)
                            {
                                var hashrate = item.Sum / windowActual;

                                // update
                                stats.Hashrate        = hashrate;
                                stats.Worker          = item.Worker;
                                stats.SharesPerSecond = (double)item.Count / windowActual;

                                // persist
                                statsRepo.InsertMinerWorkerPerformanceStats(con, tx, stats);
                            }
                        }
                    });
                }
            }
        }