Glossario / Riferimento per sviluppatori
OP_VERIFY
- Che cos'è OP_VERIFY?
- OP_VERIFY rimuove l'elemento in cima alla pila e interrompe l'intero script a meno che quell'elemento sia vero, trasformando qualsiasi verifica in Bitcoin Script in un requisito inderogabile.
Il byte 0x69 è l'asserzione di uso generale del linguaggio. Script può ramificarsi con OP_IF, ma non ha modo di generare un errore e nessun valore di ritorno oltre a ciò che sopravvive sulla pila, così un contratto impone una condizione calcolando la risposta e affidandola a questa istruzione. Quasi ogni pagamento mai effettuato è passato attraverso una di queste asserzioni, di solito nascosta dentro un opcode fuso.
Come funziona
OP_VERIFY rimuove un elemento dalla pila e pone una sola domanda: è vero?
Qui la verità è una nozione a livello di byte, non numerica. Un elemento vuoto è falso. Lo è anche una sequenza di byte zero, e lo è anche lo zero negativo, una sequenza di zeri che termina in 0x80. Tutto il resto conta come vero, compreso un hash di 20 byte o una chiave pubblica di 33 byte. Se l'elemento è falso, lo script termina sul posto e l'input che lo contiene è invalido, il che invalida la transazione che lo circonda. Se l'elemento è vero, nulla torna sulla pila e la valutazione passa all'opcode successivo.
È questo comportamento che consente a uno script di verificare più cose in sequenza. Uno script ha successo solo quando alla fine resta esattamente un valore vero, quindi senza asserzioni ogni condizione dovrebbe essere condensata in un unico booleano finale. Con le asserzioni, un contratto può richiedere un timelock, poi richiedere una preimmagine hash, poi richiedere una firma, fallendo alla prima condizione non soddisfatta.
Quattro opcode hanno l'asserzione incorporata ed esistono solo per risparmiare un byte: OP_EQUALVERIFY, OP_CHECKSIGVERIFY, OP_CHECKMULTISIGVERIFY e OP_NUMEQUALVERIFY. Poiché coprono i casi comuni, un 0x69 isolato è raro sulla mainnet.
Due opcode portano VERIFY nel nome e non si comportano affatto così. OP_CHECKLOCKTIMEVERIFY dal BIP65 e OP_CHECKSEQUENCEVERIFY dal BIP112 sono stati aggiunti tramite soft fork su codici no-op prima privi di significato, così, per non creare problemi ai nodi più vecchi, dovevano lasciare la pila esattamente come l'avevano trovata. Entrambi ispezionano l'elemento in cima e falliscono quando la condizione non è soddisfatta, ma nessuno dei due lo consuma, ed è per questo che negli script reali sono sempre seguiti da OP_DROP.
Dove lo vedi
Le asserzioni si concentrano ovunque uno script abbia più di una cosa da dimostrare.
Un semplice vault con blocco temporale si legge come una chiave pubblica, OP_CHECKSIGVERIFY, un ritardo come 144 blocchi (all'incirca un giorno), poi OP_CHECKSEQUENCEVERIFY. Gli script di commitment e HTLC di Lightning sono costruiti allo stesso modo, concatenando una verifica di preimmagine e una verifica di firma in modo che nessuna delle due da sola basti a muovere denaro. Le spese tramite script di Taproot si affidano molto a questo schema, dato che tapscript ha sostituito OP_CHECKMULTISIG con OP_CHECKSIGADD e usa le forme verify per mantenere compatte le politiche a più chiavi.
Miniscript, il compilatore di politiche che diversi wallet desktop usano ormai per descrivere le condizioni di spesa in forma leggibile, emette questi opcode al posto tuo. È il modo più semplice per osservare la generazione delle asserzioni senza scrivere a mano uno script grezzo.
OP_VERIFY vs OP_RETURN
OP_VERIFY e OP_RETURN terminano entrambi male uno script, ma solo uno dei due pone prima una domanda. OP_VERIFY fallisce quando il valore che riceve è falso, quindi una spesa corretta lo supera senza lasciare traccia. OP_RETURN, byte 0x6a, fallisce ogni volta che viene eseguito, senza alcuna condizione associata, ed è proprio per questo che si usa per costruire output che non potranno mai essere spesi e per collegare dati a una transazione. Uno script che muore sul primo ha ricevuto qualcosa di sbagliato. Uno script che muore sul secondo non era mai stato pensato per essere spendibile fin dall'inizio.