NIP-01

O protocolo aberto mais simples que é capaz de criar uma rede "social" global resistente à censura de uma vez por todas. Ele não depende de nenhum servidor central confiável, portanto, é resiliente; é baseado em chaves e assinaturas criptográficas, por isso é inviolável; não depende de técnicas P2P e, portanto, funciona. Como funciona: É uma ideia muito simples: cada pessoa pode publicar suas anotações em vários relés (que são apenas servidores simples), e as pessoas que os seguem podem se conectar a esses relés e buscar as notas. O protocolo apenas define as mensagens que podem ser enviadas entre clientes e retransmissões para publicar e buscar o conteúdo desejado.
NIP-01

Descrição básica do protocolo

rascunho · obrigatório

Este NIP define o protocolo básico do Nostr, que todos os clientes e relays devem implementar. Novos NIPs podem adicionar campos, mensagens e funcionalidades opcionais ou obrigatórias às estruturas e fluxos descritos aqui.

Analogia: imagine que o Nostr é uma cidade de cartas 📬, onde cada pessoa escreve cartas (eventos) e envia para caixas postais (relays). Para que todo mundo entenda, é preciso seguir as mesmas regras.


Eventos e assinaturas 🔑

Cada usuário possui um par de chaves criptográficas:

  • Chave privada → segredo do autor da carta (assinatura).
  • Chave pública → endereço público para receber mensagens.

No Nostr, o único tipo de objeto é o evento.

Estrutura de um evento 📝

{
  "id": "<hash sha256 do evento>",
  "pubkey": "<chave pública do autor>",
  "created_at": 1700000000,
  "kind": 1,
  "tags": [],
  "content": "Olá Nostr!",
  "sig": "<assinatura criptográfica>"
}

Campos explicados:

  • id: identidade única do evento, gerada pelo hash. 🔹 Exemplo: cada carta recebe um número de registro único.
  • pubkey: chave pública do autor. 🔹 Como colocar o nome e endereço no envelope.
  • created_at: timestamp Unix do evento. 🔹 Que horas a carta foi escrita.
  • kind: tipo do evento. 🔹 Ex.: mensagem, foto, perfil.
  • tags: metadados estruturados. 🔹 Etiquetas que ajudam a organizar cartas.
  • content: conteúdo do evento. 🔹 A mensagem escrita.
  • sig: assinatura digital do autor. 🔹 Prova de que foi realmente você que escreveu.

Como o id do evento é gerado 🧩

O id é o SHA-256 da serialização JSON UTF-8 do evento:

[
  0,
  "<pubkey>",
  1700000000,
  1,
  [],
  "Olá Nostr!"
]

Regras obrigatórias:

  • UTF-8 para codificação

  • Sem espaços ou quebras de linha

  • Caracteres especiais escapados:

    • \n → quebra de linha
    • \" → aspas
    • \\ → barra invertida
    • \t, \r, \b, \f

Analogia: o id é como colocar a carta em uma máquina que transforma cada letra em números e letras únicos. Qualquer mudança, o número muda.


Tags 🏷️

As tags são arrays de strings que conectam ou descrevem eventos.

Exemplo

"tags": [
  ["e", "ID_DE_OUTRA_CARTA"],
  ["p", "CHAVE_PUBLICA_DE_OUTRO_USUARIO"],
  ["alt", "resposta"]
]
  • e → conecta a outro evento (resposta ou thread)
  • p → menciona outro usuário
  • alt → etiqueta personalizada

Analogia: como etiquetas coloridas em cartas que indicam relações.


Tags padronizadas

  • e → evento relacionado:

    ["e", "<id de outro evento>", "<relay opcional>", "<pubkey opcional>"]
    
  • p → referência a outro usuário:

    ["p", "<pubkey>", "<relay opcional>"]
    
  • a → eventos substituíveis ou endereçáveis:

    ["a", "<kind>:<pubkey>:<d>", "<relay opcional>"]
    

Analogia:

  • e → “essa carta responde aquela carta”
  • p → “falo com João”
  • a → “essa carta pode ser atualizada ou acessada com código especial”

Kinds (tipos de eventos) 📂

O kind define como interpretar o evento.

Kind 0 → Metadados do usuário

{
  "kind": 0,
  "content": "{\"name\":\"Alice\",\"about\":\"Desenvolvedora\",\"picture\":\"https://exemplo.com/avatar.png\"}"
}

🔹 Analogia: kind 0 é como preencher um crachá: nome, sobre você e foto.

Faixas de kinds

Faixa Tipo Analogia
1, 2, 4–44, 1000–9999 Regulares cartas normais guardadas para sempre
0, 3, 10000–19999 Substituíveis cartazes que podem ser atualizados
20000–29999 Efêmeros bilhetes que desaparecem
30000–39999 Endereçáveis mensagens secretas com código

⚠️ Se dois eventos substituíveis tiverem o mesmo timestamp, vence o menor id.


Comunicação cliente ↔ relay 🌐

Relays são caixas postais que recebem e enviam eventos. O cliente abre uma conexão WebSocket por relay e envia/recebe eventos.


Mensagens do cliente para relay

  1. Enviar evento
["EVENT", { ...evento... }]

Analogia: Alice coloca a carta na caixa postal.

  1. Criar assinatura (REQ)
["REQ", "sub1", {
  "kinds": [1],
  "authors": ["<pubkey>"],
  "limit": 10
}]

Analogia: Alice pede as últimas 10 cartas de Bob.

  1. Encerrar assinatura
["CLOSE", "sub1"]

Analogia: Alice diz “não quero mais receber cartas de Bob”.


Filtros 🔍

{
  "ids": ["<event_id>"],
  "authors": ["<pubkey>"],
  "kinds": [1],
  "#e": ["<event_id>"],
  "since": 1700000000,
  "until": 1700001000,
  "limit": 50
}
  • Dentro de um filtro → todas as regras devem ser verdadeiras (AND)
  • Entre filtros → basta uma regra ser verdadeira (OR)

Analogia: escolher apenas cartas que atendem a certos critérios, como “somente cartas do João” e “somente as últimas 5 cartas”.


Mensagens do relay para o cliente

  1. Enviar evento
["EVENT", "sub1", { ...evento... }]
  1. Confirmação de envio (OK)
["OK", "<event_id>", true, ""]

Ou erro:

["OK", "<event_id>", false, "rate-limited: escrevendo rápido demais"]
  1. Fim dos eventos armazenados (EOSE)
["EOSE", "sub1"]
  1. Encerramento pelo relay (CLOSED)
["CLOSED", "sub1", "error: filtro não suportado"]

Prefixos padronizados de erro ⚠️

  • duplicate → carta repetida
  • pow → carta difícil de enviar
  • blocked → carta bloqueada
  • rate-limited → escrevendo rápido demais
  • invalid → carta inválida
  • restricted → não permitido
  • mute → carta ignorada
  • error → outro erro

Analogia: sinais da caixa postal explicando por que a carta não foi aceita.


No comments yet.