Из From EIP 2 алгоритм настройки сложности Homestead таков:
block_diff = parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99) + int(2**((block.number // 100000) - 2))
где // — оператор целочисленного деления, например. 6 // 2 = 3, 7 // 2 = 3, 8 // 2 = 4.
Как это работает?
(Этот вопрос был вызван вопросом Какой был первый блок, добытый с помощью Homestead? )
Другие связанные вопросы и ответы:
Если разница временных меток (block_timestamp - parent_timestamp)
:
parent_diff // 2048 * 1
parent_diff // 2048 * -1
до максимальной регулировки внизparent_diff // 2048 * -99
Это согласуется с заявлением ethdocs.org — Ethereum Homestead — The Homestead Release :
EIP-2/4 устраняет избыточный стимул устанавливать разницу временных меток ровно 1, чтобы создать блок с немного более высокой сложностью, который, таким образом, гарантированно превзойдет все возможные форки. Это гарантирует сохранение времени блока в диапазоне 10-20 и, согласно моделированию, восстанавливает целевое время блока 15 секунд (вместо текущих эффективных 17 секунд).
А из Ethereum Network Status среднее время блока в настоящее время составляет 13,86 секунды.
Формула корректировки сложности:
block_diff = parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99) + int(2**((block.number // 100000) - 2))
где // — оператор целочисленного деления, например. 6 // 2 = 3, 7 // 2 = 3, 8 // 2 = 4.
можно разбить на следующие части:
Подформула B — часть бомбы сложности, которая экспоненциально увеличивает сложность каждые 100 000 блоков.
+ int(2**((block.number // 100000) - 2))
Бомба сложности здесь обсуждаться не будет, так как она уже рассмотрена в следующих вопросах и ответах:
Подформула A — часть регулировки сложности, которая увеличивает или уменьшает сложность блока в зависимости от времени между отметкой времени текущего блока и отметкой времени родительского блока:
+ parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99)
Подформула A1 - позволяет выделить часть подформулы A
+ max(1 - (block_timestamp - parent_timestamp) // 10, -99)
и рассмотрим, каков эффект корректировки из-за разницы временных меток между текущим блоком и родительским блоком:
Когда (block_timestamp - parent_timestamp)
_
max(1 - 0, -99) = 1
+parent_diff // 2048 * 1
max(1 - 1, -99) = 0
+parent_diff // 2048 * 0
max(1 - 2, -99) = -1
+parent_diff // 2048 * -1
max(1 - 3, -99) = -2
+parent_diff // 2048 * -2
max(1 - 100, -99) = -99
+parent_diff // 2048 * -99
max(1 - {number greater than 100}, -99) = -99
+parent_diff // 2048 * -99
Итак, если разница временных меток (block_timestamp - parent_timestamp)
:
parent_diff // 2048 * 1
parent_diff // 2048 * -1
до максимальной регулировки внизparent_diff // 2048 * -99
Из Go Ethereum — core/block_validator.go, строки 264-311 :
func calcDifficultyHomestead(time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.mediawiki
// 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).SetUint64(parentTime)
// 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(common.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(parentDiff, params.DifficultyBoundDivisor)
x.Mul(y, x)
x.Add(parentDiff, 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(parentNumber, common.Big1)
periodCount.Div(periodCount, ExpDiffPeriod)
// the exponential factor, commonly referred to as "the bomb"
// diff = diff + 2^(periodCount - 2)
if periodCount.Cmp(common.Big1) > 0 {
y.Sub(periodCount, common.Big2)
y.Exp(common.Big2, y, nil)
x.Add(x, y)
}
return x
}
Алгоритм Ethereum был бы лучше, если бы max() не использовался. Параметр parent_diff/2048*(1-t/10) можно было бы расширить, чтобы предотвратить появление нуля в результате целочисленного деления. Это привело бы к
diff = parent_diff + parent_diff/N - parent_diff*t/T/N
где t = родительское время решения T = целевое время решения N = коэффициент исчезновения, также известный как «среднее время жизни», также известный как количество блоков для «умерения» или «буферизации» размера ответа. Она не может быть слишком маленькой, иначе из-за длительного времени решения может возникнуть отрицательная сложность.
Это очень близко к теоретически лучшему алгоритму, который представляет собой экспоненциальную скользящую среднюю (EMA), которую исследовали я и другие. Это аппроксимация EMA разложением экспоненциальной функции в ряд Тейлора:
е ^ х = 1 + х + х ^ 2/2! + ...
Где вы используете приближение e^x = 1 + x в алгоритме EMA:
diff = parent_diff*( 1 - A + A*T/t )
где A = альфа = 1-e^(-t/T/N)
См. https://github.com/zawy12/difficulty-algorithms/issues/17 .
Этот алгоритм был открыт Джейкобом Элиософфом, который уже был хорошо знаком с EMA для цен на акции. Ему нужно было изменить его, чтобы он соответствовал сложности, и в результате получается известная версия, упомянутая в Википедии в отношении оценки производительности компьютера:
https://en.wikipedia.org/wiki/Moving_average#Application_to_measuring_computer_performance
Я говорю, что это теоретически лучше, потому что вы можете уменьшить N до «1», а среднее и медианное время решения близки к ожидаемым T и ln(2)*T. Так что это лучшая оценка (из известных мне) угадывания текущего хэшрейта на основе только предыдущего блока.
Галахад
20-29
секунд и30-39
секунд не является результатом A1-1
и-2
соответственно?великий волк
2048
магическое число, хотя? В чем идея деления на2048
и почему это число?Герман Юнге
Петр Доброгост
(19,20)
диапазона.Пол Разван Берг