Wo und wann sollte die Coinbase-Transaktion (einschließlich Miner Key) hinzugefügt werden?

Ich mache ein einfaches Demonstrator-Programm, so ziemlich ein vereinfachter Bitcoin-Klon, der hauptsächlich auf dem ursprünglichen Whitepaper basiert.

Bitte haben Sie Geduld mit mir, denn ich habe keine Möglichkeit gefunden, das Problem präziser zu beschreiben.

Meine Blockchain basiert auf diesem Tutorial.

Der Transaktionsteil wird jedoch vollständig ignoriert, daher habe ich die Transaktionen auf diesen Teil der Originaldokumentation gestützt: Ein Abschnitt des ursprünglichen Bitcoin-WhitepapersWie hier angegeben, bestehen meine Transaktionen aus dem öffentlichen Schlüssel des nächsten Besitzers und der Signatur der letzten Transaktion, die vom vorherigen Besitzer signiert wurde. Ich habe auch den zu überweisenden Betrag hinzugefügt (ich verwende das In/Out-System der Einfachheit halber nicht).

Da jede Transaktion einen Hash einer vorherigen benötigt, habe ich auch eine Coinbase-Transaktion erstellt. Es enthält nur die geschürfte Menge und den öffentlichen Schlüssel des Miners (um zu wissen, wem die geschürfte Menge zu geben ist). Dadurch kann die erste reguläre Transaktion in einem Block eine vorherige Transaktion zum Hashen und Signieren haben.

Das bedeutet jedoch auch, dass der Miner Key vor der ersten Transaktion angegeben werden muss (da alle zukünftigen Transaktionen erfordern, dass der Hash der Coinbase gleich bleibt). Gleichzeitig ist es nicht sinnvoll, den Miner festzulegen, bevor er einen Block geschürft hat. Mit anderen Worten, dies würde erfordern, dass der Transaktionsbenutzer a priori weiß, wer den Block mit seiner Transaktion abbauen wird.

Meine bisherige Annahme war, dass eine Coinbase-Transaktion zur Liste der unbestätigten Transaktionen hinzugefügt wird, nachdem der vorherige Block geschürft wurde, und neue Transaktionen darauf verweisen. Dann wird die gesamte Liste in einen Block gesteckt, der dann abgebaut wird. Diese Annahme führte jedoch zu den oben erwähnten Problemen.

Die einzig mögliche Lösung, die mir einfallen könnte, besteht darin, den letzten Transaktions-Hash aus dem vorherigen Block zu verwenden, um eine neue Transaktion zu signieren, wodurch die Coinbase-Transaktion effektiv umgangen wird. Aber das erscheint mir nicht richtig.

Bitte sagen Sie mir, wenn ich etwas übersehe oder irgendwo auf eine falsche Idee gekommen bin.

Wo und wann sollte die Coinbase-Transaktion (einschließlich Miner Key) hinzugefügt werden?

Oder sollte ich diese Idee komplett verwerfen und die „Bypass“-Methode anwenden?

PS. Ich habe bereits versucht, verschiedene Wikis und Fragen zu durchsuchen, aber nichts hat mir wirklich eine klare Lösung dafür gegeben. Vor allem diese Antwort ist zu vage

Antworten (2)

Sie haben die falsche Vorstellung: Jede Transaktion muss nicht auf die Transaktion verweisen, die in einem bestimmten Block vor ihr steht, sondern auf die Transaktion, die die Ausgaben erstellt hat, die sie jetzt ausgibt. Diese „Transaktionskette“ bezieht sich auf das Verfolgen der Geschichte bestimmter Ausgaben im Laufe der Zeit, nicht nur auf die willkürliche Reihenfolge der Transaktionen innerhalb eines Blocks.

Die zweite Transaktion in einem Block (erste Nicht-Coinbase-Transaktion) verweist also auf die Transaktion(en), die die ausgegebenen Ausgaben erzeugt haben. Es wird nicht auf die Coinbase-Transaktion verwiesen.

Danke! Ich habe es mit der vorherigen Antwort herausgefunden und in Block-Explorern gegraben, aber jetzt habe ich die Bestätigung, dass meine Schlussfolgerungen richtig waren.

Die Coinbase-Transaktion wird erstellt, wenn der Miner die Vorlage für den Block erstellt, den er zu minen versucht. Im Gegensatz zu regulären Transaktionen hat es keine regulären Eingaben. Der Miner gibt einfach die Ausgaben an, um die Coins auszugeben, wobei die Summe der Ausgabebeträge kleiner oder gleich der Gesamtsumme der Gebühren im Block plus der Subvention sein muss. Die Coinbase wird immer als erste Transaktion im Block positioniert.

Die Coinbase-Transaktion hat die gleiche Struktur wie normale Transaktionen, aber für jede, txIndie sie hat, txOutPointsollte jede nur einen Nullwert haben (es gibt kein vorheriges, txidauf das verwiesen werden kann). Die scriptSigkann beliebige Informationen enthalten, da Miner nichts unterschreiben müssen. Miner fügen Informationen scriptSigwie ihren Namen oder eine zusätzliche Entropiequelle für das Mining hinzu. Darüber hinaus erfordern einige Konsensregeln, die in Bitcoin gegabelt wurden, dass die scriptSigBlockhöhe und eine Merkle-Wurzel von wtxids(für Segwit) enthalten sind.

Der Ablauf ist ungefähr so:

  • Der Miner erstellt eine Coinbase-Vorlage, die einen noch unbekannten Geldbetrag für einen oder mehrere Ausgänge ausgibt.

  • Miner sortiert Transaktionen im Mempool nach der höchsten gezahlten Gebühr pro Gewichtseinheit (pro Byte im Original) und wählt eine bestimmte Anzahl von Transaktionen aus, sodass ihre serialisierte Größe plus die serialisierte Größe der Coinbase nicht größer als die Blockgrößenbegrenzung ist.

  • Sie summieren alle Gebühren, die in den enthaltenen Transaktionen gezahlt wurden, und addieren sie zu der Subvention, um einen Betrag zu erstellen, den der Block wert ist.

  • Sie aktualisieren die Coinbase-Vorlage, wobei höchstens dieser Betrag ausgegeben wird (es ist möglich, nicht den vollen Betrag der Gebühren oder des Zuschusses zu beanspruchen, aber eine Überforderung führt zu einem ungültigen Block).

  • Der Miner berechnet die Merkle-Wurzel all dieser Transaktionen txids(wobei das txidder doppelte SHA der serialisierten Transaktion ist), die als binärer Baum genommen wird, der nach der Position geordnet ist, an der die Transaktion im Block serialisiert wird. Die Coinbase ist explizit die erste Transaktion.

  • Der Miner fügt diesen Merkle-Stamm in einen Block-Header mit den 5 anderen erforderlichen Feldern (Version, prevBlockHash, Ziel, Nonce und Zeitstempel) ein und serialisiert ihn.

  • Der Miner versucht wiederholt Double-SHA256 für den Block-Header, bis der resultierende Digest, wenn er als Ganzzahl genommen wird, numerisch kleiner oder gleich dem ist, was im targetHeader erforderlich ist. Der Miner modifiziert nonce, oder gelegentlich timestampfür jeden Doppel-SHA256-Versuch, sodass ein anderer Digest erzeugt wird, aber die anderen Felder des Headers unverändert bleiben.

  • Wenn der Miner in regelmäßigen Abständen noch keinen erfolgreichen Hash gefunden hat oder wenn ein neuer Block empfangen wird, berechnet er eine neue Vorlage, indem er diesen Prozess von vorne beginnt, der neue Informationen aufnehmen und eine höhere Belohnung bieten kann. Sie verwerfen die vorherige Vorlage, an der sie gearbeitet haben. Wenn ein neuer Block gefunden wurde, werden alle Transaktionen, die in dem Block enthalten waren, aus dem Mempool gelöscht.

Vielen Dank, das war informativ und hat mir geholfen, die genaue Lösung selbst zu finden.