Warum Hash-Witness-Skript anstelle von Pubkey-Skript in der Signatur?

Wenn eine Segwit-Eingabe signiert wird, verpflichtet sich die Signatur zum Witness-Skript (oder einem p2pkh-ähnlichen Skript im Fall von p2wpkh). Dies ist in BIP143 angegeben :

  • Für P2WPKHdas Zeugenprogramm scriptCodeist das 0x1976a914{20-byte-pubkey-hash}88ac.
  • Für P2WSHdas Zeugenprogramm,
    • wenn die witnessScriptkeine enthält OP_CODESEPARATOR, scriptCodeist die witnessScriptdarin als Skript serialisiert CTxOut.
    • wenn der witnessScriptirgendwelche enthält OP_CODESEPARATOR, scriptCodewird der witnessScriptaber alles bis einschließlich des letzten OP_CODESEPARATORvor der Ausführung der Signaturprüfung ausgeführten Opcodes entfernt und als Skripte innerhalb von serialisiert CTxOut. (Die genaue Semantik wird in den Beispielen unten demonstriert)

Was ist der Grund dafür? Warum verpflichtet sich der Hash nicht zum Pubkey-Skript wie bei Legacy-Zahlungen (p2pkh und p2sh)? Dieser Unterschied erschwert das Signieren/Bestätigen des Codes ein wenig, daher muss es wohl einen guten Grund dafür geben.

Vielleicht sollte meine Frage lauten: Warum verpflichtet sich der Hash überhaupt zu irgendeinem Skript für Segwit-Eingaben? Bei älteren Signaturen ist das Einfügen von scriptPubkey in scriptSig für die aktuelle Eingabe eine (komplizierte, siehe unten) Möglichkeit, die Wiederverwendung von Signaturen zwischen Eingaben zu vermeiden. outpointAber in Segwit wird dies mit einem Teil des Hashing-Algorithmus erreicht . Könnten wir den scriptCodeTeil nicht einfach überspringen?

Es scheint mir, dass es einen anderen Grund gibt, warum wir das scriptPubkey für Legacy-Signaturen und das Witness-Skript für Segwit-Signaturen hashen, da es einfachere Möglichkeiten gibt, die Wiederverwendung von Signaturen zu vermeiden:

  • Legacy: Wir hätten einfach irgendwo in der aktuellen Eingabe ein Dummy-Byte hinzufügen können
  • Segwit: Der Outpoint der aktuellen Eingabe löst das Problem bereits.

Antworten (1)

Ich vermute nur, aber indem wir die Transaktion an den scriptCode übergeben, stellen wir sicher, dass der Unterzeichner weiß, für welches Skript er signiert. Eine Hardware-Wallet kann zum Beispiel nur dann sicher sein, dass Outpoint 1234...cdef:0 ein bestimmtes Skript bezahlt, wenn wir ihr die Transaktion geben, die diesen Outpoint erstellt hat (damit sie diese Transaktion hashen kann, die txid überprüfen, den scriptPubKey extrahieren kann , und vergleichen Sie dies mit einem bereitgestellten WitnessScript). Da eine Transaktion (ohne Zeugendaten) bis zu fast einem Megabyte groß sein kann und eine Ausgabentransaktion auf Tausende früherer Transaktionen verweisen kann, schaffen wir eine Situation, in der ressourcenarme Geräte wie Hardware-Wallets es schwer haben, zu überprüfen, was sie sind. neu unterschreiben.

Im Gegensatz dazu müssen wir bei BIP143 dem Wallet nur jeden der scriptCodes mitteilen, für den es signieren soll. BIP141 erlaubt diese bis zu 10.000 Byte, was nur 1/100 der maximalen Größe einer Transaktion ist. Das Wallet kann diese scriptCodes untersuchen, sicherstellen, dass sie mit den Erwartungen des Wallets übereinstimmen, und sich in seiner Signatur darauf verpflichten, zu wissen, dass die Signatur ungültig ist, wenn die Person, die ihnen den scriptCode sendet, über den tatsächlichen scriptCode gelogen hat.

Aus dem gleichen Grund legt das BIP143-Signaturformat den Wert jeder Eingabe fest. Zuvor musste es frühere Transaktionen verarbeiten, um ihre Ausgabebeträge zu erhalten; Jetzt akzeptiert es einfach alle Daten, die es erhält, und signiert es in dem Wissen, dass die Signatur ungültig ist, wenn jemand es bezüglich des Betrags belügt.

"... zu wissen, dass die Signatur ungültig ist, wenn die Person, die ihnen den scriptCode sendet, über den tatsächlichen scriptCode gelogen hat." Ich bin hier in tiefem Wasser, aber ich denke, die Signatur wäre ungültig, selbst wenn sie sich nicht direkt auf den scriptCode festlegen würde, da die Signatur bereits indirekt über den Pfad outpoint->WSH->scriptCode auf den scriptCode festlegt. Das beantwortet die Frage also nicht wirklich, fürchte ich.
Sie haben Recht, dass die Übergabe an den Outpoint an das vorherige scriptPubKey und das vorherige scriptPubKey an das Skript übergeben wird, aber der Punkt der Antwort ist, dass der Beweis für Wallet, dass ein bestimmter Outpoint einem bestimmten WitnessScript entspricht, bis zu ~ 1 MB erfordert Daten plus das WitnessScript. Durch die direkte Übergabe an den scriptCode sind jetzt die einzigen Daten, die für den Beweis erforderlich sind, der scriptCode (der im normalen Gebrauch mit dem WitnessScript identisch ist).
Stellen Sie sich eine Transaktion mit einer einzelnen p2wsh-Eingabe vor. Die Hardware Wallet erhält eine unsignierte Transaktion (Tx), die vermeintliche Eingabe UTXO (U) und das vermeintliche Zeugenskript (WS). Es erhält wahrscheinlich auch einen Schlüsselableitungspfad, aber das ist für diese Diskussion irrelevant. Diese Information, [Tx, U, WS], beweist selbst nicht, dass der Outpoint an WS übergeben wird . Wenn die Eingabe basierend auf [Tx, U, WS] signiert ist und U und WS falsch sind, ist die Signatur außerdem ungültig, unabhängig davon, ob die Signatur scriptCode festschreibt oder nicht. Bin ich hier falsch? Vielen Dank für Ihre Geduld.
Ja, ich bin hier falsch. Durch ein privates Gespräch mit @David wurde mir klar, dass die Signatur nicht ungültig wäre, wenn BIP143 scriptCode weglassen würde. Vergesslichkeit. Also ja, wir müssen uns auf scriptCode festlegen.