Exemplo n.º 1
0
        public Target GetWorkRequired(ChainedHeader chainedHeaderToValidate, XRCConsensus consensus)
        {
            // Genesis block.
            if (chainedHeaderToValidate.Height == 0)
            {
                return(consensus.PowLimit2);
            }

            var XRCConsensusProtocol = (XRCConsensusProtocol)consensus.ConsensusFactory.Protocol;

            //hard fork
            if (chainedHeaderToValidate.Height == XRCConsensusProtocol.PowLimit2Height + 1)
            {
                return(consensus.PowLimit);
            }

            //hard fork 2 - DigiShield + X11
            if (chainedHeaderToValidate.Height > XRCConsensusProtocol.PowDigiShieldX11Height)
            {
                return(GetWorkRequiredDigiShield(chainedHeaderToValidate, consensus));
            }

            Target proofOfWorkLimit;

            // Hard fork to higher difficulty
            if (chainedHeaderToValidate.Height > XRCConsensusProtocol.PowLimit2Height)
            {
                proofOfWorkLimit = consensus.PowLimit;
            }
            else
            {
                proofOfWorkLimit = consensus.PowLimit2;
            }

            ChainedHeader lastBlock = chainedHeaderToValidate.Previous;
            int           height    = chainedHeaderToValidate.Height;

            if (lastBlock == null)
            {
                return(proofOfWorkLimit);
            }

            long difficultyAdjustmentInterval = GetDifficultyAdjustmentInterval(consensus);

            // Only change once per interval.
            if ((height) % difficultyAdjustmentInterval != 0)
            {
                if (consensus.PowAllowMinDifficultyBlocks)
                {
                    // Special difficulty rule for testnet:
                    // If the new block's timestamp is more than 2* 10 minutes
                    // then allow mining of a min-difficulty block.
                    if (chainedHeaderToValidate.Header.BlockTime > (lastBlock.Header.BlockTime + TimeSpan.FromTicks(consensus.TargetSpacing.Ticks * 2)))
                    {
                        return(proofOfWorkLimit);
                    }

                    // Return the last non-special-min-difficulty-rules-block.
                    ChainedHeader chainedHeader = lastBlock;
                    while ((chainedHeader.Previous != null) && ((chainedHeader.Height % difficultyAdjustmentInterval) != 0) && (chainedHeader.Header.Bits == proofOfWorkLimit))
                    {
                        chainedHeader = chainedHeader.Previous;
                    }

                    return(chainedHeader.Header.Bits);
                }

                return(lastBlock.Header.Bits);
            }

            // Go back by what we want to be 14 days worth of blocks.
            long pastHeight = lastBlock.Height - (difficultyAdjustmentInterval - 1);

            ChainedHeader firstChainedHeader = chainedHeaderToValidate.GetAncestor((int)pastHeight);

            if (firstChainedHeader == null)
            {
                throw new NotSupportedException("Can only calculate work of a full chain");
            }

            if (consensus.PowNoRetargeting)
            {
                return(lastBlock.Header.Bits);
            }

            // Limit adjustment step.
            TimeSpan actualTimespan = lastBlock.Header.BlockTime - firstChainedHeader.Header.BlockTime;

            if (actualTimespan < TimeSpan.FromTicks(consensus.TargetTimespan.Ticks / 4))
            {
                actualTimespan = TimeSpan.FromTicks(consensus.TargetTimespan.Ticks / 4);
            }
            if (actualTimespan > TimeSpan.FromTicks(consensus.TargetTimespan.Ticks * 4))
            {
                actualTimespan = TimeSpan.FromTicks(consensus.TargetTimespan.Ticks * 4);
            }

            // Retarget.
            BigInteger newTarget = lastBlock.Header.Bits.ToBigInteger();

            newTarget = newTarget.Multiply(BigInteger.ValueOf((long)actualTimespan.TotalSeconds));
            newTarget = newTarget.Divide(BigInteger.ValueOf((long)consensus.TargetTimespan.TotalSeconds));

            var finalTarget = new Target(newTarget);

            if (finalTarget > proofOfWorkLimit)
            {
                finalTarget = proofOfWorkLimit;
            }

            return(finalTarget);
        }
Exemplo n.º 2
0
        public Target GetWorkRequiredDigiShield(ChainedHeader chainedHeaderToValidate, XRCConsensus consensus)
        {
            var nAveragingInterval         = 10 * 5;  // block
            var multiAlgoTargetSpacingV4   = 10 * 60; // seconds
            var nAveragingTargetTimespanV4 = nAveragingInterval * multiAlgoTargetSpacingV4;
            var nMaxAdjustDownV4           = 16;
            var nMaxAdjustUpV4             = 8;
            var nMinActualTimespanV4       = TimeSpan.FromSeconds(nAveragingTargetTimespanV4 * (100 - nMaxAdjustUpV4) / 100);
            var nMaxActualTimespanV4       = TimeSpan.FromSeconds(nAveragingTargetTimespanV4 * (100 + nMaxAdjustDownV4) / 100);

            var           height           = chainedHeaderToValidate.Height;
            Target        proofOfWorkLimit = consensus.PowLimit2;
            ChainedHeader lastBlock        = chainedHeaderToValidate.Previous;
            ChainedHeader firstBlock       = chainedHeaderToValidate.GetAncestor(height - nAveragingInterval);

            var XRCConsensusProtocol = (XRCConsensusProtocol)consensus.ConsensusFactory.Protocol;

            if (((height - XRCConsensusProtocol.PowDigiShieldX11Height) <= (nAveragingInterval + this.MedianTimeSpan)) &&
                (consensus.CoinType == (int)XRCCoinType.CoinTypes.XRCMain))
            {
                return(new Target(new uint256("000000000001a61a000000000000000000000000000000000000000000000000")));
            }

            // Limit adjustment step
            // Use medians to prevent time-warp attacks
            TimeSpan nActualTimespan = GetAverageTimePast(lastBlock) - GetAverageTimePast(firstBlock);

            nActualTimespan = TimeSpan.FromSeconds(nAveragingTargetTimespanV4
                                                   + (nActualTimespan.TotalSeconds - nAveragingTargetTimespanV4) / 4);

            if (nActualTimespan < nMinActualTimespanV4)
            {
                nActualTimespan = nMinActualTimespanV4;
            }
            if (nActualTimespan > nMaxActualTimespanV4)
            {
                nActualTimespan = nMaxActualTimespanV4;
            }

            // Retarget.
            BigInteger newTarget = lastBlock.Header.Bits.ToBigInteger();

            newTarget = newTarget.Multiply(BigInteger.ValueOf((long)nActualTimespan.TotalSeconds));
            newTarget = newTarget.Divide(BigInteger.ValueOf((long)nAveragingTargetTimespanV4));

            var finalTarget = new Target(newTarget);

            if (finalTarget > proofOfWorkLimit)
            {
                finalTarget = proofOfWorkLimit;
            }

            return(finalTarget);
        }