go-ethereum modifies the mining cycle

    Now the Ethereum public chain uses the geth mining cycle to produce a new block in about 15 seconds. When I build a private chain based on the go-ethereum source code, what should I modify if I want to speed up the mining block cycle? The first thought of many people is to modify the difficulty in the genesis.json file of the genesis configuration file and change it to a smaller value, such as 0x10000. After running on the computer, I found that mining is basically a few blocks per second, which is a bit too fast. So I changed it to 0x20000, and found that the block is still a few blocks of 1s. This method of making up is not very reliable.

    Ethereum uses the PoW workload proof mechanism for mining. The simplest understanding is to find an integer nonce such that the hash value sha3(data+nonce)<M/difficulty. The greater the difficulty, the greater the difficulty of mining, and vice versa, the easier it is to mine. Check out the function for calculating the difficulty value in Ethereum, in go-ethereum/consensus/ethash/consensus.go:

func CalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Header) *big.Int {
	//return big.NewInt(0x100000);
	next := new(big.Int).Add(parent.Number, big1)
	switch {
	case config.IsByzantium(next):
		return calcDifficultyByzantium(time, parent)
	case config.IsHomestead(next):
		return calcDifficultyHomestead(time, parent)
	default:
		return calcDifficultyFrontier(time, parent)
	}
}

    For version 1.8.1, use the calcDifficultyHomestead function:

func calcDifficultyHomestead(time uint64, parent *types.Header) *big.Int {
	// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.md
	// algorithm:
	// diff = (parent_diff +
	//         (parent_diff / 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99))
	//        ) + 2^(periodCount - 2)

	bigTime := new(big.Int).SetUint64(time)
	bigParentTime := new(big.Int).Set(parent.Time)

	// holds intermediate values to make the algo easier to read & audit
	x := new(big.Int)
	y := new(big.Int)

	// 1 - (block_timestamp - parent_timestamp) // 10
	x.Sub(bigTime, bigParentTime)
	x.Div(x, big10)
	x.Sub(big1, x)

	// max(1 - (block_timestamp - parent_timestamp) // 10, -99)
	if x.Cmp(bigMinus99) < 0 {
		x.Set(bigMinus99)
	}
	// (parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99))
	y.Div(parent.Difficulty, params.DifficultyBoundDivisor)
	x.Mul(y, x)
	x.Add(parent.Difficulty, x)

	// minimum difficulty can ever be (before exponential factor)
	if x.Cmp(params.MinimumDifficulty) < 0 {
		x.Set(params.MinimumDifficulty)
	}
	// for the exponential factor
	periodCount := new(big.Int).Add(parent.Number, big1)
	periodCount.Div(periodCount, expDiffPeriod)

	// the exponential factor, commonly referred to as "the bomb"
	// diff = diff + 2^(periodCount - 2)
	if periodCount.Cmp(big1) > 0 {
		y.Sub(periodCount, big2)
		y.Exp(big2, y, nil)
		x.Add(x, y)
	}
	return x
}

    Looking at the function comments, the algorithm for calculating difficulty is:

    diff = (parent_diff +
         (parent_diff / 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99))
        ) + 2^(periodCount - 2)

Divided into 3 parts, the first item is parent_diff, the difficulty value of the parent block; the second item is the difficulty adjustment value parent_diff / 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99), the third item is Difficulty bomb, difficulty bomb=2^(blockNumber/100000-2), the difficulty increases by 2 every 100,000 blocks.

    The key is the second difficulty adjustment, Y=parent_diff / 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99), this expression seems so long, it doesn't make sense at first glance. Carefully analyze, deltaTime=block_timestamp - parent_timestamp, and the generation time difference between the current block and the previous block. //The operator means to divide first and then round down. When deltaTime<10s, Y=parrent_diff/2048; when 10<deltaTime<20, Y=0; when Y>=20, Y=-parrent_diff/2048. This is very clear at a glance. This is the idea of ​​using negative feedback regulation in automatic control. When the time difference is less than 10s, increase the difficulty to make the time longer. When the time difference is between 10s and 20s, the difficulty does not change. When the time difference is greater than 20s, reduce the difficulty to make mining easier. The average mining time is between 10 and 20, and the final average time is about 15s.

    It is the divisor 10 that determines the cycle. If the divisor 10 is changed to 2, the mining cycle will be between 2 and 4 seconds. Just modify it like this:

     x.Div(x, big10)     ==> x.Div(x,big.NewInt(2))  

    It seems so simple, the key is to clarify this logic.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326010409&siteId=291194637