Warum zählt der Zeugengebrauch statt der Länge?

In Legacy-Transaktionen (ohne SegWit) wird die scriptSig einfach analysiert, indem ihre Länge (ein CompactIntWert) bekannt ist und das Skript an Ort und Stelle nicht gelesen werden muss.
In der SegWit-Transaktion wird die scriptSig, die zur Zeugenposition verschoben wird, jetzt jedoch durch eine "Zählung" der Elemente innerhalb des Skripts identifiziert, und das bedeutet, dass das Skript an Ort und Stelle gelesen (interpretiert) werden muss.
War die Größe (Einsparung von 2 Bytes in Multi-Sig-Skripten) der einzige Grund für diesen Unterschied?
Gibt es aufgrund dieses Unterschieds auch Einschränkungen für OP-Codes, die in Skripten innerhalb von Zeugen verwendet werden könnten?

Antworten (1)

Beachten Sie, dass Zeugen keine Skripte sind. Sie enthalten keine Opcodes. Sie sind Stapelelemente. Zeugen haben keine expliziten Opcodes (WitnessScripts sind Skripte, aber einzelne Witness-Stack-Elemente, sodass ihre Opcodes nicht zählen).

Die Zählung wird verwendet, da sie klar zwischen dem Ende der Stack-Elemente für eine Eingabe und dem Anfang der Stack-Elemente für die nächste Eingabe abgrenzt. Die Verwendung einer Zählung folgt der Standard-Serialisierungsmethode, die an anderer Stelle in Bitcoin zum Serialisieren von Arrays von Elementen verwendet wird. In diesem Fall sind die Zeugendaten für eine Eingabe ein Array von Arrays von Bytes (im Code ist das std::vector<std::vector<unsigned char>>).

Wenn wir also der Standard-Serialisierungsmethode von std::vectors folgen, erhalten wir auf der obersten Ebene die Anzahl der Elemente in der nächstniedrigeren Ebene (dh die Anzahl der std::vector<unsigned char>Elemente), was zufällig die Anzahl der Stack-Elemente ist. Dann erhalten wir auf der nächsten Serialisierungsebene eine andere Länge für die Anzahl der Elemente in der Ebene darunter (dh die Anzahl unsigned charin jedem Vektor). Jetzt haben wir also die Länge jedes Stack-Elements. Dann kommt das Stapelelement selbst.

Der Grund, warum diese Methode für Segwit verwendet wurde, liegt wahrscheinlich darin, dass Stacks in Bitcoin Core als std::vector<std::vector<unsigned char>>. Darüber hinaus wird die Serialisierung von Vektoren auf diese Weise überall in Bitcoin verwendet, sodass der Serialisierungscode dafür im Grunde bereits in jeder existierenden Wallet-Software vorhanden war.