Table Des Matières
EN BREF
Nous avons vu dans l’article précédent que le protocole IPFS est divisé en un tat de sous-protocoles responsables de différentes fonctionnalités incluant l’identité, le réseau, le routage, l’échange, les objets, les fichiers et la nomination. Ces sous-systèmes ne sont pas indépendants; ils sont intégrés et tirent parti des propriétés mélangées. Cependant, il est utile de les décrire séparément, en construisant la pile de protocoles de bas en haut. après avoir détaillé chaque sous protocole, nous allons parler du future de l’IPFS. Ok alors, allons y.
Notez bien: les structures de données et les fonctions ci-dessous sont spécifiées dans la syntaxe Go.
IPFS – La Conception
Identités
Les nœuds sont identifiés par un NodeId, le hash cryptographique d’une clé publique, créé avec le puzzle crypto statique de S / Kademlia. Les nœuds stockent leurs clés publiques et privées (cryptées avec une phrase secrète). Les utilisateurs sont libres d’établir une «nouvelle» identité de nœud à chaque lancement, mais cela réduit les avantages du réseau. Les nœuds sont incités à rester les mêmes.
Notez bien: Tout au long de cet article, le hachage et la somme de contrôle se réfèrent spécifiquement aux totaux de hachage cryptographiques des données.
type NodeId Multihash type Multihash []byte // self-describing cryptographic hash digest type PublicKey []byte type PrivateKey []byte // self-describing keys type Node struct { NodeId NodeID PubKey PublicKey PriKey PrivateKey }
Génération d’identité IPFS basée sur S / Kademlia:
difficulty = <integer parameter> n = Node{} do { n.PubKey, n.PrivKey = PKI.genKeyPair() n.NodeId = hash(n.PubKey) p = count_preceding_zero_bits(hash(n.NodeId)) } while (p < difficulty)
Lors de la première connexion, les pairs échangent les clés publiques et vérifient: le hachage (other.PublicKey) est égal à other.NodeId. Sinon, la connexion est terminée.
Note sur les fonctions cryptographiques: Plutôt que de verrouiller le système sur un ensemble particulier de choix de fonctions, IPFS privilégie les valeurs autodescriptives. Les valeurs digestes de hachage sont stockées au format multihash, qui inclut un en-tête court spécifiant la fonction de hachage utilisée, et la longueur des digestes en octets. Example:
<function code><digest length><digest bytes>
Cela permet au système de (a) choisir la meilleure fonction pour le cas d’utilisation (par exemple, une sécurité renforcée par rapport à une performance plus rapide), et (b) évoluer au fur et à mesure que les choix de fonction changent. Les valeurs auto-descriptives permettent d’utiliser différents choix de paramètres de manière compatible.
Réseau
Les nœuds IPFS communiquent régulièrement avec des centaines d’autres nœuds du réseau, potentiellement sur l’Internet. Les fonctionnalités du réseau IPFS:
- Transport: IPFS convient parfaitement aux WebCTC DataChannels (Pour la connectivité du navigateur) ou à l’uTP (LEDBAT) et peut utiliser n’importe quel protocole de transport.
- Fiabilité: Grâce à l’uTP (LEDBAT) ou au protocol SCTP, l’IPFS fourni la fiabiabilité et la précision necessaire quand les réseau principaux en manquent.
- Connectivité: IPFS utilise également les techniques de traversée NAT ICE
- Intégrité: vérifie éventuellement l’intégrité des messages à l’aide d’une somme de contrôle de hachage.
- Authenticité: vérifie éventuellement l’authenticité des messages en utilisant HMAC avec la clé publique de l’expéditeur.
Note sur l’adressage par les pairs
IPFS peut utiliser n’importe quel réseau; il n’assume pas l’accès à l’IP ou en dépend. Cela permet à IPFS d’être utilisé dans les réseaux de superposition. IPFS stocke les adresses en tant que chaînes d’octets au format multiadress pour le réseau sous-jacent à utiliser. multiaddr fournit un moyen d’exprimer les adresses et leurs protocoles, y compris la prise en charge de l’encapsulation. Par exemple:
# an SCTP/IPv4 connection /ip4/10.20.30.40/sctp/1234/ # an SCTP/IPv4 connection proxied over TCP/IPv4 /ip4/5.6.7.8/tcp/5678/ip4/1.2.3.4/sctp/1234/
Routage
Les nœuds IPFS nécessitent un système de routage capable de trouver (a) les adresses réseau d’autres pairs et (b) les pairs qui peuvent servir des objets particuliers. IPFS réalise cela en utilisant une DSHT (distributed sloppy hash table) basé sur S / Kademlia et Coral, en utilisant les propriétés discutées dans l’article précédant section 3.1, La taille des objets et les modèles d’utilisation de IPFS sont similaires à Coral et Mainline, IPFS DHT distingue donc les valeurs stockées en fonction de leur taille. Les petites valeurs (égales ou inférieures à 1 Ko) sont stockées directement sur la DHT. Pour les valeurs plus grandes, la DHT stocke les références, qui sont les NodeIds de pairs pouvant servir le bloc.
L’interface de cette DSHT est la suivante:
1 2 3 4 5 6 7 8 9 10 11 12 | type IPFSRouting interface { FindPeer(node NodeId) // gets a particular peer’s network address SetValue(key []bytes, value []bytes) // stores a small metadata value in DHT GetValue(key []bytes) // retrieves small metadata value from DHT ProvideValue(key Multihash) // announces this node can serve a large value FindValuePeers(key Multihash, min int) // gets a number of peers serving a large value } |
Notez bien que différents cas d’utilisation nécessiteront des systèmes de routage sensiblement différents (par exemple DHT dans un réseau étendu, HT statique dans un réseau local). Ainsi, le système de routage IPFS peut être échangé contre un système qui répond aux besoins des utilisateurs. Tant que l’interface ci-dessus est remplie, le reste du système continuera à fonctionner.
Bloc d’échange – Protocole Bitswap
Dans IPFS, la distribution des données se fait en échangeant des blocs avec des homologues en utilisant un protocole inspiré de BitTorrent: BitSwap. Comme BitTorrent, les pairs BitSwap cherchent à acquérir un ensemble de blocs (want_list), et ont un autre ensemble de blocs à offrir en échange (have_list). Contrairement à BitTorrent, BitSwap n’est pas limité aux blocs d’un torrent. BitSwap fonctionne comme un marché persistant où les nœuds peuvent acquérir les blocs dont ils ont besoin, quels que soient les fichiers dont ces blocs font partie. Les blocs peuvent provenir de fichiers complètement indépendants du système de fichiers. Les nœuds se réunissent pour troquer sur le marché.
Alors que la notion de système de troc implique la création d’une monnaie virtuelle, il faudrait un registre global pour suivre la propriété et le transfert de la monnaie. Cela peut être implémenté en tant que stratégie BitSwap et sera exploré dans un futur article.
In the base case, BitSwap nodes have to provide direct value to each other in the form of blocks. This works fine when the distribution of blocks across nodes is complementary, meaning they have what the other wants. Often, this will not be the case. In some cases, nodes must work for their blocks. In the case that a node has nothing that its peers want (or nothing at all), it seeks the pieces its peers want, with lower priority than what the node wants itself. This incentivizes nodes to cache and disseminate rare pieces, even if they are not interested in them directly.
Dans un cas basique, les nœuds BitSwap doivent fournir une valeur directe les uns aux autres sous la forme de blocs. Cela fonctionne bien lorsque la distribution des blocs entre les nœuds est complémentaire, c’est à dire que chaque noeud a ce que l’autre veut. Souvent, ce ne sera pas le cas. Dans certains cas, les nœuds doivent fonctionner pour leurs blocs. Dans le cas où un nœud n’a rien de ce que ses pairs veulent (ou rien du tout), il cherche les pièces que ses pairs veulent, avec une priorité inférieure à celle que le nœud lui-même veut. Cela incite les nœuds à mettre en cache et à diffuser des pièces rares, même si elles ne les intéressent pas directement.
BitSwap crédit
Le protocole doit également inciter les nœuds à semer quand ils n’ont besoin de rien en particulier, car ils pourraient avoir les blocs que les autres veulent. Ainsi, les nœuds BitSwap envoient des blocs à leurs pairs de manière optimiste, s’attendant à ce que la dette soit remboursée. Mais les sangsues (nœuds à chargement libre qui ne partagent jamais) doivent être protégées. Un simple système de crédit résout le problème:
- Les pairs suivent leur balance (en octets vérifiés) avec d’autres nœuds.
- Les pairs envoient des blocs aux pairs débiteurs de façon probabiliste, selon une fonction qui diminue à mesure que la dette augmente.
Notez bien que si un nœud décide de ne pas envoyer à un pair, le nœud ignore par la suite le pair pour un délai d’attente ignore_cooldown. Cela empêche les expéditeurs d’essayer de jouer la probabilité en provoquant juste plus de jets de dés. (BitSwap par défaut est 10 secondes).
Stratégies BitSwap
Les stratégies différentes que les pairs BitSwap pourraient utiliser ont des effets très différents sur la performance de l’échange dans son ensemble. Dans BitTorrent, alors qu’une stratégie standard est spécifiée (tit-for-tat), une variété d’autres ont été implémentées, allant de BitTyrant (partageant le moins possible) à BitThief (Exploiter une vulnérabilité et ne jamais partager), à PropShare (partage proportionnel). Une gamme de stratégies (bonnes et malveillantes) pourrait également être mise en œuvre par les pairs BitSwap. Le choix de la fonction devrait donc viser à:
- maximiser la performance commerciale pour le noeud, et l’ensemble de l’échange.
- empêcher les freeloaders d’exploiter et de dégrader l’échange.
- être efficace et résistant à d’autres stratégies inconnues.
- être indulgent envers les pairs de confiance.
L’exploration de l’espace de telles stratégies est un travail futur. Un choix de fonction qui marche dans la pratique est un sigmoïde, mis à l’échelle par un ratio d’endettement:
Le ratio d’endettement r entre le noeud et sa pair est:
Étant donné r, la probabilité d’envoyer à un débiteur est:

Comme vous pouvez le voir sur la fig(1), cette fonction diminue rapidement car le taux d’endettement des nœuds dépasse deux fois le crédit établi.
Le ratio d’endettement est une mesure de confiance: indulgent pour les dettes entre des nœuds qui ont précédemment échangé beaucoup de données avec succès, et sans pitié pour des nœuds inconnus et non fiables. Cela (a) fournit une résistance aux attaquants qui créeraient beaucoup de nouveaux nœuds (attaques sybill), (b) protège les relations commerciales précédemment réussies, même si l’un des nœuds est temporairement incapable de fournir de la valeur, et (c) finit par étouffer les relations qui se sont détériorés jusqu’à ce qu’elles s’améliorent.
BitSwap Grand Livre (Ledger)
Les nœuds BitSwap tiennent les grands livres en compte pour les transferts avec d’autres nœuds. Cela permet aux nœuds de garder une trace de l’historique et d’éviter toute falsification. Lors de l’activation d’une connexion, les nœuds BitSwap échangent leurs informations de grand livre. S’il ne correspond pas exactement, le grand livre est réinitialisé à partir de zéro, perdant le crédit ou la dette accumulée. Il est possible que des nœuds malveillants “perdent” délibérément le grand livre, dans l’espoir d’effacer les dettes. Il est peu probable que les nœuds aient accumulé suffisamment de dettes pour justifier la perte de la fiducie accumulée; Cependant, le nœud partenaire est libre de le considérer comme une mauvaise conduite et refuse d’échanger.
type Ledger struct { owner NodeId partner NodeId bytes_sent int bytes_recv int timestamp Timestamp }
Les nœuds sont libres de conserver l’historique du registre, même si cela n’est pas nécessaire pour un fonctionnement correct. Seules les entrées actuelles du grand livre sont utiles. Les nœuds sont également libres de collecter les livres au besoin, en commençant par les livres moins utiles: les anciens (les pairs peuvent ne plus exister) et les petits.
Spécification BitSwap
Les nœuds BitSwap suivent un protocole simple.
// Additional state kept type BitSwap struct { ledgers map[NodeId]Ledger // Ledgers known to this node, inc inactive active map[NodeId]Peer // currently open connections to other nodes need_list []Multihash // checksums of blocks this node needs have_list []Multihash // checksums of blocks this node has } type Peer struct { nodeid NodeId ledger Ledger // Ledger between the node and this peer last_seen Timestamp // timestamp of last received message want_list []Multihash // checksums of all blocks wanted by peer // includes blocks wanted by peer’s peers } // Protocol interface: interface Peer { open (nodeid :NodeId, ledger :Ledger); send_want_list (want_list :WantList); send_block (block :Block) -> (complete :Bool); close (final :Bool); }
Aperçu de la durée de vie d’une connexion par les pairs:
- Ouvert (Open): les pairs envoient les registres jusqu’à ce qu’ils soient d’accord.
- Envoyé (Send): les pairs échangent want_lists et les blocs.
- Fermél (close): les pairs désactivent la connexion.
- Ignoré (ignored): spécial) un pair est ignoré (pour la durée d’un timeout) si la stratégie d’un nœud évite l’envoi.
Peer.open (NodeId, Ledger).
Lors de la connexion, le nœud initialise la connexion avec Le registre, soit stockée à partir d’une connexion dans le passé ou une nouvelle à zéro. Ensuite, envoie un message ouvert avec le registre au pair.
Lors de la réception d’un message Open (ouvert), un pair choisit d’activer la connexion. Si, selon le grand livre du destinataire, l’expéditeur n’est pas un agent de confiance (transmission inférieure à zéro ou dette impayée importante), le destinataire peut choisir d’ignorer la demande. Cela devrait être fait de manière probabiliste avec un timeout ignorer_cooldown, permettant de corriger les erreurs et de contrecarrer les attaquants.
Si vous activez la connexion, le récepteur initialise l’objet Peer (pair) avec la version locale du registre et définit l’horodatage last_seen. Ensuite, il compare le Ledger reçu avec le sien. S’ils correspondent exactement, les connexions seront ouverte. Sinon, le pair crée un nouveau livre mis à zéro et l’envoie.
Peer.send_want_list(WantList).
Lorsque la connexion est ouverte, les nœuds annoncent leur liste de diffusion à tous les correspondants connectés. Ceci est fait (a) lors de l’ouverture de la connexion, (b) après une temporisation périodique aléatoire, (c) après un changement dans want_list et (d) après la réception d’un nouveau bloc.
Lors de la réception d’une want_list, un nœud le stocke. Ensuite, il vérifie s’il possède l’un des blocs voulus. Si oui, il les envoie selon la stratégie BitSwap ci-dessus.
Peer.send_block(Block).
Envoyer un bloc est simple. Le noeud transmet simplement le bloc de données. Lors de la réception de toutes les données, le récepteur calcule la somme de contrôle Multihash pour vérifier qu’elle correspond à celle attendue et renvoie la confirmation.
Lors de la finalisation de la transmission correcte d’un bloc, le récepteur déplace le bloc de need_list à have_list, et le récepteur et l’expéditeur mettent à jour leurs ledgers pour refléter les octets supplémentaires transmis.
Si la vérification de transmission échoue, l’expéditeur est défectueux ou attaque le récepteur. Le destinataire est libre de refuser d’autres transactions. Notez que BitSwap s’attend à fonctionner sur un canal de transmission fiable, donc les erreurs de transmission (qui pourrait conduire à une pénalisation incorrecte d’un expéditeur honnête) devraient être interceptés avant que les données ne soient transmises à BitSwap.
Peer.close(Bool)
Le dernier paramètre à fermer indique si l’intention de démolir la connexion est celle de l’expéditeur ou non. Si faux, le destinataire peut choisir de rouvrir la connexion immédiatement. Cela évite les fermetures prématurées. La connexion des pairs doit être fermée sous deux conditions:
- Le délai d’expiration de silence_wait a expiré sans recevoir le message du pair (par défaut, BitSwap utilise 30 secondes). Le nœud émet Peer.close (false).
- le noeud est en cours de fermeture et BitSwap est en cours de fermeture. Dans ce cas, le nœud émet Peer.close (true).
Après un message de fermeture, le récepteur et l’expéditeur arrêtent la connexion, effaçant tout état stocké. Le registre peut être stocké pour le futur, s’il est utile de le faire.
Notez bien queLes messages non ouverts sur une connexion inactive doivent être ignorés. Dans le cas d’un message send_block, le destinataire peut vérifier si le bloc est nécessaire et correct, et si c’est le cas, l’utiliser. Quoi qu’il en soit, tous ces messages hors service déclenchent un message de fermeture (faux) de la part du destinataire pour forcer la réinitialisation de la connexion.
Objet Merkle DAG
DHT et BitSwap permettent à IPFS de former un système P2P massif pour stocker et distribuer les blocs d’une manière rapide et robuste. En plus de cela, IPFS construit un Merkle DAG, un graphe acyclique orienté où les liens entre objets sont des hachages cryptographiques des cibles intégrées dans les sources. C’est une généralisation de la structure de données Git. Les Merkle DAGs fournissent à l’IPFS de nombreuses propriétés utiles, notamment:
- Adressage du contenu: tout le contenu est identifié de manière unique par sa somme de contrôle multihash, y compris les liens.
- Résistance à l’altération: tout le contenu est vérifié avec itschecksum. Si les données sont altérées ou corrompues, l’IPFS le détecte.
- Déduplication: tous les objets qui contiennent exactement le même contenu sont égaux et ne sont stockés qu’une seule fois. Ceci est particulièrement utile avec les objets d’index, tels que les arbres git et les commits, ou les parties communes des données.
Le format de l’objet IPFS est:
type IPFSLink struct { Name string // name or alias of this link Hash Multihash // cryptographic hash of target Size int // total size of target } type IPFSObject struct { links []IPFSLink // array of links data []byte // opaque content data }
IPFS Merkle DAG est un moyen extrêmement flexible de stocker les données. Les seules exigences sont que les références d’objets doivent être (a) un contenu adressé, et (b) codé dans le format ci-dessus. IPFS accorde aux applications un contrôle complet sur le champ de données; Les applications peuvent utiliser n’importe quel format de données personnalisé qu’elles ont choisi, et que l’IPFS peut ne pas comprendre. La table de liens inobject séparée permet à IPFS de:
- Répertorie toutes les références d’objet dans un objet. Par exemple:
> ipfs ls /XLZ1625Jjn7SubMDgEyeaynFuR84ginqvzb XLYkgq61DYaQ8NhkcqyU7rLcnSa7dSHQ16x 189458 less XLHBNmRQ5sJJrdMPuu48pzeyTtRo39tNDR5 19441 script XLF4hwVHsVuZ78FZK6fozf8Jj9WEURMbCX4 5286 template <object multihash> <object size> <link name>
- Résolve les recherches de chemin de chaîne, telles que foo/ bar/ baz. Étant donné un objet, l’IPFS résout le premier composant path en un hachage dans la table de liens de l’objet, récupère ce second objet et se répète avec le composant suivant. Ainsi, les chemins de chaînes peuvent parcourir le Merkle DAG, quels que soient les formats de données.
- Résolve tous les objets référencés de manière récursive:
> ipfs refs --recursive \ /XLZ1625Jjn7SubMDgEyeaynFuR84ginqvzb XLLxhdgJcXzLbtsLRL1twCHA2NrURp4H38s XLYkgq61DYaQ8NhkcqyU7rLcnSa7dSHQ16x XLHBNmRQ5sJJrdMPuu48pzeyTtRo39tNDR5 XLWVQDqxo9Km9zLyquoC9gAP8CL1gWnHZ7z ...
Le champ des données brutes et la structure de liens commune sont les composants nécessaires pour construire les structures de données arbitraires sur l’IPFS. Bien qu’il soit facile de voir comment le modèle objet Git s’ajuste à ce DAG, considérez ces autres structures de données potentielles: (a) les magasins de valeurs-clés (b) les bases de données relationnelles traditionnelles (c) les données triples liées (d) systèmes de publication (e) plates-formes de communication liées (f) chaîne de blocs de crypto-monnaies. Ceux-ci peuvent tous être modélisés au-dessus de l’IPFS Merkle DAG, qui permet à n’importe lequel de ces systèmes d’utiliser l’IPFS comme protocole de transport pour les applications plus complexes.
Chemins (Paths)
Les objets IPFS peuvent être traversés avec une API de chemin de chaîne. Les chemins fonctionnent comme dans les systèmes de fichiers UNIX traditionnels et le Web. Les liens Merkle DAG permettent de le parcourir facilement. Notez que les chemins complets dans IPFS sont de la forme:
# format /ipfs/<hash-of-object>/<name-path-to-object> # example /ipfs/XLYkgq61DYaQ8NhkcqyU7rLcnSa7dSHQ16x/foo.txt
Le préfixe / ipfs permet le montage dans les systèmes existants à un point de montage standard sans conflit (les noms des points de montage sont bien sûr configurables). Le second composant de chemin (première à l’intérieur de IPFS) est la valeur de hachage d’un objet. C’est toujours le cas, car il n’y a pas de racine globale. Un objet racine aurait la tâche impossible de gérer la cohérence de millions d’objets dans un environnement distribué (et éventuellement déconnecté). Au lieu de cela, nous simulons la racine avec l’adressage de contenu. Tous les objets sont toujours accessibles via leur hash. Notez que cela signifie qu’étant donnés trois objets dans le chemin / bar / baz, le dernier objet sera accessible par tous les autres.
/ipfs/<hash-of-foo>/bar/baz /ipfs/<hash-of-bar>/baz /ipfs/<hash-of-baz_à $**ç_
Objets locaux
Les clients IPFS nécessitent un stockage local, un système externe sur lequel stocker et récupérer les données brutes locales pour les objets gérés par l’IPFS. Le type de stockage dépend du cas d’utilisation du noeud. Dans la plupart des cas, il s’agit simplement d’une partie de l’espace disque (soit géré par le système de fichiers natif, soit par un magasin de valeurs-clés tel que leveldb, soit directement par le client IPFS). Dans d’autres cas, par exemple des caches non persistants, ce stockage est juste une partie de RAM.
En fin de compte, tous les blocs disponibles dans IPFS se trouvent dans le stockage local de certains nœuds. Lorsque les utilisateurs demandent des objets, ils sont trouvés, téléchargés et stockés localement, au moins temporairement. Cela permet une recherche rapide pour une durée configurable par la suite.
Épinglage d’Objets
Les nœuds qui souhaitent assurer la survie d’objets particuliers peuvent le faire en épinglant les objets. Cela garantit que les objets sont conservés dans le stockage local du noeud. L’épinglage peut être effectué de manière récursive, afin de fixer tous les objets descendants liés. Tous les objets pointés sont ensuite stockés localement. Ceci est particulièrement utile pour conserver les fichiers, y compris les références. Cela fait également d’IPFS un Web où les liens sont permanents, et les objets peuvent assurer la survie des autres vers lesquels ils pointent.
Publication d’objets
L’IPFS est globalement distribué. Il est conçu pour permettre aux fichiers de millions d’utilisateurs de coexister ensemble. La DHT, avec l’adressage du hachage de contenu, permet de publier des objets de manière juste, sécurisée et entièrement distribuée. N’importe qui peut publier un objet en ajoutant simplement sa clé à la DHT, en s’ajoutant comme des pairs, et en donnant aux autres utilisateurs le chemin de l’objet. Notez que les objets sont essentiellement immuables, tout comme dans Git. Les nouvelles versions du hash différemment, sont de nouveaux objets. Le suivi des versions est le travail des objets de versionnement supplémentaires.
Cryptographie au niveau de l’objet
L’IPFS est équipé pour gérer les opérations cryptographiques au niveau de l’objet. Un objet chiffré ou signé est enveloppé dans un cadre spécial qui permet le chiffrement ou la vérification des octets bruts.
type EncryptedObject struct { Object []bytes // raw object data encrypted Tag []bytes // optional tag for encryption groups } type SignedObject struct { Object []bytes // raw object data signed Signature []bytes // hmac signature PublicKey []multihash // multihash identifying key }
Les opérations cryptographiques modifient le hachage de l’objet, définissant un objet différent. L’IPFS vérifie automatiquement les signatures et peut déchiffrer des données avec des clés spécifiées par l’utilisateur. Les liens d’objets cryptés sont également protégés, ce qui rend la traversée impossible sans clé de déchiffrement. Il est possible d’avoir un objet parent chiffré sous une clé, et un enfant sous un autre ou pas du tout. Cela sécurise les liens vers les objets partagés.
Les Dossiers
IPFS définit également un ensemble d’objets pour modéliser un système de fichiers versionné au-dessus du Meragle DAG. Ce modèle d’objet est similaire à celui de Git:
- bloc: un bloc de taille variable de données.
- liste: une collection de blocs ou d’autres listes.
- arbre: une collection de blocs, listes, ou d’autres arbres.
- commit: un instantané dans l’historique des versions d’un arbre.
J’espérais utiliser exactement les formats d’objets Git, mais je devais introduire certaines fonctionnalités utiles dans un système de fichiers distribué, à savoir: (a) les recherches de taille rapide (les tailles d’octets agrégées ont été ajoutées aux objets), (b) la déduplication des fichiers volumineux (ajout d’un objet liste), et (c) l’incorporation de commits dans les arbres. Cependant, les objets du fichier IPFS sont assez proches pour que la conversion entre les deux soit possible. En outre, un ensemble d’objets Git peut être introduit pour convertir sans perdre aucune information (autorisations de fichier UNIX, etc).
Objet de fichier: blob
L’objet blob contient une unité de données adressable et représente un fichier. Les blocs IPFS sont similaires aux blobs Git ou aux blocs de données du système de fichiers. Ils stockent les données des utilisateurs. Notez que les fichiers IPFS peuvent être représentés par des listes et des blobs. Les blobs n’ont pas de liens.
{ "data": "some data here", // blobs have no links }
Objet de fichier: liste
L’objet liste représente un fichier volumineux ou dédupliqué composé de plusieurs blobs IPFS concaténés ensemble. les listes contiennent une séquence ordonnée d’objets blob ou list. Dans un sens, la liste IPFS fonctionne comme un fichier système avec des blocs indirects. Puisque les listes peuvent contenir d’autres listes, des topologies incluant des listes liées et des arbres équilibrés sont possibles. Les graphes dirigés où le même noeud apparaît à plusieurs endroits permettent la déduplication dans le fichier. Bien sûr, les cycles ne sont pas possibles, telle qu’appliqués par hachage d’adressage.
{ "data": ["blob", "list", "blob"], // lists have an array of object types as data "links": [ { "hash": "XLYkgq61DYaQ8NhkcqyU7rLcnSa7dSHQ16x", "size": 189458 }, { "hash": "XLHBNmRQ5sJJrdMPuu48pzeyTtRo39tNDR5", "size": 19441 }, { "hash": "XLWVQDqxo9Km9zLyquoC9gAP8CL1gWnHZ7z", "size": 5286 } // lists have no names in links ] }
Objet de fichier: arbre
L’objet arbre dans IPFS est similaire à celui de Git: il représente un répertoire, une carte de noms en hachages. Les hachages référencent les blobs, les listes, les autres arbres ou les validations. Notez que le nom de chemin traditionnel est déjà implémenté par le Merkle DAG.
{ "data": ["blob", "list", "blob"], // trees have an array of object types as data "links": [ { "hash": "XLYkgq61DYaQ8NhkcqyU7rLcnSa7dSHQ16x", "name": "less", "size": 189458 }, { "hash": "XLHBNmRQ5sJJrdMPuu48pzeyTtRo39tNDR5", "name": "script", "size": 19441 }, { "hash": "XLWVQDqxo9Km9zLyquoC9gAP8CL1gWnHZ7z", "name": "template", "size": 5286 } // trees do have names ] }
Objet de fichier: commit
L’objet commit dans IPFS représente l’instantané dans l’historique des versions de n’importe quel objet. Il est similaire à Git, mais peut référencer n’importe quel type d’objet. Il pointe également vers les objets d’auteur.
{ "data": { "type": "tree", "date": "2014-09-20 12:44:06Z", "message": "This is a commit message." }, "links": [
> ipfs file-cat <ccc111-hash> --json { "data": { "type": "tree", "date": "2014-09-20 12:44:06Z", "message": "This is a commit message." }, "links": [ { "hash": "<ccc000-hash>", "name": "parent", "size": 25309 }, { "hash": "<ttt111-hash>", "name": "object", "size": 5198 }, { "hash": "<aaa111-hash>", "name": "author", "size": 109 } ] } > ipfs file-cat <ttt111-hash> --json { "data": ["tree", "tree", "blob"], "links": [ { "hash": "<ttt222-hash>", "name": "ttt222-name", "size": 1234 }, { "hash": "<ttt333-hash>", "name": "ttt333-name", "size": 3456 }, { "hash": "<bbb222-hash>", "name": "bbb222-name", "size": 22 } ] } > ipfs file-cat <bbb222-hash> --json { "data": "blob222 data", "links": [] }
{ "hash": "XLa1qMBKiSEEDhojb9FFZ4tEvLf7FEQdhdU", "name": "parent", "size": 25309 }, { "hash": "XLGw74KAy9junbh28x7ccWov9inu1Vo7pnX", "name": "object", "size": 5198 }, { "hash": "XLF2ipQ4jD3UdeX5xp1KBgeHRhemUtaA8Vm", "name": "author", "size": 109 } ] }
Contrôle de version
L’objet commit représente un instantané particulier dans l’historique des versions d’un objet. La comparaison des objets (et des enfants) de deux validations différentes révèle les différences entre deux versions du système de fichiers. Tant que la validation et les objets qu’elle référence sont accessibles, toutes les versions précédentes sont récupérables et l’historique complet des modifications du système de fichiers est accessible. Cela n’appartient pas au modèle d’objet Merkle DAG.
La pleine puissance des outils de contrôle de version Git est disponible pour les utilisateurs IPFS. Le modèle objet est compatible, bien qu’il ne soit pas le même. Il est possible de (a) construire une version des outils Git modifiée pour utiliser le graphe d’objets IPFS, (b) construire un système de fichiers FUSE monté qui monte un arbre IPFS en tant que repo Git, traduire le système de fichiers Git lire / écrire aux formats IPFS .
Chemins de système de fichiers
Comme nous l’avons vu dans la section Merkle DAG, les objets IPFS peuvent être traversés avec une API de chemin de chaîne. Les objets de fichiers IPFS sont conçus pour faciliter le montage d’IPFS sur un système de fichiers UNIX. Ils limitent les arbres à ne pas avoir de données, afin de les représenter comme des répertoires. Et les commits peuvent être représentés comme des répertoires ou entièrement cachés du système de fichiers.
Fractionnement des fichiers en listes et blob
L’un des principaux défis de la gestion des versions et de la distribution de fichiers volumineux consiste à trouver la bonne façon de les diviser en blocs indépendants. Plutôt que de supposer qu’il peut prendre la bonne décision pour chaque type de fichier, IPFS offre les alternatives suivantes:
- Utiliser Rabin Fingerprints (les empreintes de Rabin) comme dans LBFS (Low Bandwidth File System en français système de fichiers à faible bande passante) pour choisir les limites de bloc appropriées.
- Utiliser l’algorithme rsync rolling-checksum pour détecter les blocs qui ont changé entre les versions.
- Autoriser les utilisateurs à spécifier les fonctions de fractionnement de bloc fortement optimisées pour les fichiers spécifiques.
Performance de recherche de chemin
L’accès basé sur le chemin traverse le graphe d’objets. Récupérer chaque objet nécessite de rechercher sa clé dans la DHT, de se connecter à ses pairs et de récupérer ses blocs. Cela représente un surcoût considérable, en particulier lorsque vous recherchez des chemins comportant de nombreux composants. Ceci est atténué par:
- mise en cache de l’arbre: puisque tous les objets sont adressés par le hash, ils peuvent être mis en cache indéfiniment. De plus, les arbres ont tendance à être de petite taille, donc IPFS les priorise en les mettant en cache sur les blobs.
- arbres aplatis: pour n’importe quel arbre donné, un arbre spécial aplati peut être construit pour lister tous les objets accessibles depuis l’arbre. Les noms dans l’arbre aplati seraient vraiment des chemins partant de l’arbre original, avec des barres obliques
Par exemple, arbre aplati pour ttt111 ci-dessus:
{ "data": ["tree", "blob", "tree", "list", "blob" "blob"], "links": [ { "hash": "<ttt222-hash>", "size": 1234 "name": "ttt222-name" }, { "hash": "<bbb111-hash>", "size": 123, "name": "ttt222-name/bbb111-name" }, { "hash": "<ttt333-hash>", "size": 3456, "name": "ttt333-name" }, { "hash": "<lll111-hash>", "size": 587, "name": "ttt333-name/lll111-name"}, { "hash": "<bbb222-hash>", "size": 22, "name": "ttt333-name/lll111-name/bbb222-name" }, { "hash": "<bbb222-hash>", "size": 22 "name": "bbb222-name" } ] }
IPNS: Nomination et état Mutable
Jusqu’à présent, l’IPFS forme un échange de blocs pair-à-pair construisant un DAG d’objets adressé au contenu. Il sert à publier et à récupérer les objets immuables. Il peut même suivre l’historique des versions de ces objets. Cependant, il manque un composant critique: la nomination mutable. Sans cela, toute communication de nouveau contenu doit se faire hors bande, en envoyant des liens IPFS. Ce qui est requis est un moyen de récupérer l’état mutable sur le même chemin.
Cela vaut la peine de dire pourquoi nous avons travaillé dur pour construire un DAG Merkle immuable (si des données mutables sont nécessaires à la fin). Considérez les propriétés de IPFS qui échappent au DAG de Merkle: les objets peuvent être (a) récupérés via leur hash, (b) intégrité vérifiée, (c) liés à d’autres, et (d) mis en cache indéfiniment. Dans un sens:
Les objets sont permanents
Ce sont les propriétés critiques d’un système distribué à haute performance, où les données coûtent cher à traverser les liens réseau. L’adressage de contenu d’objet construit un web avec (a) des optimisations de bande passante significatives, (b) un service de contenu non fiable, (c) des liens permanents et (d) la possibilité de faire des sauvegardes permanentes complètes de tout objet et de ses références.
Le Merkle DAG, les objets à contenu immuable et les Nominations, pointeurs modifiables de Merkle DAG, instancient une dichotomie présente dans de nombreux systèmes distribués réussis. Ceux-ci incluent le système de contrôle de version de Git, avec ses objets immuables et références mutables; et Plan9, le successeur distribué d’UNIX, avec ses systèmes de fichiers Fossil et immuable Venti mutables. LBFS (Low Bandwidth File System en français système de fichiers à faible bande passante) Utilise également des index mutables et des blocs immuables.
Noms auto-certifiés
L’utilisation du schéma de dénomination de SFS nous donne un moyen de construire des noms autocertifiés, dans un espace de noms global assigné cryptographiquement, qui sont mutables. Le schéma IPFS est le suivant.
- Rappelons que dans IPFS
NodeId = hash(node.PubKey)
Noeud identifiant = hash(noeud.clé publique) - Nous attribuons à chaque utilisateur un espace de noms mutable à:
/ipns/<NodeId></li> - Un utilisateur peut publier un objet sur ce chemin Signé par sa clé privée, par exemple:/ipns/XLF2ipQ4jD3UdeX5xp1KBgeHRhemUtaA8Vm/
- Lorsque d’autres utilisateurs récupèrent l’objet, ils peuvent vérifier que la signature correspond à la clé publique et à l’identifiant NodeId. Cela vérifie l’authenticité de l’objet publié par l’utilisateur, en obtenant la réplique de l’état modifiable.
- Rappelons que dans IPFS
Notez les détails suivants:
- Le pré-fix séparé ipns (InterPlanetary Name Space) consiste à établir une distinction facilement reconnaissable entre les chemins mutables et immuables, aussi bien pour les programmes que pour les lecteurs humains.
- Parce que ce n’est pas un objet adressé par le contenu, la publication repose sur le seul système de distribution d’état modifiable dans IPFS, le système de routage. Le processus publie l’objet en tant qu’objet IPFS immuable normal, et publie son hachage sur le système de routage en tant que valeur de métadonnées: routing.setValue(NodeId, <ns-object-hash> )
- Tous les liens dans l’objet publié agissent en tant que sous-noms dans l’espace de noms: /ipns/XLF2ipQ4jD3UdeX5xp1KBgeHRhemUtaA8Vm/
/ipns/XLF2ipQ4jD3UdeX5xp1KBgeHRhemUtaA8Vm/docs
/ipns/XLF2ipQ4jD3UdeX5xp1KBgeHRhemUtaA8Vm/docs/ipfs - Il est conseillé de publier un objet commit, ou un autre objet avec un historique des versions, afin que les clients puissent trouver les anciens noms. Ceci est laissé en tant qu’option utilisateur, car ce n’est pas toujours souhaité. Notez bien qu’une fois publiié par l’utilisateur, Cet Objet ne pourra plus être publié une 2éme fois de la même manière.
Noms Humains
Alors que IPNS est en effet un moyen d’assigner et de réaffecter des noms, il n’est pas très convivial, car il expose les valeurs de hachage longues comme des noms, qui sont notoirement difficiles à retenir. Ceux-ci fonctionnent pour les URL, mais pas pour de nombreux types de transmission hors ligne. Ainsi, IPFS augmente la convivialité de IPNS avec les techniques suivantes:
Liens de pairs.
Encouragés par SFS, les utilisateurs peuvent lier les objets d’autres utilisateurs directement dans leurs propres objets (espace de noms, home, etc). Cela a l’avantage de créer également un réseau de confiance (et prend en charge l’ancien modèle d’autorité de certification):
#lien d’Alice vers Bob Bob
lien ipfs / <alice-pk-hash> / amis / bob / <bob-pk-hash>
#lien d’Eve vers Alice
lien ipfs / <eve-pk-hash / amis / alice / <alice-pk-hash>
# Eve a également accès à Bob
/ <eve-pk-hash / amis / alice / amis / bob
# accéder aux domaines certifiés Verisign
/<verisign-pk-hash>/foo.com
DNS TXT IPNS Enregistrement
Si / ipns / <domaine> est un nom de domaine valide, IPFS recherche les clés ipns dans ses enregistrements TXT DNS. IPFS interprète la valeur comme un hachage d’objet ou un autre chemin IPNS:
# cet enregistrement TXT DNS
ipfs.benet.ai. TXT “ipfs = XLF2ipQ4jD3U …”
# se comporte comme un lien symbolique
ln -s / ipns / XLF2ipQ4jD3U /ipns/fs.benet.ai
Identificateurs prononçables Proquint
Il y a toujours eu des schémas pour encoder le binaire en mots prononçables. IPNS prend en charge Proquint. Ainsi:
# cette phrase de recherche
/ ipns / dahih-dolij-sozuk-vosah-luvar-fuluh
# va se résoudre à correspondre
/ ipns / KhAwNprxYVxKqpDZ
Services de raccourcissement de noms
Les services sont destinés à surgir, cela fournira le raccourcissement du nom en tant que service, offrant leurs espaces de noms aux utilisateurs. Cela est similaire à ce que nous voyons aujourd’hui avec les DNS et les urls des sites web.
# L’utilisateur peut obtenir un lien de
/ipns/shorten.er/foobar
# Vers son propre espace de noms
/ ipns / XLF2ipQ4jD3UdeX5xp1KBgeHRhemUtaA8Vm
L’utilisation de l’IPFS
L’IPFS est conçu pour être utilisé de différentes façons. Voici quelques-unes de ses utilisations:
- En tant que système de fichiers global monté, sous / ipfs et / ipns.
- En tant que dossier de synchronisation personnel monté, il exécute automatiquement la version, la publication et la sauvegarde des écritures.
- En tant que fichier crypté ou système de partage de données.
- En tant que gestionnaire de paquets versionné pour tous les logiciels.
- En tant que système de fichiers racine d’une machine virtuelle.
- Comme un système de fichiers de démarrage d’une VM (sous un hyperviseur).
- En tant que base de données: les applications peuvent écrire directement dans le modèle de données Merkle DAG et obtenir toutes les versions, mises en cache et distributions fournies par IPFS.
- En tant que plate-forme de communication liée (et cryptée).
- En tant que CDN d’intégrité vérifié pour les fichiers volumineux (sans SSL).
- En tant que CDN chiffré.
- Sur les pages Web, en tant que CDN Web.
- Comme un nouveau site web permanent où les liens ne meurent pas.
Les implémentations IPFS ciblent:
- une bibliothèque IPFS à importer dans vos propres applications
- outils de ligne de commande pour manipuler les objets directement
- systèmes de fichiers montés, en utilisant les modules FUSE ou Kernel
Le Future De L’IPFS
Les idées qui sous-tendent l’IPFS sont le fruit de décennies de recherche réussie sur les systèmes distribués dans les universités et les logiciels libres. IPFS synthétise plusieurs des meilleures idées des systèmes les plus performants à ce jour. Mis à part BitSwap, qui est un protocole novateur, la principale contribution de l’IPFS est ce couplage de systèmes et la synthèse de conceptions.
L’IPFS est une vision ambitieuse de la nouvelle infrastructure Internet décentralisée, sur laquelle de nombreux types d’applications peuvent être construits. Au strict minimum, il peut être utilisé en tant que système de fichiers et espace de noms global, monté et versionné, ou en tant que système de partage de fichiers de nouvelle génération. À son meilleur, il pourrait pousser le Web vers de nouveaux horizons, où la publication d’informations précieuses n’impose pas l’hébergement à l’éditeur mais aux personnes intéressées, où les utilisateurs peuvent faire confiance au contenu qu’ils reçoivent sans faire confiance aux pairs d’où ils le reçoivent, et où les fichiers anciens mais importants ne disparaissent pas. L’IPFS est impatient de nous amener vers le Web permanent.
REMERCIEMENTS
L’IPFS est la synthèse de nombreuses idées et systèmes. Il serait impossible dd défier des objectifs aussi ambitieux sans se tenir debout sur les épaules de tels géants. Un remerciment special à Juan benet le concepteur Originaire de l’IPFS, remerciements personnels à David Dalrymple, Joe Zimmerman et Ali Yahya pour leurs longues discussions sur plusieurs de ces idées, en particulier: exposer le général Merkle DAG (David, Joe), le blocage de hash (David) et la protection s / kademlia sybill (David , Ali). Sans oublier David Mazieres, pour ses idées toujours brillantes.
Note:l’article précédent intitulé “IPFS, Système De Fichiers Interplanétaires – Introduction” et cet article sont inspirés de “IPFS – Content Addressed, Versioned, P2P File System(DRAFT 3) ” de Juan benet le concepteur de l’IPFS (en Anglais).