Vai al contenuto
buybitcoinsmart

Glossario / Riferimento per sviluppatori

OP_EQUAL

Che cos'è OP_EQUAL?
OP_EQUAL confronta byte per byte i due elementi in cima alla pila e ne mette in cima il risultato, vero o falso, ed è l'ultimo opcode di ogni output pay-to-script-hash.

Il byte 0x87 fa l'unico confronto di cui bitcoin ha davvero bisogno: questi due blocchi di byte sono identici? Il confronto avviene sui byte grezzi e non sui numeri, ed è per questo che il linguaggio prevede un opcode separato per l'uguaglianza aritmetica. Ogni pagamento che hai mai inviato a un indirizzo che inizia con 3 termina il suo script con questa sola istruzione.

Come funziona

Due elementi escono dalla pila e uno vi rientra: un singolo byte 0x01 quando coincidono, oppure un elemento vuoto quando non coincidono. Bitcoin tratta un elemento vuoto come falso, quindi il risultato può essere verificato da qualunque cosa segua.

Il confronto tra byte è più rigoroso di quanto sembri. Due valori che una persona chiamerebbe lo stesso numero possono essere stringhe di byte diverse, e questo opcode li considera diversi. È il comportamento corretto per il suo compito reale, cioè confrontare hash e preimmagini dove qualsiasi differenza, anche minima, deve far fallire, ed è per questo che i risultati aritmetici si confrontano invece con OP_NUMEQUAL.

La proprietà interessante è ciò che non fa: lascia un risultato invece di agire su di esso. Uno script termina con successo solo quando l'elemento rimasto in cima è vero, quindi uno script che finisce con questo opcode pone una domanda e lascia che il risultato valga come risposta. La regola cleanstack di Bitcoin Core aggiunge che non può restare nient'altro, il che, per una spesa tramite script hash, significa esattamente un valore vero e nulla di più.

Quest'ultimo dettaglio ha più conseguenze di quanto sembri. Pay-to-script-hash non è una regola generale sugli script ridotti a hash; è una regola su un esatto schema di 23 byte: un opcode di hash, un push di 20 byte e questo opcode alla fine. Se scrivi la stessa logica con la forma combinata di verifica, la gestione speciale non si applica, il redeem script non viene mai estratto né eseguito, e l'output si comporta come un normale enigma di hash che chiunque indovini la preimmagine può spendere.

Dove lo vedi

Ogni output non speso su un indirizzo che inizia con 3 mostra su un block explorer lo stesso assemblaggio di tre token, che termina qui. Lo stesso vale per ogni prelievo SegWit wrapped che un exchange ti abbia mai inviato.

Compare anche nei contratti con blocco tramite hash. Gli script di pagamento di Lightning calcolano l'hash di un segreto e confrontano il risultato con un valore fisso, ed è ciò che consente a un pagamento di regolarsi attraverso più salti nel momento in cui il destinatario rivela una preimmagine di 32 byte. Gli atomic swap tra catene usano la stessa struttura.

OP_EQUAL vs OP_EQUALVERIFY

OP_EQUALVERIFY è OP_EQUAL con la verifica incorporata. Il byte 0x88 esegue lo stesso confronto e poi interrompe subito lo script se la risposta è falsa, senza lasciare nulla sulla pila quando riesce. Scegliere tra i due dipende da ciò che viene dopo. Usa la forma semplice quando il confronto è la risposta finale dello script, come fa pay-to-script-hash. Usa la forma di verifica quando il confronto è una condizione tra diverse e l'esecuzione deve proseguire, come fa il template legacy a chiave singola prima di verificare una firma. La forma di verifica fa anche risparmiare un byte rispetto a scrivere il confronto e una distinta istruzione di verifica, cosa che contava molto di più quando ogni byte di uno script stava nella parte della transazione senza witness, a quattro unità di peso ciascuno.

Da non confondere con

Domande frequenti

Qual è la differenza tra OP_EQUAL e OP_EQUALVERIFY?

La forma semplice lascia sulla pila vero o falso perché qualcos'altro lo legga, mentre la forma di verifica interrompe subito lo script se i due elementi differiscono. Pay-to-script-hash usa la forma semplice perché il confronto è la risposta finale dello script.

Confronta numeri o byte?

Byte, senza alcuna interpretazione. Due codifiche che rappresentano lo stesso numero qui risultano diverse, che è esattamente ciò che vuoi quando confronti hash, ed è il motivo per cui i confronti aritmetici usano un opcode separato.

Termini correlati

Altro in Riferimento per sviluppatori

Leggi questa pagina in inglese