Example #1
0
    public static double?IdleUpdate(WorkerContextBase context, VarDiffConfig options, IMasterClock clock)
    {
        var ctx        = context.VarDiff;
        var difficulty = context.Difficulty;

        // abort if a regular update is just happening
        if (!Monitor.TryEnter(ctx))
        {
            return(null);
        }

        try
        {
            var    now = clock.Now;
            var    ts  = now.ToUnixSeconds();
            double timeDelta;

            if (ctx.LastTs.HasValue)
            {
                timeDelta = ts - ctx.LastTs.Value;
            }
            else
            {
                timeDelta = ts - ctx.Created.ToUnixSeconds();
            }

            timeDelta += SafetyMargin;

            // we only get involved if there was never an update or the last update happened longer than retargetTime ago
            if (timeDelta < options.RetargetTime)
            {
                return(null);
            }

            // update the last time
            ctx.LastTs = ts;

            var minDiff = options.MinDiff;
            var maxDiff = options.MaxDiff ?? Math.Max(minDiff, double.MaxValue); // for regtest

            // Always calculate the time until now even there is no share submitted.
            var timeTotal = (ctx.TimeBuffer?.Sum() ?? 0) + (timeDelta - SafetyMargin);
            var avg       = timeTotal / ((ctx.TimeBuffer?.Size ?? 0) + 1);

            // Possible New Diff
            var newDiff = difficulty * options.TargetTime / avg;

            if (TryApplyNewDiff(ref newDiff, difficulty, minDiff, maxDiff, ts, ctx, options, clock))
            {
                return(newDiff);
            }
        }

        finally
        {
            Monitor.Exit(ctx);
        }

        return(null);
    }
Example #2
0
    protected override async Task <double?> GetNicehashStaticMinDiff(WorkerContextBase context, string coinName, string algoName)
    {
        var result = await base.GetNicehashStaticMinDiff(context, coinName, algoName);

        // adjust value to fit with our target value calculation
        if (result.HasValue)
        {
            result = result.Value / uint.MaxValue;
        }

        return(result);
    }
Example #3
0
        public void VarDiff_Should_Honor_MinDiff_When_Adjusting_Down()
        {
            var vdm = new VarDiffManager(config);
            var ctx = new WorkerContextBase {
                Difficulty = 1500, VarDiff = new VarDiffContext()
            };

            var shares = new List <long> {
                2000000000, 3000000000, 4000000000
            };
            var newDiff = vdm.Update(ctx, shares, string.Empty, logger);

            Assert.NotNull(newDiff);
            Assert.True(newDiff.Value.EqualsDigitPrecision3(1000));
        }
        public void VarDiff_Should_Honor_MaxDelta_When_Adjusting_Up()
        {
            var vdm = new VarDiffManager(config, clock);
            var ctx = new WorkerContextBase {
                Difficulty = 7500, VarDiff = new VarDiffContext()
            };

            var shares = new List <long> {
                2, 3, 4
            };
            var newDiff = vdm.Update(ctx, shares, string.Empty, logger);

            Assert.NotNull(newDiff);
            Assert.True(newDiff.Value.EqualsDigitPrecision3(8500));
        }
Example #5
0
        public double?Update(WorkerContextBase ctx, IList <long> shares, string connectionId, ILogger logger)
        {
            Contract.RequiresNonNull(ctx, nameof(ctx));
            logger.Debug(() => $"Update");

            lock (ctx)
            {
                var    difficulty = ctx.Difficulty;
                var    minDiff    = options.MinDiff;
                var    maxDiff    = options.MaxDiff ?? double.MaxValue;
                double?newDiff    = null;

                if ((shares.Count > 0 && ctx.VarDiff.LastShareTs.HasValue) || shares.Count > 1)
                {
                    // make timestamps relative to each other
                    var tsRelative = new List <long>();

                    // first value is relative to last value of previous buffer
                    if (ctx.VarDiff.LastShareTs.HasValue)
                    {
                        tsRelative.Add(Math.Max(0, shares[0] - ctx.VarDiff.LastShareTs.Value));
                    }

                    for (var i = 1; i < shares.Count; i++)
                    {
                        tsRelative.Add(Math.Max(0, shares[i] - shares[i - 1]));
                    }

                    // take average
                    var avg = tsRelative.Average() / 1000d;

                    // re-target if outside bounds
                    if (avg < tMin || avg > tMax)
                    {
                        var change = options.TargetTime / avg;
                        newDiff = difficulty * change;

                        // prevent huge jumps
                        var delta = newDiff.Value - ctx.Difficulty;
                        if (Math.Abs(delta) > maxJump)
                        {
                            newDiff = difficulty + (delta > 0 ? maxJump : -maxJump);
                        }

                        // round to next 100 if big enough
                        if (newDiff > 1000)
                        {
                            newDiff = Math.Round(newDiff.Value / 100d, 0) * 100;
                        }
                    }

                    // store
                    ctx.VarDiff.LastShareTs  = shares.Last();
                    ctx.VarDiff.SilenceCount = 0;
                }

                else
                {
                    ctx.VarDiff.SilenceCount++;

                    // radical measures if there were no shares submitted at all within the buffer window
                    newDiff = difficulty / Math.Pow(2, ctx.VarDiff.SilenceCount);
                }

                if (newDiff.HasValue)
                {
                    // clamp to min/max
                    if (newDiff < minDiff)
                    {
                        newDiff = minDiff;
                    }
                    else if (newDiff > maxDiff)
                    {
                        newDiff = maxDiff;
                    }

                    // check if different
                    if (!newDiff.Value.EqualsDigitPrecision3(ctx.Difficulty))
                    {
                        ctx.VarDiff.LastUpdate = clock.UtcNow;
                    }
                    else
                    {
                        newDiff = null;
                    }
                }

                return(newDiff);
            }
        }
Example #6
0
    private const double SafetyMargin = 1;  // ensure we don't miss a cycle due a sub-second fraction delta;

    public static double?Update(WorkerContextBase context, VarDiffConfig options, IMasterClock clock)
    {
        var ctx        = context.VarDiff;
        var difficulty = context.Difficulty;
        var now        = clock.Now;
        var ts         = now.ToUnixSeconds();

        try
        {
            Monitor.Enter(ctx);

            if (ctx.LastTs.HasValue)
            {
                var minDiff   = options.MinDiff;
                var maxDiff   = options.MaxDiff ?? Math.Max(minDiff, double.MaxValue); // for regtest
                var timeDelta = ts - ctx.LastTs.Value;

                // make sure buffer exists as this point
                ctx.TimeBuffer ??= new CircularBuffer <double>(BufferSize);

                // Always calculate the time until now even there is no share submitted.
                var timeTotal = ctx.TimeBuffer.Sum() + timeDelta;
                var avg       = timeTotal / (ctx.TimeBuffer.Size + 1);

                // Once there is a share submitted, store the time into the buffer and update the last time.
                ctx.TimeBuffer.PushBack(timeDelta);
                ctx.LastTs = ts;

                // Check if we need to change the difficulty
                var variance = options.TargetTime * (options.VariancePercent / 100.0);
                var tMin     = options.TargetTime - variance;
                var tMax     = options.TargetTime + variance;

                if (ts - ctx.LastRetarget < options.RetargetTime || avg >= tMin && avg <= tMax)
                {
                    return(null);
                }

                // Possible New Diff
                var newDiff = difficulty * options.TargetTime / avg;

                if (TryApplyNewDiff(ref newDiff, difficulty, minDiff, maxDiff, ts, ctx, options, clock))
                {
                    return(newDiff);
                }
            }

            else
            {
                // init
                ctx.LastRetarget = ts;
                ctx.LastTs       = ts;
            }
        }

        finally
        {
            Monitor.Exit(ctx);
        }

        return(null);
    }
Example #7
0
 public void SetContext <T>(T value) where T : WorkerContextBase
 {
     context = value;
 }