logo
Costruire un Hot Wallet con Substrate Primitives

Costruire un Hot Wallet con Substrate Primitives

Substrate e il sistema FRAME definiscono per lo sviluppo in runtime un potente insieme di funzioni primitive per la costruzione di infrastrutture blockchain. Usati insieme, creano nuovi approcci ai problemi esistenti. Questo articolo esplorerà un'applicazione reale in cui le funzioni di Substrate vengono utilizzate per implementare un hot wallet multi-indirizzo.

Un hot wallet di solito significa che le chiavi di spesa (spending keys)sono conservate su un dispositivo online in modo che possa creare e trasmettere transazioni in modo comodo e veloce, ma in genere con un rischio maggiore. Questo articolo esplorerà alcuni account abstractions- account multi-signature, account proxy e account derivative di Substrate ​​- che ci consentono di costruire un hot wallet in grado di supportare milioni di indirizzi in sicurezza.

Questo wallet sarebbe utile se aveste bisogno di conservare token per diversi account, ma nel frattempo voleste anche dare a ciascun cliente il proprio indirizzo di deposito. La soluzione banale sarebbe quella di creare un nuovo indirizzo di deposito per ogni cliente generando una nuova coppia di chiavi. Ma gestire tutte quelle chiavi diventa rapidamente non facile. E se aveste decine o centinaia di migliaia di utenti? Utilizzando Substrate account abstractions, possiamo costruire una soluzione che sia allo stesso tempo più scalabile e più sicura.

Origini e ID account

Prima di iniziare a costruire l'hot wallet, dobbiamo gettare le basi che utilizzerà. Quando un utente interagisce con una blockchain, sta chiamando una funzione; l'insieme di queste funzioni "inviabili" costituisce l'interfaccia della blockchain.

Poiché le funzioni “inviabili” vengono invocate dal mondo esterno, la prima cosa che potrebbe interessare alla blockchain è chi ha effettivamente chiamato la funzione. Come prima cosa, la funzione deve verificare se il chiamante ha l'autorità per eseguirla. In secondo luogo, la chain potrebbe aver bisogno di sapere esattamente chi ha chiamato la funzione per aggiornare alcune informazioni sul chiamante. Se il chiamante è un account, la chain potrebbe dover aggiornare il suo saldo, ad es. per detrarre una commissione.

Potreste pensare: "Cosa intendi se il chiamante è un account?" Le funzioni in Substrate non provengono da account di per sé, provengono dalle origini. Il sistema di governance di Polkadot, ad esempio, ha una suite di origini speciali con privilegi come l'allocazione di fondi del Tesoro o la cancellazione di slashes. Se progettate la vostra blockchain con Substrate, potete creare le vostre origini personalizzate. Ma la cosa da tenere a mente per questo articolo è che un account è semplicemente una variante dell'origine Substrate. Potete pensare a questo come Substrate che dice alla funzione inviabile: "L'origine di questa esecuzione è un account".

Ora che abbiamo fatto il primo passo, abbiamo bisogno di un modo per dire alla funzione a quale account si riferisce l'origine. Se avete utilizzato qualsiasi blockchain, potreste essere abituati a un ID account come chiave pubblica che corrisponde a una chiave privata. Va bene, funziona anche in Substrate. In questo senso, un account viene identificato dalla chiave pubblica e autorizzato dalla corrispondente chiave privata.

Tuttavia, Substrate supporta maggiore astrazione. Un ID account può essere qualsiasi numero di 32 byte.[1] Potrebbe essere la chiave pubblica che corrisponde a una chiave privata, ma non deve esserlo per forza. Ha solo bisogno di un metodo di autorizzazione. Come se dovesse esserci un modo univoco per generare questo numero di identificazione dell'account, in modo che Substrate possa completare la frase iniziata sopra: "L'origine di questa esecuzione è un account identificato da questo numero".[2]

Funzioni hash

Le funzioni hash si verificano continuamente nella blockchain. I blocchi sono letteralmente collegati tra loro tramite i loro hash. Ma useremo le proprietà delle funzioni hash per altri due scopi: generare ID account e identificare le chiamate di funzione.

Una funzione hash prende un input di qualsiasi dimensione e lo mappa su un output di dimensioni fisse, diciamo 32 byte. Ma non si limita a mappare i dati su qualsiasi numero di 32 byte, ma dovrebbe mappare deterministicamente i dati univoci a un numero univoco. Si dà il caso che 32 byte possano catturare un numero astronomicamente elevato di elementi.[3]

Ad esempio, potremmo prendere alcune informazioni su una chain, come "polkadot-treasury", e trasformarle in un ID account (32 byte) utilizzando una funzione hash. Oppure, potremmo prendere le informazioni su alcune transazioni, ad es. "trasferisci 10 unità sull'account 123..." e confidare nel fatto che l'hash sia un'immagine unica di tali informazioni.

Account Multisig

Detto questo, possiamo iniziare a costruire la prima parte del nostro hot wallet: un account multisig. Gli account Multisig potrebbero non sembrare parte di un hot wallet a causa della goffaggine generale, ma questo account fungerà da base sicura per il resto dei componenti e tale goffaggine non ostacolerà l'utilizzo quotidiano.

Alcune blockchain utilizzano il multisig crittografico, dove più detentori di chiavi firmano una singola transazione off-chain prima di inviare la transazione on-chain. Il sistema multisig fornito con il sistema FRAME di Substrate funziona in un altro modo: genera un ID account basato sui singoli account che compongono il multisig e genera la soglia richiesta necessaria per l’invio dall'account creato. Substrate aggiunge uno speciale prefisso multisig a tutte queste informazioni e ne esegue l'hashing per ottenere un singolo output di 32 byte che utilizzerà l’account multisig come ID. Si noti che a questo ID account non è associata una chiave privata.

Per autorizzare una transazione da quel nuovo ID account, i membri del multisig inviano ciascuno una transazione on-chain con la chiamata di funzione che vogliono far eseguire all’account multisig. Ma non è efficiente per tutti inviare la chiamata di funzione; potrebbe essere grande e lo spazio del blocco scarso (e quindi costoso). Le funzioni hash tornano utili: solo uno dei singoli account deve inviare la chiamata di funzione effettiva; gli altri inviano solo l'hash. Stanno dicendo "siamo d'accordo a chiamare la funzione con questo hash dall'account multisig" e non è necessario inviare nuovamente la funzione.

Questo multisig da solo è troppo goffo e macchinoso per essere utilizzato come hot wallet perché richiede che più titolari di chiavi inviino transazioni per farlo funzionare. Ma è altamente sicuro e fungerà da account di base che potremo trasformare in un hot wallet senza sacrificarne la sicurezza.

Account proxy

Gli account proxy consentono all'indirizzo multisig di delegare l'autorità di spesa a un altro account, che fungerà da hot wallet pur mantenendo sicuro il multisig. Imposteremo un proxy di ritardo temporale per gestire la spesa e un altro (o più) proxy istantanei per gestire la sicurezza per questo account multisig.

Un account proxy concede alcuni privilegi da un account all'altro per effettuare chiamate di funzione per suo conto. Questi privilegi possono essere specifici, ad esempio, "solo transazioni relative allo staking", o ampi, ad esempio, "tutte le transazioni che non trasferiscono fondi", o anche privilegi completi, "qualsiasi transazione".

La creazione di un proxy richiede solo una transazione dall'account da cui è stato eseguito il proxy, indicando quale altro account sarà il suo proxied account e i suoi privilegi. Una volta che si è stabilita la relazione tra i proxy, l'account proxy potrà effettuare transazioni per l’altro account, dicendo essenzialmente alla chain: "Sono un proxy per questo account, ho questi privilegi e voglio inviare questa chiamata di funzione per conto dell’account proxied”. La logica della chain verificherà che il proxy abbia i privilegi corretti e invierà quella funzione con l'origine dell'account proxied.

L'aggiunta di un ritardo aggiunge un ulteriore livello di sicurezza. Immaginate un ritardo di 600 blocchi (un'ora su Polkadot). L'account proxy invierebbe comunque una transazione dicendo che si tratta di un proxy con alcuni privilegi, ma annuncerebbe solo l'hash della chiamata di funzione che desidera effettuare. Il proprietario dell'account proxied può richiedere la chiamata di funzione effettiva ed esaminarla. Se il proprietario non approva, può rifiutare la chiamata di funzione inviando un'altra transazione prima che scada il ritardo. Dopo il ritardo, il proxy può inviare la chiamata di funzione effettiva che corrisponde all'annuncio e Substrate la invierà.[4]

Per il nostro caso d'uso, i titolari di chiavi multisig effettueranno una transazione per impostare un altro account come proxy di ritardo con privilegi completi, ad esempio includendo i trasferimenti di saldo. Forse questo account proxy vivrà su un server online che effettua le transazioni in modo autonomo. Ogni volta che effettua una transazione, dovrà prima annunciare l'hash e quindi inviare la chiamata di funzione effettiva a qualche altro titolare dell’account (per semplicità consideriamo questo altro titolare un membro del multisig) che può verificare che la chiamata di funzione non sia dannosa. In tal caso, il multisig può effettuare una transazione in tempo per rifiutare la chiamata e, per cautela, decidere che l'account proxy è stato compromesso e rimuoverlo.

Questa configurazione funziona effettivamente, ma possiamo comunque renderla più comoda da usare. Utilizzando un solo proxy, potremmo richiedere un lungo ritardo perché coordinare un numero sufficiente di titolari di chiavi multisig per effettuare una transazione di rifiuto può essere difficile con poco preavviso. Ma un account può avere più account proxy con privilegi diversi. Per risolvere questo problema, impostare ogni titolare di chiavi multisig come un proxy con privilegi di non trasferimento, in particolare con il privilegio di rifiutare gli annunci dal proxy di ritardo.

Ricapitoliamo questa configurazione. Al centro, abbiamo un conto multisig. Questo account non ha una chiave privata, ma ha due modi per controllarla: utilizzando un account proxy ritardato o raccogliendo un numero sufficiente di firmatari degli account dei membri. Ogni membro del multisig ha anche la possibilità di rifiutare le transazioni dal proxy con privilegi completi, ma non può effettuare trasferimenti di saldo senza che altri membri si uniscano per effettuare una transazione multisig.

Di per sé, questo è un hot wallet completamente funzionale che può cambiare la hot key (l'account proxy con privilegi completi) senza cambiarne l'indirizzo (l'account multisig), semplicemente rimuovendo il proxy e impostandone uno nuovo. Ma la nostra dichiarazione del problema originale richiedeva indirizzi di deposito univoci per decine di migliaia di utenti e finora ne abbiamo solo uno.

Account Derivative

Finora abbiamo utilizzato più metodi per accedere a un account multisig; ora useremo un account per accedere a tanti multisig.

Ogni account in Substrate ha un albero di account derivati ​​a cui può accedere. Per ricavare gli ID account, e questo non ci dovrebbe più sorprendere, Substrate utilizza un algoritmo hash. Mediante l'hashing dell'ID account del chiamante con l'indice desiderato e un prefisso derivato, Substrate crea un nuovo ID account. Ad esempio, il mittente fornisce una chiamata di funzione e un indice, dicendo: "Voglio inviare questa funzione dal mio account derivato con questo indice".

Probabilmente vedrete dove sta andando. Il proprietario del wallet può assegnare un indice a ciascuno dei suoi utenti e fornire l'ID account derivato come indirizzo di deposito per quell'utente. Per accedere ai fondi, l'indirizzo proxy emetterebbe una transazione per trasferire fondi dall'indirizzo derivato del multisig.

In pratica, l'indice è limitato a 16 bit, o 65.536 account derivati, ma funziona anche il nesting. Cioè, ogni account derivato può avere il proprio insieme di 65.536 conti derivati e così via. Il secondo livello di questo albero avrebbe oltre quattro miliardi di account.

Il quadro completo

Usiamo finalmente questo. Immagina che l'utente con l'indice 11 vi paghi e voi abbiate un "account di risparmio" sul quale volete depositare i fondi. La transazione completa sarebbe del tipo: "Sono un proxy per l’account multisig e voglio trasferire fondi dall’account derivato ​​​​del multisig con indice 11 all’account di risparmio".

Supponendo che tutto appaia OK per i supervisori, il ritardo scadrebbe e il proxy può trasmettere l'intera transazione. Se i membri del multisig pensano che la hot key debba essere modificata, possono semplicemente generarne una nuova e rimuovere quella vecchia come proxy, senza influenzare il multisig o nessuno dei suoi indirizzi derivati.

L'immagine sopra mostra un diagramma del wallet che abbiamo impostato: un multisig (MS) è controllato da un insieme di chiavi (indicate con k) e imposta un proxy di ritardo del tempo (H) come tasto di scelta rapida. Dal multisig può derivare indirizzi virtualmente illimitati (l'insieme di d).

Possiamo anche ottimizzare ulteriormente questo flusso di lavoro. Substrate fornisce anche una funzione per inviare una batch di chiamate di funzione. Se gli utenti depositano e prelevano regolarmente dai loro account derivati, potete inviarli tutti in un unica batch di trasferimenti.

Le Substrate abstractions account on-chain forniscono metodi potenti per gestire gli account. Riducendo il numero di chiavi effettive necessarie e accedendo agli account in base a regole formali anziché a chiavi private, è possibile gestire centinaia di migliaia di account senza dover affrontare i limiti della memorizzazione di un numero equivalente di chiavi di firma. Questo articolo si è concentrato solo su un esempio, la creazione di un hot wallet, ma tutte le astrazioni sono isolate e possono essere composte in applicazioni più avanzate.

[1] Non devono essere 32 byte. Potete creare il vostro runtime con quello che volete, ma non voglio che questo articolo divampi nello sviluppo del runtime più di quanto dovrebbe

[2] Una rapida interruzione sulla parola “unico”, che intendo in un senso più rigoroso rispetto alla definizione media del dizionario. Una funzione è unica non se esiste una sola rappresentazione di essa, ma piuttosto se tutte le rappresentazioni (o serie di rappresentazioni) sono dimostrabilmente equivalenti. Potrebbe esistere un numero infinito di metodi per generare un particolare numero(account), ma finché tutti questi metodi generano lo stesso account, allora quell'account può essere considerato unico. Continuare su questo percorso ci porterà al tipo di matematica che ci tiene svegli la notte, ma noi stiamo generando un ID account e lo passeremo tra le funzioni, e il punto chiave qui è che non importa quante funzioni uniamo insieme (mettiamo in serie) per raggiungere un ID account, esso si comporterà come lo stesso ID account nella sua capacità di inviare origin

[3] Se siete interessati, 32 byte possono contenere fino al numero 1,15x10^77. La distanza dal bordo dell'universo osservabile è di 45,7 miliardi di anni luce, ovvero 4,32x10^23 chilometri, o 4,32x10^29 millimetri. Se consideriamo che un disco piatto, ha un'area di 5,87x10^59 millimetri quadrati. Siamo ancora fuori di un fattore 10^18, o un miliardo al quadrato. Quindi le possibilità che due diversi input hash abbiano lo stesso output è come se entrambi gli elementi atterrassero sullo stesso millimetro quadrato dell'universo osservabile, quindi lo scompongono in una griglia di 1 miliardo per 1 miliardo e di nuovo entrambi atterrano nello stesso quadrato. Quei quadrati sono larghi 1 picometro. Per riferimento, un atomo di elio ha un diametro di 62 picometri

[4] In realtà, qualsiasi account può inviare la chiamata, a condizione che il proxy abbia fatto l'annuncio, ma per motivi di pragmatismo, supponiamo che il nostro hot wallet utilizzi semplicemente lo stesso account per annunciare e inviare.

Leveraging Polkadot's Unique Capabilities To Enable Web2 UX With Subsocial's New Off-Chain Signer

Yung Beef 4.2

Polkadot, Substrate ed Ethereum

Polkadot, Substrate ed Ethereum

Sin dalla pubblicazione del documento programmatico di Polkadot tre anni fa, è stato chiaro che connettere Polkadot all’ecosistema di Ethereum per aiu

Polkadot Arena

Un breve riassunto di tutto quel che riguarda Substrate e Polkadot

Un breve riassunto di tutto quel che riguarda Substrate e Polkadot

In Parity, siamo attualmente concentrati sullo sviluppo di tre principali tecnologie: Parity Ethereum (Eth 1.0 e Serenity), Parity Substrate e il prog

Polkadot Arena

Costruire un Hot Wallet con Substrate Primitives

Costruire un Hot Wallet con Substrate Primitives

Substrate e il sistema FRAME definiscono per lo sviluppo in runtime un potente insieme di funzioni primitive per la costruzione di infrastrutture bloc

Polkadot Arena