introduzione
Le dimostrazioni a conoscenza zero, in particolare zk-SNARK (Zero-Knowledge Succinct Non-Interactive Knowledge Arguments), sono forse una delle tecnologie all'avanguardia più importanti nel Web 3. Attualmente, la maggior parte dell'attenzione dei media e degli investimenti in questo sottocampo è focalizzata su zk-Rollups, una soluzione di scalabilità che fornisce un'enorme scalabilità alle blockchain L1 come Ethereum. Nonostante ciò, zk-Rollups è tutt'altro che l'unico scopo di zk-SNARKs. Questo articolo fornirà un'analisi approfondita del concetto di codice assembly a conoscenza zero (zkASM), ne valuterà i casi d'uso in zk-Rollup e altri aspetti ed esplorerà il suo potenziale nel reinventare Internet da un livello teorico.
Principi tecnici
Come suggerisce il nome, zk-ASM è costituito principalmente da due componenti tecnici: ZK e ASM. ZK si riferisce a zk-SNARKs, che è un argomento di conoscenza conciso e non interattivo, e ASM si riferisce al codice assembly. Per comprendere le potenzialità di zk-ASM dobbiamo prima comprendere le basi teoriche di questi due concetti apparentemente oscuri.
zk-SNARK
Gli zk-SNARK sono il fiore all'occhiello delle zk-Proofs: sono un modo conciso per dimostrare che un'affermazione è vera senza rivelare alcuna informazione sui dati da dimostrare. Ad esempio, supponiamo che qualcuno dichiari "So che esiste un m tale che C(m) = 0", dove m è un gigabyte di informazioni e C è una funzione. zk-SNARK costituirà una breve prova (<1GB) che verificherà rapidamente l'esistenza di m senza esporre alcuna informazione su m (a parte le informazioni pubbliche).
Cos'è esattamente questa "C(m)"? Come si usa? Questa funzione è in realtà un circuito aritmetico o una rappresentazione in grafico aciclico diretto (DAG) della funzione specifica che vogliamo eseguire, come mostrato in figura. Essenzialmente, "m" sono i dati di ingresso del circuito e i "nodi" specifici del circuito sono porte logiche o operazioni individuali. Ad esempio, "2" e "3" possono essere immessi nel nodo "+", quindi "5" viene inviato all'operatore successivo. Ciò consente di codificare qualsiasi operazione aritmetica o logica in un "circuito aritmetico".

Dopo che il codice zk-SNARK che vogliamo eseguire è rappresentato da un circuito aritmetico, possiamo iniziare a costruire questo zk-SNARK. Fondamentalmente, la fattibilità di zk-SNARK è stabilita dal "Teorema Fondamentale dell'Algebra". Secondo il Teorema Fondamentale dell'Algebra, un polinomio di grado "d" ha al più radici "d". Questo trucco matematico è un processo in due fasi: (1) convertire la funzione "f(m)" che deve essere dimostrata in un polinomio e continuare a utilizzare il polinomio, e (2) utilizzare il "Teorema Fondamentale dell'Algebra" per elaborare il polinomio e fornire una dimostrazione concisa. In termini tecnici, la prima parte è chiamata "Polynomial Commitment Scheme" (PCS) e la seconda parte è chiamata "Polynomial Interactive Proof of Oracle" (PIOP).

La composizione di un efficiente circuito universale SNARK. Fonte: https://cs251.stanford.edu/lectures/lecture15.pdf
L'implementazione specifica di PCS e PIOP va oltre lo scopo di questo articolo, ma questo ci fornisce uno schizzo approssimativo dei passaggi principali di zk-SNARK:
Seleziona una funzione (funzione codice, equazione matematica, ecc.) su cui desideri eseguire zk-SNARK
Codifica questa funzione in un circuito aritmetico C(m)
Esegui PCS per ottenere la rappresentazione polinomiale del circuito aritmetico
Esegui PIOP e ottieni una prova concisa della dimensione del log (m).
Ora esiste uno zk-SNARK personalizzato che può dimostrare che qualcuno conosce un'informazione senza rivelarne il contenuto specifico.
codice di assemblaggio
Il secondo pezzo del puzzle zk-ASM è il codice assembly. È un linguaggio simile a un linguaggio contenente istruzioni linguistiche di livello molto basso che sono facili da leggere per le macchine ma difficili da decifrare per gli esseri umani. A differenza dei linguaggi di alto livello come Python, Java o anche C, il linguaggio assembly contiene alcune funzioni molto primitive, come MOVE (spostamento), CMP (confronto), ADD (addizione) e JMP (salto) nel processore e registrare i livelli. Ad esempio, il codice Python per digitare i numeri da 1 a 9 sullo schermo è `123456789`:

È facile da capire, vero? Diamo un'occhiata alla sua versione di assembly x86:

È davvero molto più problematico e questa è solo un'operazione molto semplice. In questo caso, perché usare il linguaggio assembly? Come accennato in precedenza, sebbene queste istruzioni non siano facilmente leggibili dagli esseri umani, possono essere facilmente "assemblate" nel codice byte di "110011001" affinché una macchina possa leggerle ed eseguirle (chiamato assemblatore). In confronto, sebbene i linguaggi di alto livello come Python e Java siano più leggibili, il processore non può eseguire direttamente programmi scritti in questi linguaggi. Abbiamo bisogno di un "compilatore" per convertire il codice Python o Java che scriviamo nel codice assembly sopra e consegnarlo alla macchina per l'assemblaggio e l'esecuzione. Il motivo per cui lo stesso pezzo di codice Python o Java può essere eseguito senza problemi su processori e sistemi operativi diversi è perché il compilatore fa il lavoro pesante e compila il codice sorgente in linguaggio assembly per il processore o sistema operativo specifico.
Poiché tutti i linguaggi vengono compilati in codice assembly (che a sua volta viene ulteriormente compilato in file binari eseguibili), l'assembly è essenzialmente come la "madre di tutti i linguaggi". Supponendo ora di poter convertire tutti gli operandi in un linguaggio assembly (come x86 o RISC-V) in rappresentazioni di circuiti aritmetici, possiamo fornire dimostrazioni zk-SNARK per tutti gli operandi in questo linguaggio assembly. In teoria, ciò significa che possiamo fornire zk-SNARK per qualsiasi programma scritto in qualsiasi linguaggio di alto livello compilabile in assembly, come Python o Java. Per questo motivo, zk-ASM merita il nostro attento studio.
Applicazione pratica
Rollup zk-EVM: Poligono zk-ASM
Una delle applicazioni più importanti di zk-ASM è la creazione di zk-Rollup compatibili con la Ethereum Virtual Machine, o zk-EVM. zk-EVM è molto importante per la scalabilità della blockchain perché consente ai programmatori di eseguire il deploy su catene L2 basate su zk-Rollup senza apportare troppe (o nessuna) modifica al codice. A questo proposito, zk-EVM di Polygon è un tipico esempio di come zk-ASM può essere utilizzato per raggiungere questo obiettivo.

Gli sviluppatori della catena pubblica Ethereum L1 utilizzano solitamente il linguaggio Solidity, che è un linguaggio di programmazione di alto livello simile al linguaggio C. Prima che il codice Solidity venga eseguito sulla blockchain L1, verrà prima compilato in una serie di codici operativi EVM, come ADD, SLOAD, EQ, ecc. Per impostazione predefinita, questo processo ovviamente non crea alcun zk-Proof. L'ingegno di Polygon è stato quello di creare un modo per tradurre ogni codice operativo EVM nel loro zk-ASM scritto su misura, che è molto compatibile con zk-SNARK. Il loro L2 zk-EVM esegue quindi zk-ASM mentre crea il circuito zk-SNARK dell'ASM per creare una prova zk-SNARK. Ad esempio, il codice dell'operazione ADD nell'EVM verrebbe tradotto in zk-ASM di Polygon come segue:

Poiché la magia di Polygon zk-EVM avviene a livello di assemblaggio, è due livelli "inferiori" rispetto allo strato di codice toccato da Ethereum normale, lo strato di "Solidità". Per questo motivo, la maggior parte degli sviluppatori può trasferire il codice EVM creato per la rete principale di Ethereum direttamente su Polygon zk-EVM. Allo stesso tempo, Polygon zk-EVM "mantiene" lo stack tecnologico di Ethereum fino al livello del codice operativo e tutta l'infrastruttura di debug che si basa sull'analisi del codice operativo compilato può ancora essere utilizzata intatta. Questo è diverso da altri progetti zk-EVM che non forniscono zk-Proof a livello di codice operativo, come zk-Sync. Pertanto, sebbene Polygon abbia inventato e verificato il proprio linguaggio assembly, come ha affermato Buterin, "può comunque verificare il codice EVM, utilizza semplicemente una logica interna diversa".
Oltre i rollup: zk-WASM
zk-EVM non è affatto l'unico caso d'uso per zk-ASM. Come accennato in precedenza, il linguaggio assembly è essenzialmente la "madre di tutti i linguaggi" e la creazione di zk-ASM sbloccherà zk-Proofs per programmi generici scritti in qualsiasi linguaggio compilabile in linguaggio assembly. Web Assembly (WASM) è uno dei più importanti linguaggi assembly emergenti. È stato rilasciato per la prima volta nel 2018 e mira a migliorare la velocità di esecuzione delle applicazioni web e fornire supplementi di esecuzione per Javascript (il principale linguaggio di programmazione dietro il Web).
In sostanza, con l'evoluzione del Web nel corso degli anni, le applicazioni Web sono cresciute in dimensioni e complessità, il che significa che i browser devono compilare tutto ciò che è scritto in Javascript, spesso a velocità estremamente lente, e devono ripetere complesse operazioni di "compilazione-ottimizzazione-ricarica" processi. WebAssembly elimina la dipendenza dai complessi motori di esecuzione del browser fornendo un linguaggio assembly portabile, modulare e facile da eseguire. Inoltre, WASM, in quanto linguaggio assembly, consente ai programmatori di scrivere frammenti di codice utilizzando linguaggi come C, C++, Rust, Java o Ruby che possono essere eseguiti direttamente nel browser. WASM è quindi diventata la tecnologia preferita per "fornire funzioni serverless distribuite".
Che ruolo possono svolgere zk-SNARK a questo riguardo? WASM è unico in quanto è una tecnologia lato client che interagisce direttamente con i dati immessi dall'utente. Ciò spesso include dati sensibili come password e informazioni personali, quindi abbiamo bisogno di una tecnologia che (1) garantisca che il programma venga eseguito in modo accurato e (2) garantisca che le informazioni sensibili non vengano divulgate. zk-SNARK è la soluzione perfetta a questi due problemi, ed è quindi un importante pezzo del puzzle per WASM.
Il lavoro sullo sviluppo di zk-WASM è ancora nelle fasi iniziali, ma diversi progetti hanno recentemente rilasciato prototipi di circuiti zk-SNARK per WebAssembly. Ad esempio, il simulatore zk-SNARK “ZAWA” di Delphinus Lab offre un modo per codificare gli operandi e la semantica della macchina virtuale WASM nel circuito informatico, consentendole di produrre prove zk-SNARK. Il circuito zk-WASM continuerà sicuramente ad essere ottimizzato in modo che i programmi scritti in linguaggi generici come C, C++, Rust e Ruby adottino il paradigma zk-Proofs.
Insomma
Questo articolo esplora le basi teoriche di zk-ASM ed esamina due casi d'uso paradigmatici di zk-ASM: Polygon utilizza zk-ASM per creare zk-EVM a livello di codice operativo e applica zk-SNARK a WebAssembly per creare zk-WASM. In definitiva, zk-ASM promette di combinare l’interoperabilità e la scalabilità del Web 2 con l’affidabilità e la sicurezza del Web 3.
Da un lato, la blockchain cerca sempre più di superare gli attuali colli di bottiglia del volume di elaborazione e, dall’altro, gli approcci Web 2 sono sempre più criticati per non riuscire a proteggere adeguatamente i dati e la privacy degli utenti. Poiché i programmatori sono in grado di utilizzare i paradigmi di progettazione Web 3 nel codice Web 2 e portare i linguaggi e il codice Web 2 nella blockchain, si prevede che zk-ASM universale diventi un punto d'incontro tra i mondi Web 2 e Web 3. In considerazione di ciò, zk-ASM potrebbe consentirci di reimmaginare un Internet più sicuro e senza fiducia.