¿Cómo calcular el nuevo valor de "bits"?

Cada 2016 bloques uno necesita calcular el valor de nuevos bits . ¿Cuál es la fórmula para calcularlo?

¿Estás preguntando cómo se calcula la dificultad o cómo los bits corresponden a la dificultad? ¿O ambos?
Entiendo cómo convertir bits-> dificultad, estoy preguntando cómo se ajusta la dificultad. Supongo que dada la marca de tiempo del bloque n y n+2015, hay una fórmula que también tiene en cuenta un redondeo específico para fijar el campo de bits en un bloque n+2016.
ESTÁ BIEN. Espero que mi respuesta te diga lo que querías saber. Es un poco largo, pero quería explicar el formato y los detalles de cómo se calculan los 'bits'.
Es interesante que preguntes sobre esto justo cuando las reglas están a punto de cambiar. Después del 15 de febrero de 2012, testnet se simplifica después de 20 minutos de búsqueda infructuosa de bloques.

Respuestas (3)

¿Qué bitsrepresenta el campo?

En primer lugar, debemos entender qué significa el campo 'bits'.

Bits está en formato 'compacto'. Es como un formato de punto flotante, pero representa números enteros grandes en lugar de números reales arbitrarios. El primer byte indica el número de bytes que ocupa el número representado, y los siguientes uno a tres bytes dan los dígitos más significativos del número. Si el segundo byte tiene un valor superior a 127, el número se interpreta como negativo.

Para convertir un entero positivo a formato 'compacto', hacemos lo siguiente:

  • convertir el entero en base 256.
  • si el primer dígito (el más significativo) es mayor que 127 (0x7f), anteponga un dígito cero
  • el primer byte del formato 'compacto' es el número de dígitos en la representación base 256 anterior, incluido el cero antepuesto si está presente
  • los siguientes tres bytes son los tres primeros dígitos de la representación anterior. Si hay menos de tres dígitos, uno o más de los últimos bytes de la representación compacta serán cero.

Ejemplo 1: convertir 1000 a formato 'compacto'

Por ejemplo, para representar 1000 en formato 'compacto', convertimos a base 256:

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

Entonces tenemos un número de base 256 de 2 dígitos:

03 e8

El primer dígito no es mayor que 0x7f, por lo que no anteponemos un dígito cero:

03 e8

Entonces la representación compacta se convierte en:

02 03 e8 00

Ejemplo 2: convertir objetivo máximo a formato 'compacto'

La dificultad mínima tiene un objetivo de 2^(256-32)-1. Representemos eso en formato 'compacto'. Primero lo convertimos a base 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

Eso es 28 dígitos 0xff. El primer dígito es mayor que 0x7f, por lo que anteponemos un dígito cero:

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

Ahora tiene 29 dígitos. hexadecimal(29) = 0x1d. Así que la representación 'compacta' de esto es:

1d 00 ff ff

Observe que hemos perdido muchos dígitos 'ff' allí. Solo hemos mantenido 2 bytes de precisión, con el byte de tamaño y el byte cero antepuesto usando dos de los cuatro bytes disponibles. Si tuviéramos que volver a convertir desde el formato 'compacto' para ver qué número hemos almacenado realmente, obtendríamos:

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

que es, de hecho, el objetivo máximo utilizado por Bitcoin. Esto es lo que una dificultad de 1 establece como objetivo de hash de bloque.

bits¿Cómo se calcula el valor del campo?

Ahora que sabemos lo que bitssignifica el campo, podemos ver cómo se decide su valor. En el cliente oficial, el bitsvalor se calcula mediante la función GetNextWorkRequired()en src/main.cpp, que hace lo siguiente:

  • si estamos trabajando en un bloque que es un múltiplo de 2016 (cada 2 semanas)
    • mire las marcas de tiempo en el último bloque y el bloque 2015 bloques antes de él
    • calcular la diferencia en estas dos marcas de tiempo
    • si la diferencia es mayor a 8 semanas, configúrelo en 8 semanas; esto evita que la dificultad disminuya en más de un factor de 4
    • si la diferencia es inferior a media semana, configúrelo en media semana; esto evita que la dificultad aumente en más de un factor de 4
    • multiplique la diferencia por el objetivo actual (es decir, la bitsconversión actual de la representación 'compacta' al objetivo que representa)
    • dividir el resultado por 2 semanas
    • si el resultado es mayor que el objetivo máximo ( 2^(256-32)-1), configúrelo en el objetivo máximo
    • convierta el resultado a la forma 'compacta' y utilícelo como el nuevo bitsvalor
  • de lo contrario (estamos trabajando en un bloque que NO es un múltiplo de 2016
    • si estamos en testnet y es posterior al 15 de febrero de 2012
      • si han pasado más de 20 minutos desde que se encontró el último bloque
        • establecido bitsen su valor más alto posible 0x1d00ffff, lo que representa una dificultad de 1; esta es la ' special-min-difficultyregla'
      • de lo contrario
        • establecido bitsen el mismo que en el último special-min-difficultybloque no regla
    • de lo contrario (no estamos en testnet, o es antes del 15 de febrero de 2012)
      • establecido bitsen el mismo que en el último bloque
2^224 no es lo que presentaste, ¿quisiste decir 2^224-1? wolframalpha.com/input/?i=2%5E224+in+hexadecimal
Sí, lo hice. ¡Gracias! He corregido mi respuesta en consecuencia.
Una cosa para agregar es que el objetivo nunca cambia +- un factor de 4 por cambio
@makerofthings7 que está cubierto por "si la diferencia es mayor a 8 semanas, configúrelo en 8 semanas" y la siguiente línea. Expandí esas líneas para dejar claro para qué sirven.
Gracias y ahora veo, todavía estoy trabajando en mis habilidades de traducción de C ++ a inglés;)

Aquí está el código relevante de 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();

Así que los pasos importantes son:

  1. Traduce los bits del bloque n+2015 a un objetivo BigNum.
  2. Calcule el intervalo de tiempo entre los bloques n y n+2015 (como un número entero de segundos).
  3. Multiplique el objetivo anterior por el intervalo de tiempo.
  4. Divida el resultado por el intervalo de tiempo deseado 2 semanas = 1209600 segundos. Esta es la aritmética de enteros, por lo que se redondea hacia abajo. El resultado es el nuevo objetivo.
  5. Convierta el objetivo en bits.

El código de la clase CBigNum está en bignum.h.

utilizo el siguiente código de python para convertir de ida y vuelta entre "objetivo" y "bits":

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))
¿Dónde está el bloque def bin2int() en su código?
@JamesBond Lo acabo de agregar