Author

Topic: How to make sure that difficulty do not go less than 1? (Read 174 times)

full member
Activity: 615
Merit: 154
CEO of Metaisland.gg and W.O.K Corp
I have another question.

If I want the difficulty to increase faster than it decrease, what parameter should I change?

Code:
    if (nActualTimespan < params.nPowTargetTimespan/2)
        nActualTimespan = params.nPowTargetTimespan/2;
    if (nActualTimespan > params.nPowTargetTimespan*2)
        nActualTimespan = params.nPowTargetTimespan*2;
full member
Activity: 615
Merit: 154
CEO of Metaisland.gg and W.O.K Corp
The numbers there (bnNew, bnPowLimit, etc.) are not the difficulty. The difficulty value that we often see is not directly part of Bitcoin or the blockchain itself. Rather what we see in the blockchain is the target value. The target and difficulty are inversely related, as the target increases, the difficulty decreases. This is because mining works by finding a hash that is less than the target value, so by having  a larger target value, there are more possible valid block hashes and thus a lower difficulty.

The numbers bnNew, bnPowLimit, etc. are all compact representations of the target. This is then expanded out to a full target value that the block hash is compared to. This compact target value is what is included in blocks as the nBits field.

Bitcoin already limits the target to a maximum value which is equal to a difficulty of 1. If the target is that maximum value, its difficulty is said to be 1. This value is not explicitly listed in that function because it is different for mainnet, testnet, and regtest. This value is the variable that has the word powLimit in it. It is defined in src/chainparams.cpp.

There are two things that you are doing wrong: you are doing your limiting incorrectly, and you are doing the limiting after the built in limiter. Firstly, because difficulty decreases as target increases, you need to make the comparison a greater than operator (>) not less than (<) as you have done. If the target is above the maximum target, it needs to be decreased. What you done is set a target minimum, not a difficulty minimum. Look at the line directly above the one you added, that is the built in limiter that is correct. Secondly, you don't need to add your own limiter. Just change the powLimit variable for the correct blockchain in src/chainparams.cpp to the maximum and the limit will be done for you.

In fact, what you are asking has already been done. So I think you just fundamentally misunderstand how the PoW target actually works and what a difficulty of 1 actually looks like.

Thanks for this amazing answer, you are right, I got it wrong and your explanation is really helping me to understand how the target and difficulty are used. Merited +2
You saved me a lot of time trying and testing to find out by myself.
 Kiss
staff
Activity: 3458
Merit: 6793
Just writing some code
The numbers there (bnNew, bnPowLimit, etc.) are not the difficulty. The difficulty value that we often see is not directly part of Bitcoin or the blockchain itself. Rather what we see in the blockchain is the target value. The target and difficulty are inversely related, as the target increases, the difficulty decreases. This is because mining works by finding a hash that is less than the target value, so by having  a larger target value, there are more possible valid block hashes and thus a lower difficulty.

The numbers bnNew, bnPowLimit, etc. are all compact representations of the target. This is then expanded out to a full target value that the block hash is compared to. This compact target value is what is included in blocks as the nBits field.

Bitcoin already limits the target to a maximum value which is equal to a difficulty of 1. If the target is that maximum value, its difficulty is said to be 1. This value is not explicitly listed in that function because it is different for mainnet, testnet, and regtest. This value is the variable that has the word powLimit in it. It is defined in src/chainparams.cpp.

There are two things that you are doing wrong: you are doing your limiting incorrectly, and you are doing the limiting after the built in limiter. Firstly, because difficulty decreases as target increases, you need to make the comparison a greater than operator (>) not less than (<) as you have done. If the target is above the maximum target, it needs to be decreased. What you done is set a target minimum, not a difficulty minimum. Look at the line directly above the one you added, that is the built in limiter that is correct. Secondly, you don't need to add your own limiter. Just change the powLimit variable for the correct blockchain in src/chainparams.cpp to the maximum and the limit will be done for you.

In fact, what you are asking has already been done. So I think you just fundamentally misunderstand how the PoW target actually works and what a difficulty of 1 actually looks like.
full member
Activity: 615
Merit: 154
CEO of Metaisland.gg and W.O.K Corp
I know it might sound stupid because the difficulty of Bitcoin is so high that there is no way it could go less than one.

But, when you fork bitcoin and make some tests, you are usually using just one node to mine. It happens that the difficulty then go lower and lower to even go less than 1.
The division get down to 0.000xxx because the mining gear is not finding hash quick enough.

It can also happen if you want to mimic DigiByte and try to find hashes in a few seconds...instead of 10 minutes.

The code is in CalculateNextWorkRequired

Code:

unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
{
    if (params.fPowNoRetargeting)
        return pindexLast->nBits;

    // Limit adjustment step
    int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime;
    if (nActualTimespan < params.nPowTargetTimespan/2)
        nActualTimespan = params.nPowTargetTimespan/2;
    if (nActualTimespan > params.nPowTargetTimespan*2)
        nActualTimespan = params.nPowTargetTimespan*2;

    // Retarget
    const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
    arith_uint256 bnNew;
    bnNew.SetCompact(pindexLast->nBits);
    bnNew *= nActualTimespan;
    bnNew /= params.nPowTargetTimespan;

    // this is my attempt to limit the difficulty to > 0x1d00ffff but it is not working
    if (bnNew > bnPowLimit)  bnNew = bnPowLimit;
    if (bnNew <0x1d00ffff) bnNew=0x1d00ffff;

    printf("%s  %i\n", bnNew.ToString().c_str(), bnNew.GetCompact());

    return bnNew.GetCompact();
}


In the code I have modified to limit the difficulty to 0x1d00ffff no matter what, but it does not work.
Any clue where I am wrong?
Jump to: