Autore: Benna | Shift Crypto | Pubblicazione originale: 1 mar 2023 | Tradotto da: 31febbraio | Milano Trustless | Link: Understanding Bitcoin Miniscript - Part II
Nella prima parte di questa serie di articoli, abbiamo visto esempi di come bloccare fondi utilizzando condizioni complesse come (persona1 può spendere in qualsiasi momento) OPPURE (persona2 può spendere dopo un anno)
utilizzando Bitcoin Script, il linguaggio di scripting nativo di Bitcoin. Questi esempi hanno dimostrato quanto sia difficile per gli sviluppatori creare tali condizioni e utilizzarle nella pratica a causa delle carenze e delle insidie connaturate a Bitcoin Script. È difficile sviluppare lo script che codifica le condizioni di spesa desiderate e creare witness validi che possano spendere i fondi.
Miniscript risolve questi problemi introducendo frammenti che incapsulano pezzi di Bitcoin Script, rendendo più facile costruire script più complessi componendo i frammenti.
Questo articolo approfondisce il funzionamento di Miniscript e la sua corrispondenza con Bitcoin Script.
Vi invitiamo a leggere la prima parte prima di immergervi [in questa lettura], poiché ci baseremo sui concetti di Bitcoin Script introdotti in quel testo, ad esempio su come vengono eseguiti gli Script per determinare se una moneta può essere spesa.
Cos'è Miniscript?
Miniscript è composto da due parti indipendenti:
Policy language
Policy language è un linguaggio di espressione di alto livello che è componibile e facile da leggere e scrivere per gli esseri umani. Policy language può essere compilato in un Miniscript corretto automaticamente, da un compilatore di policy. Un esempio di policy è or(pk(key_1),pk(key_2))
, che significa 'o key_1 o key_2 possono spendere'.
Miniscript
Un'espressione Miniscript può assomigliare, ad esempio, a or_b(pk(key_1),s:pk(key_2))
, che è stata compilata dalla policy di cui sopra utilizzando il compilatore di sipa. Si tratta di una composizione di frammenti come or_b
, pk
, ecc.
Ogni frammento corrisponde a un particolare pezzo di Bitcoin Script. Ad esempio, pk(key)
corrisponde a <key> OP_CHECKSIG
e or_b(X,Y)
corrisponde a [X] [Y] BOOLOR
.
Miniscript stesso è un linguaggio di espressione di facile lettura sia per i computer che per gli esseri umani.
Per i computer, questo è importante affinché l'applicazione del wallet possa decodificare un'espressione Miniscript e trasformarla in indirizzi di ricezione, consentendo di spendere gli UTXO.
Per gli esseri umani è importante per poter fare una copia di backup del descriptor del portafoglio scrivendolo su carta e utilizzare lo stesso per interagire con applicazioni e strumenti diversi. Ad esempio: si potrebbe voler importare il descriptor del proprio portafoglio in uno strumento di monitoraggio o di rendicontazione fiscale, oppure importarlo in un portafoglio mobile di visualizzazione. Un descriptor del wallet può includere un miniscript e può essere utilizzato per ricavare indirizzi.
Il linguaggio di espressione dei miniscript è molto simile a quello delle policy, quindi è facile confonderli. È importante capire che si tratta di due linguaggi completamente indipendenti:
- Policy language è uno strumento che aiuta gli sviluppatori a creare facilmente condizioni di spesa, in quanto è molto semplice da scrivere. Ha solo una manciata di funzioni primitive, come
and(X,Y)
,or(X,Y)
,older(time)
e così via, che si combinano perfettamente tra loro. Policy language è semplicemente uno strumento per gli sviluppatori e non è uno standard. Non è garantito che un'espressione di policy produca sempre la stessa espressione di Miniscript. - Miniscript invece è ben specificato. Solo Miniscript viene utilizzato per generare Bitcoin Script, witness validi ed eseguire analisi sulla validità. Un'espressione Miniscript corrisponderà sempre allo stesso Bitcoin Script.
Allora perché gli sviluppatori non possono scrivere direttamente le espressioni Miniscript? Perché ci affidiamo a un compilatore di policy? Il motivo è che le espressioni Miniscript non sono banali da scrivere a mano, poiché ereditano alcune delle complessità di Bitcoin Script per natura, incapsulandole:
- Ci sono molti più frammenti in Miniscript che nelle polici language. Per esempio, ci sono almeno quattro modi diversi di esprimere
X or Y
in Miniscript:or_b(X,Y)
,or_c(X,Y)
,or_d(X,Y)
eor_i(X,Y)
, ognuno dei quali corrisponde a modi diversi di esprimere X o Y in Bitcoin Script, ciascuno con caratteristiche diverse in termini di grandezza dello script, dimensione del witness e modalità di composizione con altri frammenti. - Ci possono essere molti miniscript diversi che codificano le stesse condizioni. Il compilatore di policy può aiutare a ottimizzare, ad esempio, la dimensione dello script per ridurre le spese di transazione.
- Non tutte le espressioni Miniscript producono script validi: i frammenti devono essere composti in modo da rispettare le proprietà di validazione. Il compilatore di policy si assicura di produrre solo miniscript validi.
Al lavoro: corrispondenze con Bitcoin Script
Per capire come un'espressione Miniscript codifichi un Bitcoin Script, vediamolo in azione, per eseguire la seguente espressione:
or_b(pk(key_1),s:pk(key_2))
Ogni frammento corrisponde a un particolare elemento di Bitcoin Script. pk(key)
corrisponde a <key> OP_CHECKSIG
e or_b(X,Y)
corrisponde a [X] [Y] BOOLOR
.
Ogni frammento può anche essere avvolto da pacchetti (wrapper), indicati con lettere prima dei due punti ':'. Il wrapper s:X
corrisponde a OP_SWAP [X]
. I wrapper sono fondamentalmente uguali a tutti gli altri frammenti, ma più concisi. In un certo senso, sono solo zucchero sintattico. Si può pensare, ad esempio, che s:X
sia uguale a s(X)
, o che dv:older(144)
sia uguale a d(v(older(144))
.
Quindi l'intera espressione Miniscript di cui sopra si traduce in questo script Bitcoin:
<key_1> OP_CHECKSIG OP_SWAP <key_2> OP_CHECKSIG OP_BOOLOR
\_________________/ \ \________________/ /
\ X \ X / /
\ \__________________/ /
\ Y=s:X /
\_______________________________________________/
or_b(X,Y)
In questo particolare esempio, un witness per spendere le coin sarebbe della forma <signature2> <signature1>
, dove almeno una delle firme deve essere valida. OP_SWAP
è necessario per far sì che la parte <key_2> OP_CHECKSIG
venga applicata non all'elemento superiore della stack, che contiene il risultato di <signature1> <key_1> OP_CHECKSIG
, ma all'elemento 1 sotto la cima della stack, che contiene la firma per la seconda chiave.
Ci sono in totale 22 frammenti definiti e 11 wrapper, ognuno dei quali corrisponde ad una mappatura concreta per Bitcoin Script. L'elenco di tutti i frammenti e delle loro mappature nella specifica è riportato qui.
Vediamo adesso un'espressione più complicata. Ricordiamo la condizione di spesa che abbiamo usato nella prima parte di questa serie come esempio significativo:
pubkey1 OR (pubkey2 in one year)
Lo script utilizzato per codificare questa condizione era piuttosto complicato e difficile da sviluppare a mano:
<pubkey1> OP_CHECKSIG OP_IFDUP OP_NOTIF
<pubkey2> OP_CHECKSIGVERIFY <52560 (one year)> OP_CHECKSEQUENCEVERIFY
OP_ENDIF
Con Miniscript, tuttavia, questa condizione di spesa può essere espressa con la seguente policy:
or(10@pk(pubkey1),and(pk(pubkey2),older(52560)))
che si compila come espressione Miniscript:
or_d(pk(pubkey1),and_v(v:pk(pubkey2),older(52560)))
che a sua volta si adatta al complicato script di cui sopra, mappando i frammenti alle loro controparti di Bitcoin Script in questo modo:
older(52560)
incapsula<52560> OP_CHECKSEQUENCEVERIFY
v:pk(pubkey2)
incapsula<pubkey2> OP_CHECKSIGVERIFY
and_v(X,Y)
incapsula[X] [Y]
, perciò in questo caso<pubkey2> OP_CHECKSIGVERIFY <52560> OP_CHECKSEQUENCEVERIFY
pk(pubkey1)
incapsula<pubkey1> OP_CHECKSIG
or_d(X,Y)
incapsula[X] OP_IFDUP OP_NOTIF [Y] OP_ENDIF
, ottenendo lo script finale appena riportato.
10@
dà un suggerimento al compilatore di policy che ci aspettiamo che questo percorso di spesa sia molto più probabile dell'altro. Il compilatore può utilizzare questa informazione per ottimizzare la dimensione totale dello script per questo specifico caso.
Una volta che lo script di Bitcoin Script è noto, un wallet può convertirlo in un indirizzo di ricezione bc1...
e consentire di ricevere fondi su di esso. Queste coins saranno bloccate utilizzando le condizioni di spesa espresse nella policy/miniscript originale.
Generazione dei witness
I witness corrispondenti per spendere i fondi possono anche essere generati automaticamente dall'espressione Miniscript, poiché ogni frammento definisce come costruire soddisfazioni e insoddisfazioni valide per la spesa. Un'applicazione wallet alimentata da Miniscript utilizzerebbe questo metodo per consentire di effettuare transazioni.
L'elenco di tutte le soddisfazioni e insoddisfazioni per ogni frammento si trova sotto 'Basic satisfactions' disponibili qui.
Ad esempio, il frammento pk(key)
, che corrisponde a <key> OP_CHECKSIG
, può essere soddisfatto da <signature>
. L'esecuzione finale dello script sarebbe <signature> <key> OP_CHECKSIG
e lascerebbe un 1
sullo stack se la firma è valida e uno 0
altrimenti. Lo stesso frammento può essere insoddisfatto dalla firma vuota non valida <>
. Un'insoddisfazione significa che lo script non viene interrotto e continua lasciando uno 0
sullo stack.
Si rimanda alla prima parte di questa serie di articoli su come witness e i loro script vengono combinati ed eseguiti per consentire la spesa dei fondi.
Generiamo i witness per la stessa espressione dell'esempio precedente:
- il frammento
pk(key)
può essere soddisfatto da<signature>
e non soddisfatto dalla firma vuota<>
. - il frammento
or_b(X,Y)
- (che corrisponde a[X] [Y] OP_BOOLOR
) può essere soddisfatto da tre diverse condizioni: (i)o X e Y sono soddisfatti; (ii)o uno dei due:[satisfaction for Y][satisfaction for X]
, oppure[dissatisfaction for Y][satisfaction for X]
, oppure[satisfaction for Y][dissatisfaction for X
. - Combinando i due:
or_b(pk(key_1),s:pk(key_2))
si ottengono questi tre witness validi:
<signature2> <signature1>
<> <signature1>
<signature2> <>
.
Conclusione
In questo articolo abbiamo visto come Miniscript semplifichi lo sviluppo di spese complesse e come permetta alle applicazioni dei wallet di ricevere e spendere fondi bloccati con tali condizioni.
Nella prossima puntata, scriveremo un parser Miniscript completo e un correttore nel linguaggio di programmazione Go. Sarà in grado di generare indirizzi di ricezione Bitcoin da espressioni Miniscript arbitrarie. Restate sintonizzati!
Milano Trustless (31febbraioMI)
#MilanoTrustless è un progetto personale per #orangepillare 🟠💊 Milano e infondere ai (meravigliosi) milanesi la mentalità #trustless
follow me :
Related Posts
Athletes and Bitcoin: Securing Wealth Beyond Their Careers
Oct 27, 2024
Športniki in bitcoin - Kaj pa po koncu kariere?
Oct 27, 2024
Lightning Network to Wspólny Język Ekonomii Bitcoina
Oct 25, 2024