Damit ein Einlösungsskript die Bedingungen eines Skripts erfüllt, was muss es nach der Ausführung auf dem Stapel belassen?
Ich habe diese Präsentation von Andreas Antonopoulos über Advanced Bitcoin Scripting gesehen.
Aus Andreas 'Beispielen geht hervor, dass ein Einlösungsskript, um die Bedingungen des Skripts zu erfüllen, nach seiner Ausführung TRUE (und nichts anderes) auf dem Stapel belassen muss. Das war erkundigte sich auch über hier .
Daher gibt es ein VERIFY-Suffix, so dass einige Opcodes (z. B. EQUAL, CHECKSIG, CHECKMULTISIG) konkurrierende Opcodes haben (z. B. EQUALVERIFY, CHECKSIGVERIFY, CHECKMULTISIGVERIFY). Anstatt TRUE auf dem Stapel zu belassen, setzen diese VERIFY-Opcodes "die Ausführung des Skripts fort, wenn das Ergebnis des bedingten Operators TRUE ist", aber "schieben diese TRUE nicht zurück in den Stapel, sondern setzen einfach die Ausführung fort". Diese VERIFY-Opcodes können verwendet werden, um sicherzustellen, dass bei der Ausführung des Einlöseskripts TRUE (und nichts anderes) auf dem Stapel verbleibt, anstatt TRUE TRUE TRUE zu sagen.
In dieser Sitzung des Bitcoin Core PR Review Clubs erklärte Pieter Wuille jedoch (paraphrasierend):
Für CLEANSTACK muss ein Stapel mit einem einzelnen Element vorhanden sein, das ungleich Null sein muss. Ohne CLEANSTACK ist ein nicht leerer Stapel mit mehreren Elementen in Ordnung, solange das oberste Element ungleich Null ist
Ich habe zwei Fragen:
Vermutlich ist TRUE gleich 1 und FALSE gleich 0?
Alle Opcodes, die als FALSE ausgewertet werden, führen zum sofortigen Ausfall und zur Beendigung der Ausführung? Mit non-CLEANSTACK würden Sie also niemals einen resultierenden Stapel von TRUE FALSE TRUE-Pass sehen, da FALSE zu einem sofortigen Fehler führen würde und Sie den endgültigen TRUE nicht bewerten würden. Sie könnten jedoch einen Stapel von beispielsweise TRUE 3 TRUE 5 sehen, und dies würde mit Nicht-CLEANSTACK passieren. (Mit CLEANSTACK würde dies fehlschlagen, da CLEANSTACK ein einzelnes Element im resultierenden Stapel haben muss.)
Antworten
Vielen Dank an harding für die Beantwortung dieser Frage im IRC und sanket1729 für Änderungen.
Vermutlich ist TRUE gleich 1 und FALSE gleich 0?
TRUE ist ein Wert ungleich Null. Dies wird häufig in Skripten verwendet, die frühere OP_NOPx-Opcodes enthalten, deren Werte nach der Überprüfung nicht vom Stapel genommen werden, z. B. ein Skript, das von einem Miner nach einer bestimmten Höhe ausgegeben werden kann : <locktime> OP_CLTV
; Wenn CLTV fehlschlägt, ist die Transaktion ungültig. Wenn es erfolgreich ist, kann das Skript den auf dem Stapel verbleibenden Wert ungleich Null passieren.
Alle Opcodes, die als FALSE ausgewertet werden, führen zum sofortigen Ausfall und zur Beendigung der Ausführung? Mit non-CLEANSTACK würden Sie also niemals einen resultierenden Stapel von TRUE FALSE TRUE-Pass sehen, da FALSE zu einem sofortigen Fehler führen würde und Sie den endgültigen TRUE nicht bewerten würden. Sie könnten jedoch einen Stapel von beispielsweise TRUE 3 TRUE 5 sehen, und dies würde mit Nicht-CLEANSTACK passieren. (Mit CLEANSTACK würde dies fehlschlagen, da CLEANSTACK ein einzelnes Element im resultierenden Stapel haben muss.)
Ohne CLEANSTACK ist nur der höchste Wert auf dem Stapel am Ende der Ausführung von Bedeutung. Alles weiter unten im Stapel spielt keine Rolle.
CLEANSTACK ist eine Standarditätsregel für P2SH, aber eine Konsensregel für Segwit v0 ( BIP141-Spezifikation ) und Tapscript, SegWit v1 ( BIP342-Spezifikation , Regel 4, ii).
Das Wort "Misserfolg" ist hier nicht eindeutig. Es gibt verschiedene Möglichkeiten, wie verschiedene Opcodes fehlschlagen können. Wenn beispielsweise OP_CHECKSIG fehlschlägt, wird nur eine 0 in den Stapel verschoben. Wenn jedoch OP_CHECKSIGVERIFY fehlschlägt, schlägt das gesamte Skript fehl. Sie können TRUE FALSE FALSE mit nur OP_0 OP_0 OP_1 auf den Stapel legen.
Einige der VERIFY-Opcodes, z. B. EQUALVERIFY, CHECKSIGVERIFY, CHECKMULTISIGVERIFY, werden sofort nach einem Fehler beendet, ihre Nicht-VERIFY-Entsprechungen jedoch nicht.
Alles, was zählt, ist der Status des Stapels am Ende der Skriptauswertung. Sie können beispielsweise OP_CHECKSIG gefolgt von OP_IF OP_PUSHNUM1 OP_ELSE OP_PUSHNUM2 OP_ENDIF ausführen. Wenn die Signatur erfolgreich ist, nehmen Sie einen Zweig. Wenn dies fehlschlägt, nehmen Sie einen anderen Zweig (Dies wird jedoch nicht als bewährte Methode angesehen und sollte im Allgemeinen nicht durchgeführt werden.)
CLEANSTACK ist ein Versuch, Formbarkeit zu verhindern, indem Leute eine Menge Müll in Ihre scriptSig- oder Zeugen-Daten einfügen. Weil Sie einfach eine Reihe von Daten auf den Stapel schieben können, die nie verwendet werden und die die korrekte Auswertung des Skripts nicht verhindern. (Pre-Segwit, dies wirkte sich auf die Formbarkeit aus und wurde als Standardrichtlinie durchgesetzt. Mit Segwit ist dies nicht mehr möglich, da es sich um eine Konsensregel handelt.)