Système de fichiers interplanétaire - hachage trivial (identité), bloc DAG et tampons de protocole

Récemment, IPFS a ajouté la prise en charge d'un hachage trivial (identité) . Dans mon article, j'en parlerai et montrerai comment il peut être utilisé.


Permettez-moi de vous rappeler: InterPlanetary File System est un nouveau réseau de partage de fichiers décentralisé (serveur HTTP, Content Delivery Network ). J'ai commencé l'histoire à ce sujet dans l'article "Interplanetary File System IPFS" .

Habituellement, lors du hachage, en passant par une fonction de hachage, les données sont irréversiblement «compressées» et, par conséquent, un identifiant court est obtenu. Cet identifiant vous permet de retrouver des données sur le réseau et de vérifier leur intégrité.


Un hachage trivial est les données elles-mêmes. Les données ne changent en aucune façon et, par conséquent, la taille du "hachage" est égale à la taille des données.


Un hachage trivial remplit la même fonction que Data: URL . L'identifiant de contenu dans ce cas contient les données elles-mêmes au lieu d'un hachage. Cela vous permet d'imbriquer des blocs enfants dans le parent et de les rendre disponibles immédiatement après avoir reçu le parent. Vous pouvez également inclure des données de site directement dans l'enregistrement DNS.


Par exemple, encodez la chaîne de texte "Hello World" dans l' identifiant du contenu (CID) avec un hachage trivial.
image


Structure d'identification:


[ ][varint  CID][varint  ][varint ID ][varint  ][] 

Commençons par la fin.


[hachage]


Le hachage trivial dans notre cas est la chaîne elle-même. Traduisons-le en HEX .


 " " = 0x"D09F D180 D0B8 D0B2 D0B5 D182 20 D0BC D0B8 D180" 

Il s'agit du HEX de cette chaîne encodée en utf-8 . Mais pour que le navigateur sache avec certitude qu'il s'agit d'une ligne utf-8, ajoutez-la au début: 0xEFBBBF . Il s'agit d' un marqueur de séquence d'octets (BOM).


 0x"EFBBBF D09F D180 D0B8 D0B2 D0B5 D182 20 D0BC D0B8 D180" 

[longueur du hachage varint]


Maintenant, nous pouvons calculer la longueur du "hachage". Tous les deux caractères HEX sont un octet. Par conséquent, la chaîne résultante est longue de 22 octets. Dans HEX, ce sera 0x16 .


Ajoutez 0x16 au début de la ligne.


 0x"16 EFBBBF D09F D180 D0B8 D0B2 D0B5 D182 20 D0BC D0B8 D180" 

[id de hachage varint]


Maintenant, nous avons besoin de l'ID de hachage. Le hachage trivial ou l'identité dans la table de hachage a l'identifiant 0x00 .


Ajoutez 0x00 au début de la ligne.


 0x"00 16 EFBBBF D09F D180 D0B8 D0B2 D0B5 D182 20 D0BC D0B8 D180" 

C'est déjà une partie multi-hachage de l'identifiant, vous pouvez transcoder HEX en Base58 et le multi-hachage est prêt. Mais ipfs ne le reconnaît pas en dehors de l'identifiant de contenu (CID).


Continuons.


[type de contenu varint]


Regardez maintenant la table multicodec pour obtenir le type de contenu. Dans notre cas, il s'agit de données brutes et l'identifiant est 0x55 respectivement.


Ajoutez 0x55 au début de la ligne.


 0x"55 00 16 EFBBBF D09F D180 D0B8 D0B2 D0B5 D182 20 D0BC D0B8 D180" 

[version varint de CID]


Nous encodons le format de la première version de l'identifiant de contenu . Par conséquent, ajoutez 0x01.


Ajoutez 0x01 au début de la ligne.


 0x"01 55 00 16 EFBBBF D09F D180 D0B8 D0B2 D0B5 D182 20 D0BC D0B8 D180" 

Et donc nous sommes déjà à la ligne d'arrivée.


[préfixe de base]


Il indique quelle option de codage des données binaires en texte est utilisée.


HEX (F)


Nous pouvons utiliser le terme HEX directement en ajoutant le symbole "F" au début du préfixe de base HEX


 F01550016EFBBBFD09FD180D0B8D0B2D0B5D18220D0BCD0B8D180 

Nous avons obtenu un identifiant HEX pour le contenu qui contient la ligne utf-8: "Hello world"


Test: / ipfs / F01550016EFBBBFD09FD180D0B8D0B2D0B5D18220D0BCD0B8D180


Base58btc (z)


La base58btc sera donc plus courte


Nous traduisons notre chaîne HEX en base58btc. Vous pouvez utiliser le convertisseur en ligne .


 0x"01 55 00 16 EFBBBF D09F D180 D0B8 D0B2 D0B5 D182 20 D0BC D0B8 D180" = "3NDGAEgXCxbPucFFCQc9s5ScqZjqVFNr56P" (base58btc) 

Ajoutez le caractère de préfixe de base base58btc "z" au début de la ligne


 z3NDGAEgXCxbPucFFCQc9s5ScqZjqVFNr56P 

Nous avons obtenu en base58btc un identifiant de contenu qui contient une ligne utf-8: "Hello world"


Test: / ipfs / z3NDGAEgXCxbPucFFCQc9s5ScqZjqVFNr56P


Bloc DAG


Le texte est bon, mais pour encoder une page HTML, nous devons intégrer ses données dans le bloc d'annuaire DAG.


Voici notre HTML:


 <b><i><u> </u></i></b> 

De même, selon les instructions ci-dessus, nous obtenons l'identifiant de contenu dans base58btc pour ce texte:


 zeExnPvBXdTRwCBhfkJ1fHFDaXpdW4ghvQjfaCRHYxtQnd3H4w1MPbLczSqyCqVo 

Maintenant écrivez le fichier JSON:


 { "links": [{ "Cid": { "/": "zeExnPvBXdTRwCBhfkJ1fHFDaXpdW4ghvQjfaCRHYxtQnd3H4w1MPbLczSqyCqVo" }, "Name": "index.html" }], "data": "CAE=" } 

  1. Les "données" indiquent le type de bloc DAG - le répertoire.
  2. "liens" est un tableau de liens de fichiers.
  3. "Nom" est le nom du fichier, respectivement.
  4. "Cid" contient l'identifiant du contenu

ipfs dag put -f"protobuf" convertissez JSON en bloc DAG via IPFS.


J'ai un multihash: QmXXixn4rCzGguhxQPjXQ8Mr5rdqwZfJTKkeB6DfZLt8EZ


A ce stade, nous avons reçu un bloc dans lequel un répertoire avec un fichier inscrit dans le bloc.


Ensuite, en utilisant ce multicash, déchargez le bloc fini


 ipfs block get QmXXixn4rCzGguhxQPjXQ8Mr5rdqwZfJTKkeB6DfZLt8EZ > block.dag 

Nous traduisons le contenu de block.dag en HEX:


 0x"123F0A2F0155002BEFBBBF3C623E3C693E3C753ED09FD180D0B8D0B2D0B5D18220D0BCD0B8D1803C2F753E3C2F693E3C2F623E120A696E6465782E68746D6C18000A020801" 

Ajouter:


  1. Version CID (0x01)
  2. Type de contenu DAG (0x70)
  3. hachage trivial (0x00)
  4. taille des données 69 octets (0x45)

 0x"01 70 00 45 123F0A2F0155002BEFBBBF3C623E3C693E3C753ED09FD180D0B8D0B2D0B5D18220D0BCD0B8D1803C2F753E3C2F693E3C2F623E120A696E6465782E68746D6C18000A020801" 

Convertissez en Base58btc et ajoutez le préfixe "z"


 z6S3Z3W1zuRxio8AJC41jRTdyU9pZWnU6sNbvyGyypEdD8JVNdW42ZmGYWKWGbVDELLvJNWcMspaZMUPZKt7JQmhdyXCqq7j37GL 

Ainsi, nous avons obtenu un identifiant de contenu avec un répertoire dans lequel la page html index.html avec le texte "Hello World".


Test: / ipfs / z6S3Z3W1zuRxio8AJC41jRTdyU9pZWnU6sNbvyGyypEdD8JVNdW42ZmGYWKWGbVDELLvJNWcMspaZMUPZKt7JQmhdyXCqqjj37gL


De plus, ce hachage peut également être intégré dans un autre bloc ou enregistré dans l'enregistrement DNS dnslink. Ainsi, dans un bloc, vous pouvez adapter un petit site simple.


Tampons de bloc et de protocole DAG


Le bloc DAG peut également être assemblé manuellement. Un bloc DAG correspond aux données des tampons de protocole . La couche supérieure est merkledag.proto qui a unixfs.proto dans Data.


Tampons de protocole


Tout protobuffer commence par l'identifiant du champ varint. Souvent, un identifiant occupe un octet car sa valeur totale est inférieure à 0x80. Dans notre cas, le premier octet est 0x12. Les 3 bits inférieurs de ce champ sont de type. Le reste est l'ID spécifié dans le fichier proto.


Délimité par la longueur

Nous décryptons l'identifiant:


 0x12 & 0x07 = 2 (: Length-delimited) 0x12 >> 3 = 2 (ID: 2) 

Délimité par la longueur signifie que varint est suivi de la taille du champ en octets et de son contenu directement. Ce type est utilisé à la fois pour diverses structures imbriquées et des données brutes (chaîne, octets, messages incorporés, champs répétés compressés). Ce que le fichier proto y définit déjà.


Varint

Déchiffrer l'identifiant d'un autre type:


 0x18 & 0x07 = 0 (: Varint) 0x12 >> 3 = 3 (ID: 3) 

Varint signifie que suit immédiatement la valeur de varint. Ce conteneur est utilisé pour écrire de nombreux types de valeurs (int32, int64, uint32, uint64, sint32, sint64, bool, enum). Ce qui définit également le fichier proto.


Nous analyserons block.dag que nous avons traduit en HEX ci-dessus


Pour analyser un bloc, vous pouvez utiliser un site qui analysera automatiquement tout tampon de protocole sans utiliser de fichiers proto.


 0x"123F0A2F0155002BEFBBBF3C623E3C693E3C753ED09FD180D0B8D0B2D0B5D18220D0BCD0B8D1803C2F753E3C2F693E3C2F623E120A696E6465782E68746D6C18000A020801" 

Nous démontons le bloc et mappons les identifiants des fichiers proto.


merkledag.proto
 // An IPFS MerkleDAG Link message PBLink { // multihash of the target object optional bytes Hash = 1; // utf string name. should be unique per object optional string Name = 2; // cumulative size of target object optional uint64 Tsize = 3; } // An IPFS MerkleDAG Node message PBNode { // refs to other objects repeated PBLink Links = 2; // opaque user data optional bytes Data = 1; } 

unixfs.proto
 message Data { enum DataType { Raw = 0; Directory = 1; File = 2; Metadata = 3; Symlink = 4; HAMTShard = 5; } required DataType Type = 1; optional bytes Data = 2; optional uint64 filesize = 3; repeated uint64 blocksizes = 4; optional uint64 hashType = 5; optional uint64 fanout = 6; } 

 12 (: 2 (Length-delimited). ID: 2 (PBLink PBNode.Links (merkledag.proto))) 3F (: 63 ) 0A (: 2 (Length-delimited). ID: 1 (PBLink.Hash)) 2F (: 47 ) 01 55 00 2B (CIDv1 Raw Identity 43 ) EFBBBF3C623E3C693E3C753ED09FD180D0B8D0B2D0B5D18220D0BCD0B8D1803C2F753E3C2F693E3C2F623E = "<b><i><u> </u></i></b>" 12 (: 2 (Length-delimited). ID: 2 (PBLink.Name)) 0A (: 10 ) 696E6465782E68746D6C = "index.html" 18 (: 0 (Varint). ID: 3 (PBLink.Size)) 00 (: 0) 0A (: 2 (Length-delimited). ID: 1 (PBNode.Data = Data (unixfs.proto))) 02 (: 2 ) 08 (: 0 (Varint). ID: 1 (Data.Type)) 01 (1 == Data.DataType.Directory) 

Par conséquent, un bloc avec deux fichiers ressemblera à ceci:


 12 (: 2 (Length-delimited). ID: 2 (PBLink PBNode.Links (merkledag.proto))) 3B (: 59 ) 0A (: 2 (Length-delimited). ID: 1 (PBLink.Hash)) 2F (: 47 ) 01 55 00 2B (CIDv1 Raw Identity 43 ) EFBBBF3C623E3C693E3C753ED09FD180D0B8D0B2D0B5D18220D0BCD0B8D1803C2F753E3C2F693E3C2F623E = "<b><i><u> </u></i></b>" 12 (: 2 (Length-delimited). ID: 2 (PBLink.Name)) 06 (: 6 ) 312E68746D6C = "1.html" 18 (: 0 (Varint). ID: 3 (PBLink.Size)) 00 (: 0) 12 (: 2 (Length-delimited). ID: 2 (PBLink PBNode.Links)) 3B (: 59 ) 0A (: 2 (Length-delimited). ID: 1 (PBLink.Hash)) 2F (: 47 ) 01 55 00 2B (CIDv1 Raw Identity 43 ) EFBBBF3C623E3C693E3C753ED09FD180D0B8D0B2D0B5D18220D0BCD0B8D1803C2F753E3C2F693E3C2F623E = "<b><i><u> </u></i></b>" 12 (: 2 (Length-delimited). ID: 2 (PBLink.Name)) 06 (: 6 ) 322E68746D6C = "2.html" 18 (: 0 (Varint). ID: 3 (PBLink.Size)) 00 (: 0) 0A (: 2 (Length-delimited). ID: 1 (PBNode.Data = Data(unixfs.proto))) 02 (: 2 ) 08 (: 0 (Varint). ID: 1 (Data.Type)) 01 (1 == Data.DataType.Directory) 

En d'autres termes, le champ PBNode.Links (0x12) est répété autant de fois que le nombre de fichiers à placer dans le bloc.


Pour vérifier, ajoutez au début de "F 01 70 00" (Identité HEX CIDv1 DAG) et la taille du bloc DAG "7E" (126 octets)


 F 01 70 00 7E 12 3B 0A 2F 01 55 00 2B EFBBBF3C623E3C693E3C753ED09FD180D0B8D0B2D0B5D18220D0BCD0B8D1803C2F753E3C2F693E3C2F623E 12 06 312E68746D6C 18 00 12 3B 0A 2F 01 55 00 2B EFBBBF3C623E3C693E3C753ED09FD180D0B8D0B2D0B5D18220D0BCD0B8D1803C2F753E3C2F693E3C2F623E 12 06 322E68746D6C 18 00 0A 02 08 01 

Vérifier: / ipfs / F0170007E123B0A2F0155002BEFBBBF3C623E3C693E3C753ED09FD180D0B8D0B2D0B5D18220D0BCD0B8D1803C2F753E3C2F693E3C2F623E1206312E68746D6C1800123B0A2F0155002BEFBBBF3C623E3C693E3C753ED09FD180D0B8D0B2D0B5D18220D0BCD0B8D1803C2F753E3C2F693E3C2F623E1206322E68746D6C18000A020801


Conclusion


J'espère avoir donné suffisamment d'informations pour qu'il soit possible d'implémenter la création de blocs et d'identifiants.

Source: https://habr.com/ru/post/fr423073/


All Articles