IPFS senza dolore (ma non è sicuro)

IPFS senza dolore (ma non è sicuro)

Nonostante il fatto che su Хабр ci fosse già non c'è un solo articolo su IPFS.

Preciso subito che non sono un esperto in questo campo, ma ho dimostrato interesse per questa tecnologia e i miei tentativi di utilizzarla spesso hanno causando qualche dolore. Oggi ho di nuovo intrapreso esperimenti e ho ottenuto alcuni risultati che vorrei condividere. In breve, descriverò il processo di installazione di IPFS e alcune funzionalità (tutto è stato eseguito su ubuntu, non ho provato su altre piattaforme).

Se hai perso cos'è IPFS, è scritto in modo abbastanza dettagliato qui: habr.com/ru/post/314768

Installazione

Per la pulizia dell'esperimento, propongo di installare subito su un server esterno, poiché esamineremo alcune insidie del lavoro in modalità locale e remota. Poi, se desideri, sarà facile disinstallare, non è complicato.

Installiamo go

Documentazione ufficiale
Controlla l'ultima versione su golang.org/dl

Nota: è meglio installare IPFS con l'account utente che intendi utilizzare più frequentemente. Infatti, di seguito considereremo l'opzione di montaggio tramite FUSE e ci sono alcune sottigliezze.

cd ~
curl -O https://dl.google.com/go/go1.12.9.linux-amd64.tar.gz
tar xvf go1.12.9.linux-amd64.tar.gz
sudo chown -R root:root ./go
sudo mv go /usr/local
rm go1.12.9.linux-amd64.tar.gz

Dopo, devi aggiornare l'ambiente (maggiori dettagli qui: golang.org/doc/code.html#GOPATH).

echo 'export GOPATH=$HOME/work' >> ~/.bashrc
echo 'export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin' >> ~/.bashrc
source ~/.bashrc

Controlliamo che go sia installato

go version

Installiamo IPFS

Mi è piaciuto di più il metodo di installazione tramite ipfs-update.

Lo installiamo con il comando

go get -v -u github.com/ipfs/ipfs-update

Dopo, puoi eseguire i seguenti comandi:

ipfs-update versions — per vedere tutte le versioni disponibili da scaricare.
ipfs-update version — per vedere l'attuale versione installata (finché non abbiamo installato IPFS, sarà none).
ipfs-update install latest — per installare l'ultima versione di IPFS. Al posto di latest, puoi indicare qualsiasi versione desiderata dall'elenco disponibile.

Installiamo ipfs

ipfs-update install latest

Controlliamo

ipfs --version

In generale, l'installazione è tutta qui.

Avvio di IPFS

Inizializzazione

Per cominciare, dobbiamo eseguire l'inizializzazione.

ipfs init

In risposta riceverai qualcosa di simile:

 ipfs init
initializing IPFS node at /home/USERNAME/.ipfs
generating 2048-bit RSA keypair...done
peer identity: QmeCWX1DD7HnXXXXXXXXXXXXXXXXXXXXXXXXxxx
to get started, enter:
	ipfs cat /ipfs/QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv/readme

Puoi eseguire il comando suggerito

ipfs cat /ipfs/QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv/readme

Risultato

Ciao e benvenuto in IPFS!

██╗██████╗ ███████╗███████╗
██║██╔══██╗██╔════╝██╔════╝
██║██████╔╝█████╗  ███████╗
██║██╔═══╝ ██╔══╝  ╚════██║
██║██║     ██║     ███████║
╚═╝╚═╝     ╚═╝     ╚══════╝

Se stai vedendo questo, hai installato con successo
IPFS e ora stai interfacciandoti con l'ipfs merkledag!

 -------------------------------------------------------
| Attenzione:                                           |
|   Questo è un software alpha. Usalo a tuo rischio!  |
|   Molto è mancante o poco rifinito. Ci sono bug.     |
|   Non è ancora sicuro. Leggi le note di sicurezza per ulteriori informazioni. |
 -------------------------------------------------------

Dai un'occhiata ad alcuni degli altri file in questa directory:

  .\/about
  .\/help
  .\/quick-start     <--- esempi di utilizzo
  .\/readme          <--- questo file
  .\/security-notes

Qui, a mio avviso, inizia l'interessante. I ragazzi già nella fase di installazione iniziano a utilizzare le loro stesse tecnologie. L'hash fornito QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv — non è stato generato appositamente per te, ma è incorporato nel rilascio. Cioè, prima del rilascio hanno preparato un testo di benvenuto, lo hanno caricato in IPFS e hanno aggiunto l'indirizzo nell'installer. A mio parere, è davvero fantastico. E questo file (o meglio, l'intera cartella) ora può essere visualizzato non solo localmente, ma anche sul gateway ufficiale. ipfs.io/ipfs/QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv. In questo modo, si può essere certi che il contenuto della cartella non è stato modificato, perché se fosse stato cambiato, anche l'hash sarebbe cambiato.

A proposito, in questo caso IPFS è simile a un server di controllo versione. Se si apportano modifiche ai file sorgente della cartella e si carica di nuovo la cartella in IPFS, essa riceverà un nuovo indirizzo. Tuttavia, la vecchia cartella non scomparirà e sarà accessibile al suo indirizzo precedente.

Avvio diretto

ipfs daemon

Dovresti ricevere una risposta simile a questa:

ipfs daemon
Inizializzazione del daemon...
 versione go-ipfs: 0.4.22-
Versione repo: 7
Versione sistema: amd64/linux
Versione Golang: go1.12.7
Swarm in ascolto su /ip4/x.x.x.x/tcp/4001
Swarm in ascolto su /ip4/127.0.0.1/tcp/4001
Swarm in ascolto su /ip6/::1/tcp/4001
Swarm in ascolto su /p2p-circuit
Swarm annuncio /ip4/127.0.0.1/tcp/4001
Swarm annuncio /ip6/::1/tcp/4001
Server API in ascolto su /ip4/127.0.0.1/tcp/5001
WebUI: http://127.0.0.1:5001/webui
Gateway (sola lettura) server in ascolto su /ip4/127.0.0.1/tcp/8080
Daemon pronto

Apriamo le porte per Internet

Fai attenzione a queste due righe:

WebUI: http://127.0.0.1:5001/webui
Gateway (sola lettura) server in ascolto su /ip4/127.0.0.1/tcp/8080

Se hai installato IPFS localmente, accederai alle interfacce IPFS tramite indirizzi locali e ti sarà tutto accessibile (Per esempio, localhost:5001/webui/). Ma quando si installa su un server esterno, per impostazione predefinita, i gateway sono chiusi per Internet. Ci sono due gateway:

  1. Admin webui (github) sulla porta 5001.
  2. API esterna sulla porta 8080 (sola lettura).

Per ora, per esperimenti, è possibile aprire entrambe le porte (5001 e 8080), ma su un server di produzione, ovviamente, la porta 5001 dovrebbe essere chiusa dal firewall. C'è anche la porta 4001, necessaria affinché altri peer possano trovarti. Dovrebbe rimanere aperta per le richieste esterne.

Apriamo per la modifica ~/ipfs/config e cerchiamo queste righe:

"Addresses": {
  "Swarm": [
    "/ip4/0.0.0.0/tcp/4001",
    "/ip6/::/tcp/4001"
  ],
  "Announce": [],
  "NoAnnounce": [],
  "API": "/ip4/127.0.0.1/tcp/5001",
  "Gateway": "/ip4/127.0.0.1/tcp/8080"
}

Sostituiamo 127.0.0.1 con l'IP del server e salviamo il file, dopodiché riavviamo ipfs (fermiamo il comando in esecuzione con Ctrl+C e lo riavviamo).

Dovremmo ottenere

...
WebUI: http://ip_tuo_server:5001/webui
Gateway (sola lettura) server in ascolto su /ip4/ip_tuo_server/tcp/8080

Ora le interfacce esterne dovrebbero essere accessibili.

Controlla

http://dominio_o_ip_del_server:8080/ipfs/QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv/readme

Dovrebbe aprirsi il file readme riportato sopra.

http://dominio_o_ip_del_server:5001/webui/

Dovrebbe aprirsi l'interfaccia web.

Se hai in esecuzione webui, puoi modificare le impostazioni di IPFS direttamente da lì, compreso visualizzare le statistiche, ma più avanti esaminerò le opzioni di configurazione direttamente tramite il file di configurazione, il che non è critico. È solo utile ricordare dove si trova il config e cosa farne, altrimenti, se l'interfaccia web non funziona, sarà più complicato.

Configuriamo l'interfaccia web per lavorare con il proprio server

Ecco il primo scoglio, su cui sono stati spesi circa tre ore.

Se hai installato IPFS su un server esterno, ma non hai installato o avviato IPFS localmente, quando accedi a /webui nell'interfaccia web dovresti vedere un errore di connessione:

IPFS senza dolore (ma non è sicuro)

Il fatto è che, secondo me, webui funziona in modo piuttosto ambiguo. Prima prova a connettersi all'API del server in cui l'interfaccia è aperta (ovviamente basandosi sull'indirizzo nel browser). E se non riesce, prova a connettersi al gateway locale. E se hai IPFS in esecuzione localmente, allora webui funzionerà normalmente, ma tu lavorerai con l'IPFS locale, non quello esterno, anche se hai aperto webui su un server esterno. Poi carichi file, ma per qualche motivo non li vedi semplicemente sul server esterno…

Se non è avviato nemmeno localmente, otteniamo un errore di connessione. Nel nostro caso, l'errore è probabilmente dovuto a CORS, come indica anche webui, proponendo di aggiungere la configurazione.

ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["http://ip_tuo_server:5001", "http://127.0.0.1:5001", "https://webui.ipfs.io"]'
ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods '["PUT", "GET", "POST"]'

Io ho semplicemente usato un wildcard.

ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["*"]'

Tutti i titoli aggiunti possono essere trovati in ~/.ipfs/config. Nel mio caso è

  "API": {
    "HTTPHeaders": {
      "Access-Control-Allow-Origin": [
        "*"
      ]
    }
  },

Riavviamo ipfs e vediamo che webui si è connesso con successo (dovrebbe farlo, se hai aperto i gateway per richieste esterne, come descritto sopra).

Ora puoi caricare cartelle e file direttamente tramite l'interfaccia web, oltre a creare le tue cartelle.

Montaggio del file system FUSE

Questa è una funzionalità piuttosto interessante.

Possiamo aggiungere file (come cartelle), non solo tramite l'interfaccia web, ma anche direttamente nel terminale, ad esempio

ipfs add test -r
added QmfYuz2gegRZNkDUDVLNa5DXzKmxxxxxxxxxx test/test.txt
added QmbnzgRVAP4fL814h5mQttyqk1aURxxxxxxxxxxxx test

L'ultimo hash è l'hash della cartella radice.

Con questo hash possiamo aprire la cartella su qualsiasi nodo ipfs (che possa trovare il nostro nodo e ottenere il contenuto), possiamo farlo tramite l'interfaccia web sulla porta 5001 o 8080, oppure localmente tramite ipfs.

ipfs ls QmbnzgRVAP4fL814h5mQttyqk1aUxxxxxxxxxxxxx
QmfYuz2gegRZNkDUDVLNa5DXzKmKVxxxxxxxxxxxxxx 10 test.txt

Ma è possibile aprirlo anche come una normale cartella.

Creiamo due cartelle nella radice e forniamo i diritti al nostro utente.

sudo mkdir /ipfs /ipns
sudo chown NOME_UTENTE /ipfs /ipns

e riavviamo ipfs con il flag —mount

ipfs daemon --mount

È possibile creare cartelle anche in altri luoghi e specificare il percorso tramite i parametri ipfs daemon —mount —mount-ipfs /percorso_ipfs —mount-ipns /percorso_ipns

Ora la lettura da questa cartella è un po' insolita.

ls -la /ipfs
ls: reading directory '/ipfs': Operazione non consentita
totale 0

Cioè, non c'è accesso diretto alla radice di questa cartella. Tuttavia, puoi ottenere il contenuto conoscendo l'hash.

ls -la /ipfs/QmbnzgRVAP4fL814h5mQttyqxxxxxxxxxxxxxxxxx
totale 0
-r--r--r-- 1 root root 10 31 Ago 07:03 test.txt

cat /ipfs/QmbnzgRVAP4fL814h5mQttyqxxxxxxxxxxxxxxxxx/test.txt 
test
test

All'interno della cartella anche il completamento automatico funziona quando si specifica il percorso.

Come ho detto sopra, ci sono delle sottigliezze nel montaggio: per impostazione predefinita, le cartelle FUSE montate sono accessibili solo all'utente corrente (anche root non potrà leggere da tale cartella, per non parlare di altri utenti nel sistema). Se vuoi rendere queste cartelle accessibili ad altri utenti, devi modificare in configurazione «FuseAllowOther»: false in «FuseAllowOther»: true. Ma non è tutto. Se esegui IPFS con l'utente root, allora va tutto bene. Ma se lo fai con un utente normale (anche se con sudo), riceverai un errore.

mount helper error: fusermount: l'opzione allow_other è consentita solo se 'user_allow_other' è impostato in /etc/fuse.conf

In tal caso, devi modificare /etc/fuse.conf, decommentando la riga #user_allow_other.

Dopo di che, riavviamo ipfs.

Problemi noti con FUSE

Non è raro riscontrare che dopo il riavvio di ipfs con montaggio (o anche in altri casi), i punti di montaggio /ipfs e /ipns diventano inaccessibili. Non c'è alcun accesso a essi, e ls -la /ipfs mostra ???? nella lista dei diritti.

Ho trovato questa soluzione:

fusermount -z -u /ipfs
fusermount -z -u /ipns

Dopo di che riavviamo ipfs.

Aggiungiamo il servizio

Naturalmente, l'esecuzione nel terminale è adatta solo per test iniziali. In modalità operativa, il demone dovrebbe avviarsi automaticamente all'avvio del sistema.

Con sudo creiamo il file /etc/systemd/system/ipfs.service e vi scriviamo:

[Unit]
Description=IPFS Daemon
After=syslog.target network.target remote-fs.target nss-lookup.target

[Service]
Type=simple
ExecStart=/home/USERNAME/work/bin/ipfs daemon --mount
User=USERNAME
Restart=always

[Install]
WantedBy=multi-user.target

USERNAME deve ovviamente essere sostituito con il tuo utente (e forse il percorso completo al programma ipfs sarà diverso per te (devi indicare per forza il percorso completo)).

Attiviamo il servizio.

sudo systemctl enable ipfs.service

Avviamo il servizio.

sudo service ipfs start

Controlliamo lo stato del servizio.

sudo service ipfs status

Per pulizia dell'esperimento, in seguito sarà possibile riavviare il server per verificare che ipfs si avvii correttamente in automatico.

Aggiungiamo i peer noti

Consideriamo una situazione in cui abbiamo nodi IPFS installati sia su un server esterno che localmente. Sul server esterno aggiungiamo un file e cerchiamo di ottenerlo tramite IPFS localmente usando CID. Cosa succederà? Ovviamente, il server locale probabilmente non sa nulla del nostro server esterno e cercherà semplicemente di trovare il file tramite CID "chiedendo" a tutti i peer IPFS a cui ha avuto accesso. Questi a loro volta chiederanno agli altri. E così via, finché il file non viene trovato. In sostanza, la stessa cosa accade quando cerchiamo di ottenere un file tramite il gateway ufficiale ipfs.io. Se siamo fortunati, il file verrà trovato in pochi secondi. Se no, potrebbe non essere trovato neanche dopo alcuni minuti, il che influisce molto sul comfort del lavoro. Ma noi sappiamo dove apparirà per primo quel file. Perché non dire subito al nostro server locale "Cerca prima lì"? A quanto pare, è possibile farlo.

1. Accediamo al server remoto e nel file di configurazione ~\/ .ipfs\/config cerchiamo

"Identity": {
    "PeerID": "QmeCWX1DD7HnPSuMHZSh6tFuxxxxxxxxxxxxxxxx",

2. Eseguiamo sudo service ipfs status e cerchiamo le voci Swarm, ad esempio:

Swarm announcing \/ip4\/ip_tuo_server\/tcp\/4001

3. Componiamo da questo un indirizzo generale del tipo "\/ip4\/ip_tuo_server\/tcp\/4001\/ipfs\/$PeerID".

4. Per maggiore affidabilità, attraverso il nostro webui locale proviamo ad aggiungere questo indirizzo ai peer.

IPFS senza dolore (ma non è sicuro)

5. Se tutto va bene, apriamo il file di configurazione locale ~\/ .ipfs\/config, troviamo "Bootstrap": […
e aggiungiamo per primo all'array l'indirizzo ottenuto.

Riavviamo IPFS.

Ora aggiungiamo un file sul server esterno e proviamo a richiederlo localmente. Dovrebbe arrivare rapidamente.

Ma questa funzionalità è ancora instabile. Per quanto ne so, anche se indichiamo l'indirizzo di un peer in Bootstrap, durante il funzionamento ipfs modifica l'elenco delle connessioni attive ai peer. In ogni caso, si sta discutendo di ciò e ci sono richieste riguardo alla possibilità di indicare peer permanenti qui e sembra che si prevede sia previsto di aggiungere qualche funzionalità in ipfs@5.0+

L'elenco degli attuali peer può essere visto sia nel webui che nel terminale.

ipfs swarm peers

In entrambe le interfacce si può aggiungere manualmente il proprio peer.

ipfs swarm connect "\/ip4\/ip_tuo_server\/tcp\/4001\/ipfs\/$PeerID"

Fino a quando non miglioreranno questa funzionalità, possiamo scrivere uno strumento che verifichi la connessione con il peer desiderato e, se non è presente, aggiunga la connessione.

Ragionamenti

Tra coloro che sono già familiari con IPFS, ci sono sia argomenti a favore che contro. In linea di massima, la discussione di ieri discussione mi ha spinto a scavare ancora una volta su IPFS. Riguardo alla discussione menzionata: non posso dire di essere fortemente contro alcuna delle argomentazioni espresse (sono d'accordo solo su quella che afferma che un programma e mezzo utilizza IPFS). In generale, entrambi hanno le loro ragioni (soprattutto il commento sui controlli fa riflettere). Ma se si scarta la valutazione morale e legale, quale valutazione tecnica darebbe ognuno a questa tecnologia? Personalmente ho una sensazione interna che «questo è necessario, ha sicure prospettive». Ma il perché esattamente non ha una formulazione chiara. Se si guardano i mezzi centralizzati esistenti, per molti parametri sono decisamente avanti (stabilità operativa, velocità di funzionamento, gestibilità e così via). Tuttavia, ho un'idea che sembra avere senso e che difficilmente potrebbe essere realizzata senza tali sistemi decentralizzati. Certamente, sto alzando la posta, ma la formulerei così: il principio di distribuzione delle informazioni su Internet deve essere cambiato.

Spiego. Se ci si pensa, attualmente le informazioni si diffondono secondo il principio «spero che chi gliel'ho passata, la protegga e non venga persa o ricevuta da chi non la deve ricevere». Prendiamo ad esempio i vari servizi di posta, archiviazione cloud e così via. E cosa abbiamo ottenuto alla fine? Su Habr, Sicurezza informatica è al primo posto e praticamente ogni giorno riceviamo notizie su un'ulteriore fuga globale di dati. In linea di massima, tutto ciò che è più interessante è elencato nell'<ironia>articolo straordinario<\/ironia> L'estate è quasi finita. Quasi non ci sono dati non trapelati. Quindi i principali giganti di Internet stanno diventando sempre più grandi, accumulano sempre più informazioni e simili fughe di dati sono una sorta di esplosioni atomiche informative. Non era mai successo prima, e ora ancora. Allo stesso tempo, anche se molti comprendono che ci sono rischi, continueranno a fidarsi dei loro dati a società terze. Innanzitutto, non ci sono molte alternative, e in secondo luogo, quelle promettono che hanno risolto tutte le vulnerabilità e che non ricapiterà mai più.

Quale opzione mi sembra migliore? A mio avviso, i dati dovrebbero essere inizialmente diffusi in modo aperto. Ma l'apertura, in questo caso, non significa che tutto debba essere facilmente leggibile. Parlo dell'apertura nel magazzinaggio e nella distribuzione, ma non di un'apertura totale nella lettura. Presumo che le informazioni debbano essere diffuse con chiavi pubbliche. Infatti, il principio delle chiavi aperte/chiuse è già antico, praticamente come Internet. Se le informazioni non sono riservate e sono destinate a un ampio pubblico, vengono pubblicate immediatamente con una chiave pubblica (ma sempre in forma crittografata, chiunque può semplicemente decrittografarla con la chiave disponibile). E se non è così, viene pubblicata senza chiave pubblica, e la chiave stessa viene fornita a chi deve avere accesso a queste informazioni. Inoltre, chi deve leggerle deve avere solo la chiave, e non dovrebbe preoccuparsi troppo di dove trovare queste informazioni — le scarica semplicemente dalla rete (questo è il nuovo principio di distribuzione in base al contenuto, non all'indirizzo).

In questo modo, i malintenzionati dovrebbero procurarsi un enorme numero di chiavi segrete per un attacco di massa e difficilmente riusciranno a ottenerle tutte in un solo posto. Questa sfida, a mio avviso, è più complessa rispetto a violare un determinato servizio.

E qui si chiude anche un altro problema: la conferma dell'autenticità. Oggi in Internet si possono trovare molte citazioni scritte dai nostri conoscenti. Ma dove è la garanzia che siano state effettivamente scritte da loro? Se ogni tale registrazione fosse accompagnata da una firma digitale, sarebbe molto più semplice. E non importa dove si trovano queste informazioni, ciò che conta è la firma, che per sua natura è difficile da falsificare.

Ecco dove diventa interessante: IPFS già incorpora strumenti di crittografia (dopotutto è costruito sulla tecnologia blockchain). Nella configurazione è già specificata la chiave privata.

  "Identity": {
    "PeerID": "QmeCWX1DD7HnPSuMHZSh6tFuMxxxxxxxxxxxxxx",
    "PrivKey": "CAASqAkwggSkAgEAAoIBAQClZedVmj8JkPvT92sGrNIQmofVF3ne8xSWZIGqkm+t9IHNN+\/NDI51jA0MRzpBviM3o\/c\/Nuz30wo95vWToNyWzJlyAISXnUHxnVhvpeJAbaeggQRcFxO9ujO9DH61aqgN1m+JoEplHjtc4KS5
pUEDqamve+xAJO8BWt\/LgeRKA70JN4hlsRSghRqNFFwjeuBkT1kB6tZsG3YmvAXJ0o2uye+y+7LMS7jKpwJNJBiFAa\/Kuyu3W6PrdOe7SqrXfjOLHQ0uX1oYfcqFIKQsBNj\/Fb+GJMiciJUZaAjgHoaZrrf2b\/Eii3z0i+QIVG7OypXT3Z9JUS60
KKLfjtJ0nVLjAgMBAAECggEAZqSR5sbdffNSxN2TtsXDa3hq+WwjPp\/908M10QQleH\/3mcKv98FmGz65zjfZyHjV5C7GPp24e6elgHr3RhGbM55vT5dQscJu7SGng0of2bnzQCEw8nGD18dZWmYJsE4rUsMT3wXxhUU4s8\/Zijgq27oLyxKNr9T7
2gxqPCI06VTfMiCL1wBBUP1wHdFmD\/YLJwOjV\/sVzbsl9HxqzgzlDtfMn\/bJodcURFI1sf1e6WO+MyTc3.................

Non sono un esperto di sicurezza e non posso sapere esattamente come utilizzarli correttamente, ma mi sembra che a livello di scambio tra i nodi IPFS queste chiavi vengano utilizzate. Inoltre, js-ipfs e progetti-esempio come orbit-db, su cui si basa orbit.chat. Quindi, teoricamente, ogni dispositivo (mobile e non solo) può essere facilmente dotato delle proprie macchine di crittografia e decrittografia. In questo caso, rimarrebbe solo a ognuno prendersi cura della conservazione delle proprie chiavi private e ognuno sarebbe responsabile della propria sicurezza, invece di essere ostaggio del fattore umano in qualche super popolare gigante di Internet.

Solo gli utenti registrati possono partecipare al sondaggio. Accedi, per favore.

Hai mai sentito parlare di IPFS?

  • Non ho mai sentito parlare di IPFS, ma sembra interessante

  • Non ho sentito e non voglio sentire

  • Ho sentito, ma non mi ha interessato

  • Ho sentito, ma non ho capito, ora sembra interessante

  • Uso attivamente IPFS da tempo

Hanno votato 69 utenti. 13 utenti si sono astenuti.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster