Recentemente, o IPFS adicionou suporte para um hash trivial (identidade) . No meu artigo, vou falar sobre isso e mostrar como ele pode ser usado.
Deixe-me lembrá-lo: O InterPlanetary File System é uma nova rede descentralizada de compartilhamento de arquivos (servidor HTTP, rede de entrega de conteúdo ). Comecei a história sobre isso no artigo "Sistema de arquivos interplanetário IPFS" .
Geralmente, ao fazer o hash, passando por uma função de hash, os dados são irreversivelmente "compactados" e, como resultado, um pequeno identificador é obtido. Esse identificador permite encontrar dados na rede e verificar sua integridade.
Um hash trivial são os próprios dados. Os dados não mudam de forma alguma e, portanto, o tamanho do "hash" é igual ao tamanho dos dados.
Um hash trivial executa a mesma função que Data: URL . O identificador de conteúdo nesse caso contém os próprios dados em vez de um hash. Isso permite aninhar blocos filhos no pai, disponibilizando-os imediatamente após o recebimento do pai. Você também pode incluir dados do site diretamente no registro DNS.
Por exemplo, codifique a sequência de texto "Hello World" no identificador do conteúdo (CID) com um hash trivial.

Estrutura de identificação:
[ ][varint CID][varint ][varint ID ][varint ][]
Vamos começar do fim.
[hash]
O hash trivial no nosso caso é a própria string. Vamos traduzi-lo para HEX .
" " = 0x"D09F D180 D0B8 D0B2 D0B5 D182 20 D0BC D0B8 D180"
Este é o HEX dessa sequência codificada utf-8 . Mas, para que o navegador tenha certeza de que essa é uma linha utf-8, adicione-a no começo: 0xEFBBBF
. Este é um marcador de sequência de bytes (BOM).
0x"EFBBBF D09F D180 D0B8 D0B2 D0B5 D182 20 D0BC D0B8 D180"
[comprimento do hash varint]
Agora podemos calcular o comprimento do "hash". Cada dois caracteres HEX são um byte. Por conseguinte, a cadeia resultante tem 22 bytes. No HEX, será 0x16
.
Adicione 0x16
ao início da linha.
0x"16 EFBBBF D09F D180 D0B8 D0B2 D0B5 D182 20 D0BC D0B8 D180"
[varint hash id]
Agora precisamos do hash id. O hash ou identidade trivial na tabela de hash tem o identificador 0x00
.
Adicione 0x00
ao início da linha.
0x"00 16 EFBBBF D09F D180 D0B8 D0B2 D0B5 D182 20 D0BC D0B8 D180"
Esta já é uma parte com múltiplos hash do identificador, você pode transcodificar HEX para Base58 e o multi-hash está pronto. Mas o ipfs não o reconhece fora do identificador de conteúdo (CID).
Vamos seguir em frente.
[tipo de conteúdo varint]
Agora observe a tabela multicodec para obter o tipo de conteúdo. No nosso caso, são dados brutos e o identificador é 0x55
respectivamente.
Adicione 0x55
ao início da linha.
0x"55 00 16 EFBBBF D09F D180 D0B8 D0B2 D0B5 D182 20 D0BC D0B8 D180"
[versão varint do CID]
Codificamos o formato da primeira versão do identificador de conteúdo . Portanto, adicione 0x01.
Adicione 0x01
ao início da linha.
0x"01 55 00 16 EFBBBF D09F D180 D0B8 D0B2 D0B5 D182 20 D0BC D0B8 D180"
E assim já estamos na linha de chegada.
[prefixo base]
Indica qual opção de codificação de dados binários para texto é usada.
HEX (F)
Podemos usar o termo HEX diretamente adicionando o símbolo "F" no início do prefixo base HEX
F01550016EFBBBFD09FD180D0B8D0B2D0B5D18220D0BCD0B8D180
Temos um identificador HEX para o conteúdo que contém a linha utf-8: "Hello world"
Teste: / ipfs / F01550016EFBBBFD09FD180D0B8D0B2D0B5D18220D0BCD0B8D180
Base58btc (z)
Base58btc será mais curto, portanto
Traduzimos nossa string HEX para base58btc. Você pode usar o conversor online .
0x"01 55 00 16 EFBBBF D09F D180 D0B8 D0B2 D0B5 D182 20 D0BC D0B8 D180" = "3NDGAEgXCxbPucFFCQc9s5ScqZjqVFNr56P" (base58btc)
Adicione o caractere de prefixo base base58btc "z" ao início da linha
z3NDGAEgXCxbPucFFCQc9s5ScqZjqVFNr56P
Temos o base58btc, um identificador de conteúdo que contém uma linha utf-8: "Hello world"
Teste: / ipfs / z3NDGAEgXCxbPucFFCQc9s5ScqZjqVFNr56P
Bloco DAG
O texto é bom, mas para codificar uma página HTML, precisamos incorporar seus dados no bloco de diretório do DAG.
Aqui está o nosso HTML:
<b><i><u> </u></i></b>
Da mesma forma, de acordo com as instruções acima, obtemos o identificador de conteúdo em base58btc para este texto:
zeExnPvBXdTRwCBhfkJ1fHFDaXpdW4ghvQjfaCRHYxtQnd3H4w1MPbLczSqyCqVo
Agora escreva o arquivo JSON:
{ "links": [{ "Cid": { "/": "zeExnPvBXdTRwCBhfkJ1fHFDaXpdW4ghvQjfaCRHYxtQnd3H4w1MPbLczSqyCqVo" }, "Name": "index.html" }], "data": "CAE=" }
- Os "dados" indicam o tipo de bloco DAG - o diretório.
- "links" é uma matriz de links de arquivos.
- "Nome" é o nome do arquivo, respectivamente.
- "Cid" contém o identificador de conteúdo
ipfs dag put -f"protobuf"
converta JSON em bloco DAG via IPFS.
Eu tenho um multihash: QmXXixn4rCzGguhxQPjXQ8Mr5rdqwZfJTKkeB6DfZLt8EZ
Nesse estágio, recebemos um bloco no qual um diretório com um arquivo inscrito no bloco.
Em seguida, usando essa multicash, descarregue o bloco concluído
ipfs block get QmXXixn4rCzGguhxQPjXQ8Mr5rdqwZfJTKkeB6DfZLt8EZ > block.dag
Traduzimos o conteúdo de block.dag para HEX:
0x"123F0A2F0155002BEFBBBF3C623E3C693E3C753ED09FD180D0B8D0B2D0B5D18220D0BCD0B8D1803C2F753E3C2F693E3C2F623E120A696E6465782E68746D6C18000A020801"
Adicionar:
- Versão CID (0x01)
- Tipo de conteúdo DAG (0x70)
- hash trivial (0x00)
- tamanho dos dados 69 bytes (0x45)
0x"01 70 00 45 123F0A2F0155002BEFBBBF3C623E3C693E3C753ED09FD180D0B8D0B2D0B5D18220D0BCD0B8D1803C2F753E3C2F693E3C2F623E120A696E6465782E68746D6C18000A020801"
Converta em Base58btc e adicione o prefixo "z"
z6S3Z3W1zuRxio8AJC41jRTdyU9pZWnU6sNbvyGyypEdD8JVNdW42ZmGYWKWGbVDELLvJNWcMspaZMUPZKt7JQmhdyXCqq7j37GL
Assim, obtivemos um identificador de conteúdo com um diretório no qual a página html index.html com o texto "Hello World".
Teste: / ipfs / z6S3Z3W1zuRxio8AJC41jRTdyU9pZWnU6sNbvyGyypEdD8JVNdW42ZmGYWKWGbVDELLvJNWcMspaZMUPZKt7JQmhdyXCqqjj37gL
Além disso, esse hash também pode ser incorporado em outro bloco ou gravado no registro DNS DNS Link. Assim, em um bloco, você pode ajustar um site simples e pequeno.
Buffers de protocolo e bloco DAG
O bloco DAG também pode ser montado manualmente. Um bloco DAG são dados de buffers de protocolo . A camada superior é merkledag.proto, que possui unixfs.proto em Dados.
Buffers de protocolo
Qualquer protobuffer começa com o identificador de campo varint. Geralmente, um identificador ocupa um byte, pois seu valor total é menor que 0x80. No nosso caso, o primeiro byte é 0x12. Os 3 bits inferiores deste campo são do tipo O restante é o ID especificado no arquivo proto.
Delimitado por comprimento
Descriptografamos o identificador:
0x12 & 0x07 = 2 (: Length-delimited) 0x12 >> 3 = 2 (ID: 2)
Delimitado por comprimento significa que varint é seguido pelo tamanho do campo em bytes e seu conteúdo diretamente. Esse tipo é usado para várias estruturas aninhadas e dados brutos (sequência, bytes, mensagens incorporadas, campos repetidos compactados). O que o arquivo proto já define nele.
Varint
Decifre o identificador de outro tipo:
0x18 & 0x07 = 0 (: Varint) 0x12 >> 3 = 3 (ID: 3)
Varint significa que segue imediatamente o valor em varint. Este contêiner é usado para escrever muitos tipos de valores (int32, int64, uint32, uint64, sint32, sint64, bool, enum). Que também define o arquivo proto.
Vamos analisar o block.dag que traduzimos para o HEX acima
Para analisar um bloco, você pode usar um site que analise automaticamente qualquer Buffer de Protocolo sem usar arquivos proto.
0x"123F0A2F0155002BEFBBBF3C623E3C693E3C753ED09FD180D0B8D0B2D0B5D18220D0BCD0B8D1803C2F753E3C2F693E3C2F623E120A696E6465782E68746D6C18000A020801"
Desmontamos o bloco e mapeamos os identificadores dos arquivos 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)
Assim, um bloco com dois arquivos terá a seguinte aparência:
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)
Ou seja, o campo PBNode.Links (0x12) é repetido tantas vezes quanto o número de arquivos a serem colocados no bloco.
Para verificar, adicione no início de "F 01 70 00" (HEX CIDv1 DAG Identity) e o tamanho do bloco DAG "7E" (126 bytes)
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
Confira: / IPFs / F0170007E123B0A2F0155002BEFBBBF3C623E3C693E3C753ED09FD180D0B8D0B2D0B5D18220D0BCD0B8D1803C2F753E3C2F693E3C2F623E1206312E68746D6C1800123B0A2F0155002BEFBBBF3C623E3C693E3C753ED09FD180D0B8D0B2D0B5D18220D0BCD0B8D1803C2F753E3C2F693E3C2F623E1206322E68746D6C18000A020801
Conclusão
Espero ter fornecido informações suficientes para que seja possível implementar a criação de blocos e identificadores.