Как рассчитать новое значение «бит»?

Каждые 2016 блоков необходимо вычислить новое значение битов . По какой формуле его вычислить?

Вы спрашиваете, как рассчитывается сложность или как биты соответствуют сложности? Или оба?
Я понимаю, как конвертировать биты->сложность, я спрашиваю, как настраивается сложность. Я предполагаю, что с учетом временной метки из блока n и n+2015 для нее есть формула, которая также учитывает некоторое конкретное округление, чтобы заполнить поле битов в блоке n+2016.
ХОРОШО. Надеюсь, мой ответ расскажет вам то, что вы хотели знать. Это довольно длинно, но я хотел объяснить формат, а также детали того, как вычисляются «биты».
Интересно, что вы спрашиваете об этом как раз в тот момент, когда правила вот-вот изменятся. После 15 февраля 2012 года тестовая сеть становится легкой после 20 минут бесплодного поиска блоков.

Ответы (3)

Что bitsпредставляет поле?

Прежде всего, нам нужно понять, что означает поле «биты».

Биты в «компактном» формате. Это похоже на формат с плавающей запятой, но он представляет большие целые числа, а не произвольные действительные числа. Первый байт указывает количество байтов, которое занимает представленное число, а следующие от одного до трех байтов дают старшие значащие цифры числа. Если 2-й байт имеет значение больше 127, то число интерпретируется как отрицательное.

Чтобы преобразовать положительное целое число в «компактный» формат, мы:

  • преобразовать целое число в основание 256.
  • если первая (самая значащая) цифра больше 127 (0x7f), добавьте нулевую цифру
  • первый байт «компактного» формата — это количество цифр в приведенном выше представлении с основанием 256, включая предшествующий ноль, если он присутствует
  • следующие три байта являются первыми тремя цифрами приведенного выше представления. Если присутствует менее трех цифр, то один или несколько последних байтов компактного представления будут равны нулю.

Пример 1. Преобразование 1000 в «компактный» формат

Например, чтобы представить 1000 в «компактном» формате, мы конвертируем в основание 256:

1000 = (0x03)*256 + (0xe8)*1

Итак, у нас есть двухзначный номер с основанием 256:

03 e8

Первая цифра не больше 0x7f, поэтому мы не добавляем нулевую цифру:

03 e8

Тогда компактное представление принимает вид:

02 03 e8 00

Пример 2. Преобразование максимального целевого значения в «компактный» формат

Минимальная сложность имеет цель 2^(256-32)-1. Представим это в «компактном» формате. Сначала мы преобразуем его в основание 256:

ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff

Это 28 цифр 0xff. Первая цифра больше 0x7f, поэтому мы добавляем нулевую цифру:

00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff

Теперь это 29 цифр. шестнадцатеричный (29) = 0x1d. Таким образом, «компактное» представление этого:

1d 00 ff ff

Обратите внимание, что мы потеряли много цифр 'ff'. Мы сохранили только 2 байта точности, что с байтом размера и добавленным нулевым байтом, использующим два из четырех доступных байтов. Если бы нам нужно было преобразовать обратно из «компактного» формата, чтобы увидеть, какое число мы фактически сохранили, мы получим:

ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

что на самом деле является максимальной целью, используемой Биткойном. Это то, что сложность 1 устанавливает цель хэша блока.

Как bitsрассчитывается значение поля?

Теперь, когда мы знаем, что bitsозначает поле, мы можем посмотреть, как определяется его значение. В официальном клиенте bitsзначение вычисляется функцией GetNextWorkRequired()в src/main.cpp, которая делает следующее:

  • если мы работаем над блоком, кратным 2016 (каждые 2 недели)
    • посмотрите временные метки на последнем блоке и блок 2015 перед ним
    • вычислить разницу в этих двух метках времени
    • если разница больше 8 недель, установите ее на 8 недель; это предотвращает снижение сложности более чем в 4 раза
    • если разница меньше половины недели, установите ее на полнедели; это предотвращает увеличение сложности более чем в 4 раза
    • умножьте разницу на текущую цель (т. е. ток, bitsпреобразованный из «компактного» представления в цель, которую он представляет)
    • разделить результат на 2 недели
    • если результат больше максимального целевого значения ( 2^(256-32)-1), установите его на максимальное целевое значение
    • преобразовать результат в «компактную» форму и использовать его как новое bitsзначение
  • в противном случае (мы работаем над блоком, который НЕ кратен 2016
    • если мы в тестовой сети и это позднее 15 февраля 2012 г.
      • если с момента обнаружения последнего блока прошло более 20 минут
        • установите bitsмаксимально возможное значение 0x1d00ffff, что соответствует сложности 1; это " special-min-difficultyправило"
      • в противном случае
        • установить bitsтак же, как и в последнем special-min-difficultyблоке без правил
    • в противном случае (мы не в тестовой сети или до 15 февраля 2012 г.)
      • установить bitsтак же, как в последнем блоке
2 ^ 224 - это не то, что вы представили, вы имели в виду 2 ^ 224-1? wolframalpha.com/input/?i=2%5E224+in+hex
Да. Спасибо! Я исправил свой ответ соответственно.
Стоит добавить, что цель никогда не меняется +- коэффициент 4 на каждое изменение.
@makerofthings7, на который указывает «если разница больше 8 недель, установите ее на 8 недель» и следующую строку. Я расширил эти строки, чтобы было понятно, для чего они нужны.
Спасибо, и теперь я вижу, я все еще работаю над своими навыками перевода с C ++ на английский язык;)

Вот соответствующий код из main.cpp:

static const int64 nTargetTimespan = 14 * 24 * 60 * 60; // two weeks
static const int64 nTargetSpacing = 10 * 60;
static const int64 nInterval = nTargetTimespan / nTargetSpacing;

...

// Go back by what we want to be 14 days worth of blocks
const CBlockIndex* pindexFirst = pindexLast;
for (int i = 0; pindexFirst && i < nInterval-1; i++)
    pindexFirst = pindexFirst->pprev;
assert(pindexFirst);

// Limit adjustment step
int64 nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();
printf(" nActualTimespan = %"PRI64d" before bounds\n", nActualTimespan);
if (nActualTimespan < nTargetTimespan/4)
    nActualTimespan = nTargetTimespan/4;
if (nActualTimespan > nTargetTimespan*4)
    nActualTimespan = nTargetTimespan*4;

// Retarget
CBigNum bnNew;
bnNew.SetCompact(pindexLast->nBits);
bnNew *= nActualTimespan;
bnNew /= nTargetTimespan;

if (bnNew > bnProofOfWorkLimit)
    bnNew = bnProofOfWorkLimit;

...

return bnNew.GetCompact();

Итак, важные шаги:

  1. Переведите биты блока n+2015 в цель BigNum.
  2. Вычислить промежуток времени между блоками n и n+2015 (как целое число секунд).
  3. Умножьте старую цель на промежуток времени.
  4. Разделите результат на желаемый промежуток времени 2 недели = 1209600 секунд. Это целочисленная арифметика, поэтому она округляется в меньшую сторону. Результат - новая цель.
  5. Преобразуйте цель в биты.

Код класса CBigNum находится в bignum.h.

я использую следующий код Python для преобразования туда и обратно между «целью» и «битами»:

import binascii

def target_int2bits(target):
    # comprehensive explanation here: bitcoin.stackexchange.com/a/2926/2116

    # get in base 256 as a hex string
    target_hex = int2hex(target)

    bits = "00" if (hex2int(target_hex[: 2]) > 127) else ""
    bits += target_hex # append
    bits = hex2bin(bits)
    length = int2bin(len(bits), 1)

    # the bits value could be zero (0x00) so make sure it is at least 3 bytes
    bits += hex2bin("0000")

    # the bits value could be bigger than 3 bytes, so cut it down to size
    bits = bits[: 3]

    return length + bits

def bits2target_int(bits_bytes):
    exp = bin2int(bits_bytes[: 1]) # exponent is the first byte
    mult = bin2int(bits_bytes[1:]) # multiplier is all but the first byte
    return mult * (2 ** (8 * (exp - 3)))

def int2hex(intval):
    hex_str = hex(intval)[2:]
    if hex_str[-1] == "L":
        hex_str = hex_str[: -1]
    if len(hex_str) % 2:
        hex_str = "0" + hex_str
    return hex_str

def hex2int(hex_str):
    return int(hex_str, 16)

def hex2bin(hex_str):
    return binascii.a2b_hex(hex_str)

def int2bin(val, pad_length = False):
    hexval = int2hex(val)
    if pad_length: # specified in bytes
        hexval = hexval.zfill(2 * pad_length)
    return hex2bin(hexval)

def bin2hex(binary):
    # convert raw binary data to a hex string. also accepts ascii chars (0 - 255)
    return binascii.b2a_hex(binary)

def bin2int(binary):
    return hex2int(bin2hex(binary))
Где в вашем коде находится блок def bin2int() ?
@JamesBond Я только что добавил это