DEV Community

Pedro Pietroluongo
Pedro Pietroluongo

Posted on

O que é IPFS

Este post abre a série IPFS com o Nabu. IPFS significa InterPlanetary File System. O assunto é o endereço do conteúdo: um bloco se chama pelo hash dos próprios bytes.

A proposta

A proposta do IPFS é trocar o "onde" pelo "o quê". Um URL (Uniform Resource Locator) da web diz em que servidor e em que caminho buscar um arquivo. Se o servidor sai do ar, ou se alguém troca o arquivo e mantém o caminho, o URL continua igual e o conteúdo muda. Quem recebe os bytes precisa confiar em quem os enviou.

O IPFS propõe o contrário. O nome do dado é uma função dos bytes. Quem recebe calcula a função de novo. Se o resultado bate com o nome pedido, os bytes são aqueles, qualquer que seja o par que os entregou.

A Demonstração

Pegue a frase olá. Os bytes UTF-8 passam por SHA-256 (Secure Hash Algorithm, 256 bits), uma função que espalha qualquer entrada num número de tamanho fixo. Um byte diferente muda o número. O mesmo texto produz sempre o mesmo número. Esse número, mais um rótulo de como ler os bytes, vira o CID (Content Identifier, identificador de conteúdo).

Na prática os dados são partidos em blocos. Cada bloco ganha um CID. Um bloco pode conter links para outros blocos, também na forma de CIDs. O conjunto forma um DAG (Directed Acyclic Graph, grafo dirigido sem ciclos): as setas saem de um bloco para os filhos, e não há caminho que volte ao início. A raiz tem o seu próprio CID. Pedir a raiz e seguir os links reconstrói o conjunto.

Um CID versão 1 junta três escolhas. A versão diz qual é o formato do identificador. O codec diz como os bytes estão organizados: raw são bytes opacos, dag-cbor é um mapa CBOR (Concise Binary Object Representation, um formato binário compacto) com links, dag-pb é o protobuf usado pelos arquivos clássicos do IPFS. Essas formas de organizar bytes com links fazem parte do IPLD (InterPlanetary Linked Data). O multihash diz qual função de hash foi usada e traz o digest. Por isso os mesmos bytes com codecs diferentes têm CIDs diferentes. O hash sozinho identifica os bytes. O CID identifica os bytes mais a forma de lê-los.

O Nabu guarda e troca esses blocos. Um caminho de arquivo Unix fica para a aplicação que monta o DAG por cima.

flowchart LR
  bytes[bytes] --> hash[sha256]
  hash --> cid[cidV1]
  cid --> link[linksInsideOtherBlocks]

No Nabu

HashedBlock, em src/main/java/org/peergos/HashedBlock.java, é o par que a rede devolve: o CID e os bytes.

public class HashedBlock {
    public final Cid hash;
    public final byte[] block;
}
Enter fullscreen mode Exit fullscreen mode

Quem grava um bloco calcula o CID. Não há uma tabela à parte de "nome para bytes". FileBlockstore.put faz a conta com CID versão 1 e SHA-256:

public CompletableFuture<Cid> put(byte[] block, Cid.Codec codec) {
    Cid cid = new Cid(1, codec, Multihash.Type.sha2_256, Hash.sha256(block));
Enter fullscreen mode Exit fullscreen mode

O primeiro argumento, 1, é a versão do CID. codec vem de quem chama: a API HTTP pede o nome IPLD em format e traduz com Cid.Codec.lookupIPLDName. Multihash.Type.sha2_256 escolhe a função. Hash.sha256(block) é o digest. Os bytes iguais com Raw e com DagCbor produzem CIDs diferentes, e os dois podem coexistir no mesmo store.

A interface Blockstore oferece has(Cid), get(Cid), put(byte[], Codec) e rm(Cid). has responde se a cópia local existe. get devolve Optional<byte[]>, vazio quando o CID não está aqui. put devolve o CID calculado, não um caminho. rm apaga essa cópia local. O conteúdo com o mesmo CID continua válido em qualquer outro par que ainda o tenha.

EmbeddedIpfs.getBlocks aplica a regra na hora de buscar. Para cada Want (o pedido: um CID e, se houver, um segredo de autorização), o método pergunta blockstore.has. O que já está local entra numa lista e é lido com blockstore.get. Se o has disse sim e o get veio vazio, ou se o get lançou, o pedido volta para a lista remota. Se essa lista termina vazia, o método devolve só o que achou no disco. Se sobra pedido e não há BlockService, lança Blocks not found locally. Com o serviço presente, que no nó completo é o Bitswap, concatena os blocos locais com os que a rede devolver.

O que fica de fora aqui: o Nabu não implementa o sistema de arquivos FUSE (Filesystem in Userspace) do Kubo, nem ipfs add de um diretório. A API HTTP cobre operações de bloco, refs locais, um pedaço da DHT (Distributed Hash Table, a tabela que aponta quem tem o CID) e a leitura IPNS (InterPlanetary Name System, o nome mutável). Quem quiser um diretório endereçado por conteúdo monta os blocos e os links na aplicação.

Nesta série

O anterior é A série IPFS com o Nabu. O próximo é Identidade e endereços.

Top comments (0)