Internet computer wiki

Canister – Smart Contract

Canister – Smart Contract

I canisters sono smart contract che scalano – unità computazionali interoperabili progettate per servizi su scala internet.

Una dapp costruita su ICP può essere composta da uno o più canister, alcuni dei canister possono fornire interfacce web alle quali gli utenti accedono tramite il loro browser.

A volte un sistema o un servizio Web3 o una dapp possono essere composti da migliaia o milioni di canisters. Per esempio un servizio di social può creare una istanza canister per ogni user oppure in alternativa, un singolo canister può essere un servizio autonomo o una dapp.

Alcune caratteristiche chiave dei canisters sono:

  • Sono adatti a tutto, cioè la classe dei loro programmi è di tipo Turing Complete (qualsiasi cosa calcolabile può essere calcolata dallo smart contract)
  • Sono a prova di manomissione perché le istruzioni del programma sono eseguite fedelmente ed i risultati parziali e finali sono accuratamente memorizzati e/o trasmessi
  • Sono autonomi, ciò significa che uno smart contract è eseguito automaticamente dal network, senza necessità di azioni da parte di nessun individuo
  • Sono componibili e supportano la “tokenizzazione”

Un’importante caratteristica da notare è che ICP permette ai canister un range di politiche di mutabilità, spaziando da “completamente immutabile” a “unilateralmente aggiornabile” con altre possibilità nel mezzo.

L’immutabilità è essenziale in certi casi, immaginate un contratto finanziario dove è fondamentale che il codice nel canister non cambi mai.

In altri casi la mutabilità è utile visto che un canister può essere aggiornato per servire meglio gli utenti o riparare a un bug

Dagli Smart Contract ai Canister

Uno smart contract è un pezzo di software o un intero programma che agisce sugli input e produce fedelmente risultati certificati mantenendo al contempo l’integrità del suo stato interno.
Per fidarsi di uno smart contract è necessario che esso giri su una piattaforma affidabile come ICP.
Gli smart contracts hanno grandi vantaggi rispetto ai software tradizionali in quanto forniscono una catena di fiducia dagli input agli output e non possono essere manomessi.

I canister sono perlopiù degli smart contracts, tuttavia ci sono diverse analogie più facili da capire da una prospettiva differente.

  • Un canister è simile ad un processo come in un sistema operativo
  • Un canister è simile ad un container come quelli usati con docker e la open container initiative
  • Un canister è un modulo istanza WebAssembly
  • Un canister è un attore nell’actor model

Canister come smart contracts

Una differenza chiave tra come vengono distribuiti gli smart contract su ICP rispetto alle altre blockchain, è come i dati provenienti dagli smart contracts possono essere verificati.

ICP è alimentata dalla Chain Key Cryptography, che permette a qualsiasi artefatto certificato da qualsiasi smart contract su qualsiasi subnet, di essere verificato usando una singola chiave pubblica da 48 byte per l’intera blockchain.
Questo è in contrasto con le blockchain tradizionali, dove l’intera blockchain dal genesis block è necessaria per verificare lo stato attuale delle cose.

Un’analogia utile è quella tra un database tradizionale e il suo registro delle transazioni.
Una chain subnet è il registro delle transazioni (certificato con crittografia) dello stato della subnet. In una blockchain tradizionale, tutto il registro delle transazioni deve essere riprodotto per certificare lo stato di uno smart contracts che sta girando nella blockchain. In una blockchain subnet, lo stato delle subnetwork ( lo stato di tutti gli smart contracts attivi sulla blockchain) è periodicamente ri-certificato (attualmente ogni 100 blocchi) così l’intera chain subnet non deve essere tenuta in giro per sempre o se necessario si può memorizzare altrove come backup.
Questo dà agli smart contracts su ICP chiari vantaggi in scalabilità rispetto a quelli su blockchain tradizionali.

Canister come processi

Un canister è molto simile a un processo in un OS come Linux, MacOS o Windows.

Il sistema operativo tiene traccia dei range di memoria validi per un processo, mentre ICP applica un limite alla memoria lineare di un canister .

Il pianificatore dell’OS “sveglia” un processo quando del lavoro deve essere fatto, mentre ICP pianifica l’esecuzione di un canister con i suoi input.
Un OS mantiene lo stato per conto di un processo, come un open file descriptors e il processo che lo tiene aperto, in modo simile ICP mantiene lo stato per conto dei canister, ma invece di file descriptors tiene traccia del bilancio in cycles del canister, chiamate in sospeso, permessi ecc.

Proprio come un processo non può direttamente modificare la sua tabella di file descriptors, un canister non può modificare direttamente il suo bilancio di cycles.

Il sistema operativo fornisce funzionalità ai processi che permettono loro di effettuare operazioni speciali, come manipolare file e comunicare con dispositivi periferici. In un modo simile ICP fornisce le API ai canister per permettergli di:

  • Fare pagamenti
  • Chiamare gli altri canister
  • Creare e gestire canister
  • Gestire i permessi
  • Avere l’orario del sistema, una funzione non banale in un sistema distribuito

Una caratteristica unica di ICP è che essa fornisce un accesso alla casualità sicura. Presto i canister saranno in grado di firmare transazioni Bitcoin ed Ethereum attraverso queste APIs.

La più grande differenza fra un processo ed un canister è che il canister è replicato attraverso diversi nodi. Quando un processo ha un malfunzionamento crasha, ma quando è il canister ad avere un malfunzionamento (causato da un bug nel WebAssembly) non succede, invece di crashare il canister riporta il suo stato ad un momento precedente all’esecuzione del messaggio corrente, così il canister può continuare ad eseguire nuovi messaggi.
Ovviamente questo è un piccolo aiuto se il canister continua a crashare su tutti i messaggi che riceve, ma è molto utile nella salvaguardia contro le mancanze accidentali nella logica del canister.

Nello specifico, un canister non può terminare nello stesso modo di un processo, perché non ci sono chiamate al sistema come exit() o abort().
Un canister può essere solo rimosso da ICP da un controller attraverso un comando amministrativo.
Il controller di un canister è un utente o un altro canister a cui è permesso eseguire comandi amministrativi, come rimuovere o aggiornare un canister.

L’abilità di un canister di controllarne un altro è un ingrediente fondamentale quando si costruiscono servizi auto-governati o autonomi su ICP.

Canister come container

Il significato della parola canister (barattolo) è simile a quello di container, infatti spesso con canister ci si riferisce ad un container cilindrico, il concetto di canister ha molte cose in comune con il concetto di container.

Docker dà questa definizione: “un container è una unità standard di software che “impacchetta” il codice e tutte le sue dipendenze così l’applicazione gira velocemente ed in modo affidabile da un ambiente computazionale ad un altro

Containers e canister sono simili anche nel fatto che possono essere stoppati (canister) o messi in pausa (container), possono essere spostati mentre sono fermi.
All’interno dei containers girano dei processi quindi devono avere a che fare anche con i processi esistenti.

La principale differenza fra containers e canisters è che un canister è uno smart contract (fornisce garanzie di sicurezza e gira su piattaforme affidabili).

Canister come istanze WebAssembly

Un canister è simile ad una istanza di un modulo WebAssembly, questa è più di un’analogia, questo è come i canister sono attualmente implementati su ICP.

Tecnicamente la parte di codice di un canister è un modulo WebAssembly che importa le API di sistema, questa è la funzionalità fornita da ICP ai canisters. Inoltre un canister può esportare una API per proprio conto, che può poi essere chiamata dagli utenti o da altri canisters.

Come recitano le specifiche WebAssembly: “un modulo istanza è la rappresentazione dinamica di un modulo, completa di un proprio stato e di uno stack di esecuzione”.
Quindi un canister distribuito su una chain subnet è un istanza di modulo WebAssembly, non un semplice modulo, perché è importare notare che molti canisters possono far girare lo stesso modulo WebAssembly.

I canisters usano la persistenza ortogonale per far sembrare che il modulo viva per sempre, rendendo i database e i file I/O obsoleti. Per memorizzare in modo persistente una variabile, gli sviluppatori possono semplicemente scriverla nella memoria. L’operazione di persistenza è completamente trasparente agli sviluppatori ed ortogonale nel senso che gli sviluppatori non devono far nulla per far persistere i dati.

Tutte le operazioni in scrittura sulla memoria lineare di un canister sono tracciati per 2 motivi.
Il primo, perché facendo questo ogni calcolo fallito o bug nel WebAssembly può essere riportato indietro, il secondo perché se una “replica” si arresta a causa di eventi imprevisti, come una interruzione di corrente, nel momento in cui tornerà online richiederebbe le pagine modificate dalle altre “replica” per riprendere le operazioni.
Questo è il sistema con il quale ICP mantiene l’illusione di fornire istanze di moduli WebAssembly dalla durata indefinita.

Utilizzare WebAssembly dà ad ICP numerosi benefici:

  • I canister possono essere scritti in qualsiasi linguaggio compilabile in WebAssembly (es Motoko, Rust) e i canister scritti in linguaggi differenti sono pienamente interoperabili.
  • WebAssembly è deterministico, eccetto per alcuni casi limite che sono facili da escludere.
  • WebAssembly ha una semantica formale. In un orizzonte temporale più lungo, potrebbero esserci ambienti di esecuzione.
  • WebAssembly formalmente verificati end-to-end, per una maggiore sicurezza.

Inoltre, ICP evolverà con le specifiche WebAssembly, supportando le nuove caratteristiche quando saranno abbastanza mature.

Canister come attori

L’actor model è un modello matematico riguardante la computazione simultanea, dove un attore, in risposta ad un messaggio, può modificare il suo stato, mandare messaggi o creare nuovi attori.

Un canister è come un attore sotto vari aspetti, per esempio ha:

  • Uno stato privato che può essere modificato soltanto da se stesso
  • Un singolo thread di esecuzione, quindi non ha bisogno di sincronizzazione basata sul blocco
  • L’abilità di comunicare con altri canisters attraverso messaggi asincroni
  • L’abilità di creare nuovi canister

 

Un’importante differenza tra gli attori tradizionali e i canister, sta nel fatto che su ICP i canisters passano i messaggi in modo bidirezionale.
I messaggi sono divisi in richieste e risposte, dove le richieste possono avere una risposta e ICP tiene traccia dei callback per le risposte.

Nella terminologia dell’actor model, ogni attore ha un indirizzo mailing usato per ricevere messaggi, Anche i canister hanno un indirizzo mailing, che può sembrare simile a un indirizzo IPv6.

Un singolo canister ha solo un thread di esecuzione per gli aggiornamenti ma ICP esegue un numero potenzialmente enorme di canisters in parallelo.
In aggiunta si fa una distinzione fra richieste, che hanno bisogno di aggiornare lo stato di un canister e fra query, che non possono modificarne lo stato.

Mentre la velocità effettiva di aggiornamento di un canister è limitata dal consenso della blockchain e dal singolo thread di esecuzione, un canister può esaudire centinaia di query in contemporanea, raggiungendo una velocità effettiva nell’ordine di migliaia di query al secondo con una latenza misurata in millisecondi.

Per completare il quadro, va aggiunto che anche l’utente finale partecipa come attore nel modello, questo significa che i browser e le app mobile possono effettuare direttamente aggiornamenti e query sui canister. Inoltre il linguaggio Mokoto, fatto su misura per ICP, si ispira all’actor model.

Vantaggi rispetto gli altri tipi di smart contracts

I canister hanno tutte le caratteristiche degli smart contracts su altre blockchain.

Tuttavia in contrasto agli smart contracts, i canister hanno caratteristiche di performance che rendono possibile usarli per costruire servizi software che possono scalare.

I canisters sono più adatti per sistemi distribuiti che lavorano in contemporanea perchè sono basati sull’actor model.

Statistiche

Il numero di canisters presenti su ICP è visibile sulla ICP dashboard.

Vedi anche