Wie wird der Zielabschnitt eines Blockheaders berechnet?

Ich habe auf https://en.bitcoin.it/wiki/Target herumgestöbert und das aktuelle Ziel gefunden, aber ich kann anscheinend nicht herausfinden, wie es generiert wird. Es wird angeblich generiert, wenn die Schwierigkeit angepasst wird, wie hier angegeben: https://en.bitcoin.it/wiki/Block_hashing_algorithm , aber was genau ist der Algorithmus zum Generieren des Ziels? Wenn mir jemand einen Pseudocode zeigen könnte, wäre das großartig.

Es ist mir nicht klar, ob Sie nach einer verbalen Erklärung des Schwierigkeitsalgorithmus, der spezifischen Codezeile, wo sie zu finden ist, oder einer schrittweisen Erklärung des Codes suchen. Vielleicht könnten Sie Ihre Frage bearbeiten, um sie zu klären. Wenn Sie nach dem ersten fragen: mögliches Duplikat von Wie wird die Schwierigkeit berechnet?
Ist Schwierigkeit dasselbe wie das Ziel?
Schwierigkeit ist im Wesentlichen die menschenlesbare Darstellung des Ziels. Siehe hier: Was ist „Schwierigkeit“ und wie bezieht es sich auf „Ziel“?

Antworten (3)

Der Zielabschnitt des Blockheaders heißt im Code nBits . nBits ist eine kompakte 32-Bit-Codierung eines 256-Bit-Zielschwellenwerts. Es funktioniert wie die wissenschaftliche Notation, außer dass es die Basis 256 anstelle der Basis 10 verwendet. Wenn nBits beispielsweise gleich 0x181b8330 ist, würden Sie es wie folgt berechnen:

nBits-Formel

Oder, einfacher gesagt, verwenden Sie die gleiche Abkürzung wie bei der normalen wissenschaftlichen Notation:

nBits schnell

An einem Re-Target-Punkt (jeden 2.016. Block) passt Bitcoin Core nBits gemäß den in dieser Antwort beschriebenen Regeln an, außer dass es wichtig ist zu beachten, dass, wenn sich die Schwierigkeit um p Prozent ändert, nBits um den Kehrwert ( -p Prozent ) angepasst werden ). Das liegt daran, dass ein niedrigeres Ziel bei der Implementierung von Bitcoin schwerer zu erreichen ist.

Es ist auch wichtig zu beachten, dass Sie den Exponententeil von nBits nicht einfach auf die offensichtliche Weise anpassen können, da Satoshi, als er den Code zum ersten Mal schrieb, von einem signierten Typ geerbt hat – daher muss besonders darauf geachtet werden, keine negativen nBits zu erstellen Wert. Die Bitcoin.org-Entwicklerreferenz enthält weitere Details (aber seien Sie vorsichtig, ich habe diesen Abschnitt noch nicht von einem Experten überprüfen lassen).

Können Sie erklären, wie das Base-256 ist? Sicherlich würden wir für die Basis 256 256 eindeutige Symbole benötigen?
@ElRonnoco Es hat 256 eindeutige Symbole: Jedes Byte ist ein Symbol. (Jedenfalls für die Analogie; die Exponentialschreibweise erfordert nicht wirklich, dass die Basis überhaupt mit Symbolen übereinstimmt; tatsächlich verwenden Mathematiker häufig die Basis $e$ . )

Ich bin mir nicht sicher, wie dies tatsächlich im Code implementiert ist, aber Sie können den neuen Zielwert (nBits) mit Daten aus dem vorherigen 2016. Block annähern. Beachten Sie, dass nBits, wie oben beschrieben, die 32-Bit-Kompaktcodierung des 256-Bit-Zielwerts ist.

Hier zeigt die neue Schwierigkeit (d_new) als:

d_neu = d_alt * 2 Wochen / t_alt

wobei „old“ die vorherigen 2016-Blöcke bezeichnet und t_old die Zeit ist, die benötigt wurde, um diese vorherigen 2016-Blöcke zu finden.

Hier zeigt d_new aus Genesis-Blockwerten als:

d_new = nBits_genesis / nBits_new und ähnlich
d_old = nBits_genesis / nBits_old

Die Kombination dieser 3 Gleichungen ergibt

nBits_new = (t_old / 2 Wochen) * nBits_old

Wenn wir also die Zeitstempel des neuen Blocks und des vorherigen 2016. Blocks und das Ziel des vorherigen 2016. Blocks kennen, können wir uns dem neuen Zielwert annähern. Zum Beispiel:

Block 703584
nBits = 0x170e2632 = 927282 * 256^(23-3)
Zeitstempel 04.10.2021 16:35:19

Block 701568 (der vorherige 2016. Block)
nBits = 0x170ed0eb = 970987 * 256^(23-3)
Zeitstempel 2021-09-21 07:34:36

Also
t_old = 13 Tage 9h 33s = 1155633s und 2 Wochen = 1209600s
nBits_old = 970987 * 256^(23-3)
Somit ist das neue Ziel ungefähr
1155633/1209600 * 256^20
= 0,955384424 * 970987 * 292726 = ,,9266 ^20

Beim Konvertieren in das kompakte 32-Bit-Format erhalten wir nBits_new ~ 0x170e27b2

Die Mantisse 927666 (0x0e27b2) liegt nahe an der tatsächlichen Mantisse 927282 (0x0e2632). Es ist eine vernünftige Annäherung, aber offensichtlich sind die absoluten Werte der Ziele ziemlich unterschiedlich, weil es sich um Basis 256 handelt. Der Fehler hier ist wahrscheinlich auf das Runden auf die nächste Sekunde in den Zeitstempeln zurückzuführen. Auch wenn dies nicht die explizite Berechnung im Code ist, hoffe ich, dass es zum allgemeinen Verständnis beiträgt, einschließlich der Verweise hier und hier .

Ich habe eine funktionierende c#-Implementierung der nBits-Berechnung. Ich habe getestet und es funktioniert. Denken Sie jedoch daran, dass meine Maschine Little Endian ist, sodass die Implementierung dies berücksichtigt. Wenn Ihre Maschine Big Endian ist, wäre die Art und Weise, wie Sie die nBits-Bytes einlesen würden, anders. Wenn Sie nicht wissen, wie Sie changeFactor erhalten, finden Sie die Schritte unten nach dem Code.

changeFactor ist das Verhältnis der Zeit, die zum Mining der letzten 2015 -Blöcke benötigt wurde, zur erwarteten Zeit von 10 Minuten pro Block. {Bitte ist kein Tippfehler. Es sind die letzten 2015-Blöcke, die Sie bei der Berechnung des Änderungsfaktors berücksichtigen, obwohl Sie nBits nur nach jeweils 2016-Blöcken neu berechnen}.

tatsächliche Zeit der letzten 2015-Blöcke = unixEpoch des aktuell höchsten Blocks - unixEpoch des Blocks mit blockHeight gleich [currentHighestBlockHeight - 2014] {wiederum kein Tippfehler}

erwartete Zeit = 2016 * 10 * 60 = 1209600

Änderungsfaktor = aktuelle Zeit / erwartete Zeit. Es gibt jedoch eine Grenze für den Änderungsfaktor. Pro Retargeting-Zyklus darf es keine Änderung von mehr als 400 % geben.

Nachdem Sie also den Änderungsfaktor erhalten haben, machen Sie das ff. um es innerhalb der festgelegten Grenzen zu halten, bevor es der Retargeting-Funktion zugeführt wird.

if (changeFactor > 4) changeFactor = 4;
if (changeFactor < 0.25) changeFactor = 0.25;

Schließlich sind oldNBits nur die nBits des aktuellen Highest-Blocks in uint-Form. Hoffe das hilft.

public static uint RetargetByFactor(uint oldNBits, double changeFactor)
        {
            // convert change factor to rational number with numerator and denomenator
            BigInteger numerator = 0;
            BigInteger denomenator = 1;

            while(changeFactor % 1 != 0)
            {
                changeFactor = changeFactor * 10;
                denomenator = denomenator * 10;
            }
            numerator = (BigInteger)changeFactor;

            byte[] oldNBitsBytes = BitConverter.GetBytes(oldNBits);
            byte[] mantissa = new byte[] {oldNBitsBytes[0], oldNBitsBytes[1], oldNBitsBytes[2], 0x00 };  // need to reverse the bytes because we want the mantissa in little endian
            byte exponent = oldNBitsBytes[3];

            BigInteger result = new BigInteger(mantissa);
            result = result << (exponent-3)*8;

            result = result * numerator / denomenator;

            byte[] resultBytes = result.ToByteArray();

            if (result == 0)
            {
                return 0;
            }

            // now to get the exponent of the newNBits, we count how many binary right shifts are needed for result to go below or equal to 0xffffff.
            byte newExponent = 3;
            while(result > 0xffffff)
            {
                result = result >> 8;
                newExponent++;
            }

            BigInteger newMantissa = result;

            List<byte> compressedResult = new List<byte>();
            byte[] newMantissaBytes = newMantissa.ToByteArray();

            
            compressedResult.AddRange(new byte[] { newMantissaBytes[0], newMantissaBytes[1], newMantissaBytes[2] });

            compressedResult.Add(newExponent);

            return BitConverter.ToUInt32(compressedResult.ToArray(), 0);
        }
Lassen Sie mich abschließend hinzufügen, dass Sie nBits nur für alle Blöcke berechnen, deren blockHeight % 2016 gleich Null ist.