Rand Protocol
Documentação
Conceitos fundamentais

Contas e endereços

Os dois tipos de chaves na chain, como um endereço rand1 shielded é derivado, o que uma viewing key revela e por que o endereço curto da chain 11 foi revertido.

Use esta página para gerar a chave certa para cada finalidade, para analisar ou validar um endereço e para saber o que se revela ao entregar uma chave a alguém. Não há contas nesta chain: um saldo é um fato sobre um arquivo de chave, nunca sobre a chain.

Duas chaves, dois tipos de endereço

chave de nóchave de carteira
gerada porrand-node keygenrand keygen
segredouma seed de 32 bytesuma spend key de 256 bits
identidade públicaum endereço de 32 bytes, em base58, de 32 a 44 caracteresum endereço blindado, rand1…, com 1.665 ou 1.666 caracteres
assinablocos, votos, mints do faucet, Unbond, Withdraw, um Registration e, na chain 20, um voto de AdmitValidator; como autoridade de mint Key de um token, TokenMint e SetAuthority. Na chain 20, todas essas mensagens também cobrem o hash de gênese (Transações)nada: uma transferência é autorizada por suas provas
aparece na chain comoproponente de bloco, uma linha do registro de validadores, o emissor de um mint do faucet, a autoridade key de um tokennunca em uma transferência, onde fica selada dentro de envelopes. É publicada onde o valor entra no pool com um montante público: um depósito pela bridge, um mint de token e, na chain 20, o pagamento de uma invocação nomeiam o endereço do destinatário; o endereço de pagamento de um validador consta do registro; a gênese da chain 20 nomeia o tesouro de taxas da bridge; e, desde a chain 14, um mint do faucet e uma nota alloc da gênese publicam o pk do proprietário, os primeiros 32 bytes do endereço
arquivo{ "seed", "address", "public_key" }, modo 0600{ "version": 2, "spend_key": "<64 hex>" }, modo 0600

As duas nunca se misturam. Os validadores são identificados pelo primeiro tipo, e o mesmo formato de chave Dilithium2 serve à autoridade de mint Key de um token (rand token create --authority-key-out grava um arquivo no formato de rand-node keygen), à chave de pausa da bridge e às suas seis chaves de guardiões pós-quânticas. As chaves de atestação dos guardiões são secp256k1, com endereços de 20 bytes no estilo Ethereum (Bridge). O valor é mantido sob o segundo tipo.

O endereço transparente

Uma chave de nó é uma seed de 32 bytes da qual um par de chaves Dilithium2 é derivado de forma determinística: uma chave pública de 1.312 bytes e assinaturas de 2.420 bytes. O endereço é um hash BLAKE3 com separação de domínio da chave pública, representado em base58:

address = blake3("rand-address" || public_key)      // 32 bytes, shown as base58

Os objetos assinados (votos, blocos, mints, ações de staking) carregam a chave pública completa, de modo que um verifier confere blake3("rand-address" || public_key) == address em vez de confiar em um endereço isolado. A mesma seed também produz a identidade libp2p do nó, uma chave ed25519 a partir de blake3("rand-p2p-identity" || seed), que é o peer id depois de /p2p/ em um multiaddr de bootstrap.

rand-node keygen --out node.key.json      # prints the address
rand-node address --key node.key.json     # address, public key (hex), libp2p peer id

Exemplo: EdrEC2QRQrQF64iRXxF9927jNj6RidiHHByzx5xD6F1e é um dos validadores da chain 20. As chains 15 a 20 reutilizam as dezoito chaves rotacionadas para a chain 14, de modo que seus endereços e peer ids permanecem os mesmos e nenhum endereço de validador nem peer id da chain 13 continua em uso; mais oito validadores entraram com bond na chain 15, e todos os 26 constam do arquivo de gênese desde a chain 16.

O endereço blindado

Uma carteira é um único segredo, a spend key sk de 256 bits, e todo o resto é derivado dela. A derivação usa Poseidon2 com uma tag de domínio como primeira palavra absorvida (H(domain, msg)), a mesma função que a zkVM calcula no circuito:

spend key   sk                          256 bits, in wallet.key.json
   │
   ├─ viewing key   nk = H(NK, sk)      sees the whole history; cannot spend
   │     ├─ pk = H(PK, nk)              the field a note names its owner by
   │     ├─ nullifier(cm) = H(NF, nk, cm)   what a spend publishes
   │     ├─ ovk                         opens envelopes this wallet sent
   │     └─ ML-KEM-768 decapsulation key    opens envelopes sent to this wallet
   └─ address   rand1 + base58(pk || kem_ek)

O endereço é composto pelos 32 bytes de pk seguidos da chave de encapsulamento ML-KEM-768 de 1.184 bytes, em base58 após o prefixo rand1: 1.665 ou 1.666 caracteres (o comprimento em base58 depende dos primeiros bytes; cerca de um endereço em quatorze é o mais curto), cerca de 1,6 KB, e sem checksum. Quem envia precisa da chave de encapsulamento para selar o envelope da nota, e é por isso que ela está no endereço. Ela é pública por concepção: qualquer pessoa pode pagar a ele, e possuí-lo nada diz sobre o que ele contém.

rand keygen                      # wallet.key.json; refuses to overwrite an existing file
rand address                     # rand1… on stdout, its fingerprint XXXX-XXXX-XXXX-XXXX on stderr

Desde a v0.5.10, rand address imprime exatamente o endereço e uma quebra de linha na saída padrão, de modo que $(rand address) funciona em um script. A impressão digital vai para stderr.

A análise, exatamente como ShieldedAddress::parse a faz: remover rand1, decodificar de base58 e exigir exatamente 32 + 1.184 = 1.216 bytes; os 32 primeiros são pk, como oito palavras u32 little-endian, e o restante é a chave de encapsulamento. O RPC recusa qualquer parâmetro com mais de 2.000 caracteres antes de analisá-lo.

Ao lado do arquivo de chave, a carteira mantém <key>.key.json.notes.json, um cache das notas que esta chave abriu. Ele contém os textos claros das notas, por isso é gravado com modo 0600 como a chave; todas as suas linhas podem ser recuperadas por uma nova varredura a partir da folha 0.

Um endereço é longo demais para ser lido em voz alta ou comparado a olho nu e não tem checksum; por isso, desde a v0.5.10, toda carteira mostra uma impressão digital ao lado dele. A impressão digital serve apenas para exibição: nada na chain nem na rede carrega uma.

fingerprint = first 80 bits of blake3("rand-address-fingerprint-1" || pk_bytes || kem_ek)
            = 16 Crockford base32 characters, shown as XXXX-XXXX-XXXX-XXXX

O hash é calculado sobre os 1.216 bytes brutos que o endereço codifica. O alfabeto é 0123456789ABCDEFGHJKMNPQRSTVWXYZ; a análise ignora maiúsculas e hifens e lê O como 0 e I ou L como 1.

Um link randpay: carrega um endereço e, opcionalmente, o que pagar a ele:

randpay:<rand1…>[?amount=<decimal>][&asset=<index | 64 hex | rpl1…>][&memo=<percent-encoded UTF-8>]

amount está nas unidades de exibição do ativo (RAND decimal com nove casas decimais, um token com os decimals da própria linha de seu registro) e não pode ser zero. memo tem no máximo 510 bytes de UTF-8. O esquema é reconhecido sem distinção entre maiúsculas e minúsculas; um parâmetro desconhecido, um repetido ou uma codificação percentual inválida é recusado.

rand address --uri --amount 1.5 --memo "invoice #42" --qr   # a randpay: link, as a terminal QR
rand contacts add alice rand1q9f…                            # shows the fingerprint, asks add? [y/N]
rand send alice 1.5 --memo "coffee"                          # to a contact, with a memo

rand send <TO> aceita um endereço rand1…, um link randpay: ou o nome de um contato salvo, tentados nessa ordem. O amount, o asset e o memo de um link preenchem o que a linha de comando deixa de fora, e um valor informado das duas formas que não coincida é recusado. Antes de gerar a prova, send imprime to <contact, if any> · fingerprint XXXX-XXXX-XXXX-XXXX · <amount> <asset> e pede confirmação; um script passa --yes. Os contatos são armazenados ao lado da chave em <key>.contacts.json, com modo 0600. O memo viaja dentro do envelope da nota (Notas).

Não existe rand balance <address> nem RPC de saldo: a chain não pode responder a isso para ninguém. Uma carteira calcula seu saldo varrendo todos os envelopes da chain com sua viewing key (Notas).

Chaves que você pode entregar a outra pessoa

A divulgação é uma propriedade das chaves, e a chain não pode forçar nada disso.

chaveabregranularidade
a viewing key nk (64 hex)toda nota que a carteira já recebeu e, por meio de ovk, toda nota que já enviou, com o nullifier de cada gastotudo ou nada, retroativa e prospectiva
uma chave de transação TxKey (32 bytes)exatamente o envelope que ela selou: a nota e, desde a chain 18, seu memoum pagamento
uma chave de chamada K_calla transcrição de entradas privadas de uma chamada confidencialuma chamada

Uma viewing key não pode gastar. Desde a chain 17 (autorização dividida), a própria prova do bundle é feita a partir de nk, e todo bundle também carrega uma segunda prova de autorização, pequena, que só a spend key pode produzir e que fica vinculada a uma única transação (Notas). Isso é o que permite entregar nk a um prover delegado, e portanto todo o histórico da carteira, sem que ele possa gastar; a carteira sempre produz a prova de autorização em sua própria máquina. Os endereços, as chaves e as notas existentes não mudam com a divisão. A carteira deriva nk a cada execução e nunca o armazena; cada TxKey é sorteada de novo para cada envelope e descartada após a selagem. Um nó pode receber uma viewing key por rand_importViewingKey (em memória, no máximo 64 por nó, perdida na reinicialização) para varrer em nome do titular — o caminho do explorador — e rand_checkTransaction(hash, key) confere um pagamento contra uma TxKey em uma única chamada sem estado. rand viewing-key imprime nk, e rand tx-key <hash> imprime a chave de cada saída de uma transação que esta carteira consegue abrir.

Os ids de token não são endereços

Um token RPL tem um terceiro tipo de identificador textual, e ele nomeia um token, nunca um titular. O id de ativo de 32 bytes do token é exibido como 64 caracteres hexadecimais e como rpl1…: bech32m (BIP-350) com a parte legível rpl sobre os 32 bytes do id, 52 caracteres de dados mais um checksum de 6 caracteres, 62 caracteres. A análise é estrita: um checksum inválido, outra parte legível, uma carga que não tenha exatamente 32 bytes ou caixa mista é recusado, de modo que um erro de digitação nunca resolve para um token diferente. Uma nota não carrega o id; sua palavra asset é o índice denso do token no registro (Tokens RPL).

O destinatário da bridge

O formato de transmissão da bridge tem um campo de destinatário de 32 bytes, e um endereço blindado não cabe nele. Hoje o campo carrega um hash do endereço:

recipient_hash = blake3("rand-shielded-recipient" || pk_bytes || kem_ek)

O depositante na chain de origem informa o hash, os guardiões o assinam, e a transação BridgeAttest carrega o endereço completo para que o ledger o confira contra o hash (Bridge).

O endereço blindado curto: testado na chain 11, revertido

A chain 11 (tag v0.2 do fullnode, 2026-09-17) substituiu o endereço longo por um receiver id de 53 a 55 caracteres, rand1 + base58(blake3(receiver signing key) ‖ checksum), e moveu a chave de encapsulamento ML-KEM para um receiver record assinado, que o remetente obtinha no registro do explorer ou recebia embutido em uma solicitação de pagamento. Ela funcionou por um dia e foi revertida no mesmo dia (fullnode 17db41d); a chain 12 voltou ao endereço longo, exatamente como descrito acima, e todas as chains desde então, a chain 20 inclusive, o mantêm.

Por que foi retirada. Um receiver id é um hash, e um remetente não consegue selar uma note para um hash. O primeiro pagamento a uma carteira que nunca havia se registrado exigia que o destinatário entregasse uma solicitação de pagamento ou um arquivo de record, e o próprio registro era pago com uma autotransferência, que uma carteira nova e vazia não consegue fazer. Os dois caminhos de entrega também informavam ao registro quem estava prestes a ser pago. O desenho que preserva um endereço curto, a capacidade de envio incondicional e a privacidade criptográfica é um endereço híbrido: uma chave X25519 de 32 bytes embutida (cerca de 93 caracteres) e a chave pós-quântica obtida por consulta, de modo que o primeiro pagamento a uma carteira não registrada é confidencial contra adversários clássicos e todos os seguintes são totalmente pós-quânticos. Isso é especificado a seguir; até que seja lançado, o endereço longo é o endereço.

A especificação da chain 11 e sua implementação permanecem no histórico do fullnode (docs/superpowers/specs/2026-09-17-short-shielded-address.md, tag v0.2) pelas partes que o desenho híbrido reaproveita: a chave de assinatura do receiver derivada, o record assinado e seu verificador, e o registro como estado da chain.

Última verificação em relação ao commit c0878c3f do fullnode (chain 21) em 2026-10-12. Onde o código e esta página divergirem, o código está certo; avise-nos.