Capítulo 5

Uma imersão profunda no Monero e em criptografia

Muito antes do surgimento dos computadores, matemática e criptografia sempre estiveram no centro dos sistemas de comunicação e de troca de informações. Embora cifras simples existam desde os tempos de César, a criptografia moderna nasceu durante as Guerras Mundiais para criptografar mensagens importantes e confidenciais. Inicialmente, governos e militares financiaram pesquisas secretas sobre criptografia para identificar protocolos que pudessem proteger segredos de estado.

Agora, a criptografia não está mais limitada a espiões e militares; ela forma a base da comunicação e segurança na era da internet e tem sido amplamente estudada por pesquisadores acadêmicos e institucionais espalhados por todo o planeta.

Hoje em dia, a criptografia é uma ferramenta onipresente que fornece segurança, gerenciamento, comunicação e diversos tipos de conexões que melhoram nossa vida no dia-a-dia. Considere, por exemplo, a invenção do Secure Socket Layer (SSL, tornado obsoleto em favor do TLS), que baseia-se em assinar conteúdos criptograficamente. Hospitais, bancos, governos e empresas, todos eles protegem seus dados usando criptografia.

Esse capítulo discutirá como ferramentas criptográficas podem ser utilizadas em um banco de dados financeiro descentralizado para dar origem às criptomoedas, em especial, o Monero.

5.1 Fundamentos de matemática

Aqui vai uma breve introdução a vários princípios matemáticos que formam o cerne da criptografia.

5.1.1 Divisão Euclidiana (A/B)

Dividir qualquer número A por outro B, escrito como A/B ou A÷B retorna uma resposta que pode ser escrita na forma de um quociente com um resto ou como um único decimal.

De modo geral:

A/B = q com resto r

Por exemplo:

12/4 = 3 com resto 0, que pode ser escrito como 3,0 na forma decimal
13/4 = 3 com resto 1, que pode ser escrito como 3,25 na forma decimal
27/5 = 5 com resto 2, que pode ser escrito como 5,4 na forma decimal

5.1.2 Números primos

Um número primo é qualquer inteiro (número completo) que seja divisível apenas por um e por ele mesmo. Por exemplo:

20 não é primo pois ele é divisível por 2, 4, 5 e 10, resultando em números inteiros, por exemplo: 20 ÷ 4 = 5 ou 20 ÷ 10 = 2.

7 é primo pois dividi-lo por qualquer inteiro não resulta em um número inteiro, por exemplo: 7 ÷ 3 = 2,333.

Alguns exemplos de números primos incluem o 3, 5, 7, 11, 13, 97, 223, 997, 3413, 4421, 17837, 145601, 428567, 1171967 e números ainda maiores como 2074722246773485207821695222107608587480996474721117292752992589912196684750549658310084416732550077 ou os primos gêmeos 2.996.863.034.895  × 2^1.290.000 ± 1, que têm mais de 350.000 dígitos cada!

5.1.3 Aritmética modular

A aritmética modular descreve números inteiros que “voltam para trás” quando atingem um certo valor. O relógio de ponteiros é um bom exemplo. Se você for dormir 5 horas após as 11:00 da noite, não verá o relógio de ponteiros marcar 16:00! Em vez disso, à meia-noite, os números voltam para zero (ou seja, 5 horas após 11:00 da noite é 04:00 da manhã do dia seguinte).

Dados dois número positivos, A (dividendo) e B (divisor),

A módulo B = resto r da divisão A/B.

No contexto dos relógios, ir dormir 5 horas após 11:00 da noite pode ser representado como:

(11:00 da noite + 5 horas) mod 12 = ...
                                  = 16:00 mod 12
                                  = 04:00 (da manhã)

5.1.4 Representação dos inteiros

Números inteiros podem ser representados usando diversas codificações diferentes, muitas das quais são frequentemente encontradas em ciência da computação.

A maioria das pessoas está bastante familiarizada com o sistema “decimal” de base-10, que utiliza 10 caracteres para representar números: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.

A codificação “hex” adiciona 6 caracteres extras, formando o conjunto de base-16: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f.

O número inteiro 11719682 na base-10 pode ser expressado como B2D402 na base-16. Perceba que um conjunto de caracteres maior requer menos dígitos para representar o mesmo número.

Computadores “pensam” na base-2, utilizando somente os caracteres “0” e “1”. Este sistema é chamado de binário e o número 11719682 (base-10) seria representado como 101100101101010000000010 na forma binária.

O Monero apresenta o endereço final e as chaves na base-58, que utiliza numerais arábicos e a maior parte do conjunto de caracteres latinos (tanto na forma maiúscula quanto minúscula). Ele é similar a outro esquema chamado Base64, porém foi modificado para evitar o uso de números e letras que parecem iguais quando impressas. O Monero utiliza esse formato puramente para ajudar os usuários, que muitas vezes precisam ler ou transcrever longos endereços.

O alfabeto na base-58 é: 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz

Nota: O zero (0) juntamente com as letras I (i maiúsculo), O (o maiúsculo) e l (L minúsculo) não fazem parte do alfabeto Base58 por conta de sua semelhança um com o outro.

5.1.5 Curvas elípticas

5.1.5.1 Introdução geral

Curvas elípticas são definidas como um conjunto de pontos bi-dimensionais (x, y) que satisfazem uma equação:

y^2=x^3+ax+b.

Por exemplo, com coeficientes fixos a = 2 e b = 3, essa equação fica:

y^2=x^3+2x+3,

que é satisfeita por muitos pares de pontos, como:

x = 3 e y = 6
x = 3 e y = -6
x = -1 e y = 0.

2.1.5.2 Ed25519 Edwards Invertida

O Monero utiliza uma curva elíptica Edwards Invertida particular para realizar operações criptográficas, a Ed25519, que é birracionalmente equivalente à curva de Montgomery Curve25519.

A curva Ed25519 pode ser expressa algebricamente como:

- x^2 + y^2 = 1 − (121665/121666) x^2 y^2.

Considerando a equação genérica da nossa curva elíptica, a Edwards Invertida é um caso especial que usa os parâmetros:

a = -1 e b = 121665/121666.

Recentemente, ficou claro que o algoritmo PRNG (sigla para gerador de números pseudoaleatórios ou Pseudo-Random Number Generator, em inglês) endossado pelo NIST (Instituto Nacional de Padrões e Tecnologia ou National Institute of Standards and Technology, em inglês) é falho e possivelmente contém um backdoor. Dado que os algoritmos do padrão NIST4 tiveram problemas recentemente, a curva Edwards Invertida foi selecionada para tratar essas questões levantadas pela comunidade de criptografia.

Visto sob uma perspectiva mais ampla, as curvas selecionadas pelo NIST também são implicitamente apoiadas pela NSA (Agência de Segurança Nacional ou National Security Agency, em inglês). Esse tipo de apoio é visto com suspeita pelas comunidades de criptografia e criptomoedas por conta de incidentes passados onde a NSA usou sua autoridade sobre o NIST para enfraquecer os algoritmos sugeridos pela última.

A curva Edwards Invertida Ed25519 não está sujeita a nenhuma patente e a equipe por trás dela desenvolveu e adaptou algoritmos básicos de criptografia pensando na eficiência. Neste momento, acredita-se que essa curva é segura.

5.1.5.3 Operações elípticas

Adição de pontos de uma curva elíptica e multiplicação escalar são operações fundamentais em esquemas de criptografia usando curvas elípticas. É importante termos um conhecimento básico sobre esses conceitos antes de imergirmos nos mecanismos de cálculo do Monero.

A adição de pontos em uma curva elíptica funciona de forma diferente da adição convencional que encontramos na aritmética usada em nosso cotidiano. Para adicionar dois pontos em uma curva elíptica, precisamos encontrar a linha entre esses dois pontos e depois encontrar o ponto no qual a curva intercepta com essa linha. O ponto é então refletido sobre o eixo x para chegar-se ao ponto final desejado.

Para se adicionar um ponto a ele próprio, operação conhecida como duplicação de pontos, precisamos encontrar a linha tangente ao ponto inicial para se chegar ao ponto que essa tangente intercepta com a curva. Este ponto é então refletido sobre o eixo x para chegar-se ao ponto final desejado.

A multiplicação escalar utiliza tanto um ponto na curva quanto um inteiro. Para multiplicar um ponto, P, por um inteiro, S, o ponto é adicionado a ele próprio S vezes. Muitos esquemas criptográficos, como aqueles empregados no Monero, utilizam pontos base comuns da curva elíptica como pontos geradores para gerar chaves públicas a partir de chaves privadas.

Quando o ponto gerador da curva é adicionado a ele próprio várias vezes, o ponto resultante não pode ser usado para determinar quantas vezes a operação aconteceu. Esse problema é frequentemente referenciado como problema do logaritmo discreto em curvas elípticas. Esse tipo de multiplicação escalar é considerada uma função de uma só via, já que é muito difícil reverter a operação.

5.2 Fundamentos de criptografia

Monero é a criptomoeda líder em segurança e não-rastreabilidade graças às suas características únicas voltadas para privacidade, as quais exploraremos mais atentamente ao longo deste capítulo. Este é um dos capítulos mais técnicos do livro devido à natureza matemática da criptografia. Técnicas mais complexas são desenvolvidas a partir de princípios simples conhecidos como primitivas criptográficas.

Uma primitiva criptográfica é um algoritmo que serve como alicerce para protocolos criptográficos. O Monero emprega uma grande variedade de primitivas criptográficas para diversos usos, alguns dos quais abordamos conceitualmente nos Capítulos 3 e 4. A abordagem intencional do Monero no que se refere à privacidade e à prova de trabalho (resistente a ASICs) requer ferramentas criptográficas mais sofisticadas do que aquelas utilizadas por muitas das outras criptomoedas.

5.2.1 Criptografia simétrica e assimétrica

Algoritmos para criptografar dados podem ser classificados como simétricos ou assimétricos dependendo do tipo de chaves que são utilizadas.

A encriptação simétrica requer que os participantes compartilhem um segredo, por exemplo, você criptografa uma mensagem com a senha “hunter2” e o remetente usa a senha “hunter2” para decriptá-la. Para se comunicar dessa forma, ambas as partes precisam concordar em um segredo (simétrico) compartilhado previamente. Essa questão prática limita a utilidade da encriptação simétrica a poucas aplicações.

A encriptação assimétrica permite que duas partes interajam em segurança sem a necessidade de compartilhar um segredo em particular. Esse tipo de criptografia está intimamente ligada à estrutura de segurança da internet, de aplicativos de mensagens ponta-a-ponta e das criptomoedas.

O Bitcoin utiliza encriptação assimétrica com duas chaves:

  • chave privada – para assinar transações e descriptografar dados
  • chave pública – para verificar assinaturas e criptografar dados

O Monero utiliza uma estrutura criptográfica mais complexa que requer quatro chaves:

  • chave pública de visualização – usada para verificar a validade de endereços
  • chave privada de visualização – usada para ver dados como saldo, taxas e valor das transações (a chave de visualização não consegue criar nem assinar transações)
  • chave pública de gasto – outra chave pública para verificar transações
  • chave privada de gasto – usada para assinar transações, por exemplo, ao enviar moneroj

Seu endereço público Monero é uma representação direta do par de chaves públicas, enquanto o Bitcoin (e seus clones) utiliza um hash da sua única chave pública. Chaves EdDSA (tanto privadas quanto públicas) têm 256 bits de comprimento ou 64 caracteres hexadecimais. Nem todo inteiro de 256-bit é um escalar EdDSA válido (chave privada); ele deve ser menor que a “ordem da curva” descrito pela equação da seção sobre a função Ed25519.

5.2.2 Hashing

O Capítulo 4 discutiu o conceito de hash e como ele é usado para uma variedade de coisas, desde confirmar a veracidade de dados até distribuir recompensas em um sistema prova de trabalho. Exemplos de hashes são mostrados na seção de criptografia próxima ao final do Capítulo 4.

Selecionar um bom algoritmo de hash é crucial para gerar endereços e chaves de forma segura. Se duas entradas diferentes produzem o mesmo hash de saída, tal fenômeno é conhecido como colisão. Hashes são comumente utilizados como um identificador nos sistemas blockchain, apoiando-se em sua propriedade de singularidade. Além disso, uma colisão durante a geração da semente faria com que mais de uma pessoa acabasse possuindo as mesmas chaves e endereços; obviamente isso seria extremamente problemático!

O Monero utiliza o sistema prova de trabalho CryptoNight, que emprega um algoritmo especial de hash chamado CryptoNote, projetado com base no hash Keccak. O algoritmo Keccak ganhou a competição do NIST para se tornar o SHA3 e foi projetado por engenheiros que não estão ligados à NSA.

5.2.3 Gerador de números pseudoaleatórios do Monero (PRNG)

Quando usuários e computadores estão criando novas chaves, é crucial que eles encontrem novas chaves que ninguém poderá adivinhar. Na verdade, isso é um tarefa bastante difícil, já que tanto equipamentos quanto softwares geralmente são projetados para favorecer a reprodutibilidade. Se o computador gera dados aleatórios de forma previsível, a saída pode até ser bastante aleatória mas ao mesmo tempo relativamente fácil de adivinhar.

Por exemplo, considere um PRNG que simplesmente misture os dígitos do horário atual para criar uma chave de 4 dígitos. Assim, as “10:34” ele poderia gerar a saída “0413” ou “1403” ou “0134”, e assim por diante. Se você quisesse manter essa chave secreta, este seria um método horrível de se usar por algumas razões:

Um adversário que saiba que você criou suas chaves quando você retornou do almoço, por volta das 12:45, saberia que os dígitos “1” e “2” aparecem na sua chave e isso restringiria consideravelmente as opções possíveis.

No formato HH:MM, não existe uma hora do dia que tenha três “9”. Na verdade, não existe nenhuma hora do dia que contenha três dígitos de qualquer um dos números {6, 7, 8, 9} já que 17:89 h, 18:78 h, etc. são horários impossíveis. Essa regra exclui muitas senhas de 4 dígitos, deixando o adversário com uma “lista” muito menor de opções para adivinhar.

O gerador de números aleatório acima baseado no relógio é péssimo, pois usar a hora do dia como semente inicial é previsível. A semente inicial deveria ser muito mais difícil de ser adivinhada por um adversário. Bons geradores de números aleatórios introduzem bastante entropia para tornar suas saídas imprevisíveis. Simplesmente misturar 4 dígitos não introduz muita entropia, outra razão pela qual nosso PRNG acima seria inseguro.

Quando um usuário está gerando uma carteira, seu sistema operacional provém a semente inicial ou primeira fonte de entropia. A partir disso, o Monero aplica repetidamente a função hash Keccak para levar a uma saída imprevisível e não reprodutível. Cada rodada de hash produz uma saída, que é então usada como entrada para o próximo hash.

5.3 Gerando chaves e endereços Monero

5.3.1 Escolhendo uma semente

No Capítulo 2, conversamos sobre o coração da sua carteira: sua semente. Esse segredo gerado por sua carteira é usado para derivar todas as suas chaves, e acessar e gastar seus fundos. Naquela ocasião, simplesmente consideramos a semente mnemônica de 25 palavras.

“Por trás da cortina”, uma semente é um inteiro de 256 bits único a partir do qual chaves e endereços são derivados, por exemplo:

112699108505435943726051051450940377552177626778909564691673845134467691053980

Geralmente, eles são representados como um número na base-16 contendo 64 dígitos, por exemplo:

f9296f587419f1cdede67de160fca14d1069ecaa4c52f012af031eeA09ee039c

(para chaves no estilo mnemônico, essa representação da semente é, na verdade, a chave privada de gasto por si só!)

Escrever as chaves em qualquer um dos formatos acima seria bastante difícil e a maioria das pessoas estariam sujeitas a cometer ao menos um erro. Converter a semente para uma frase mnemônica é outro passo incluído somente para melhor a usabilidade e a interpretação por humanos. A frase mnemônica basicamente converte o número de 256 bits acima em um “número” na base-1626 contendo 24 dígitos (24 palavras). Essa representação da longa sequência de caracteres da semente é muito mais fácil de ser lida:

lamb hexagon aces acquire twang bluntly argue when unafraid awning academy nail threaten sailor palace selfish cadets click sickness juggled border thumbs remedy ridges border

Quando sua carteira apresenta a semente de 24 palavras, ela também adiciona uma 25ª palavra que funciona como um verificador, permitindo a detecção posterior de erros de digitação ou equívocos. O método mnemônico do Monero codifica numa razão mínima de 4:3. Em outras palavras, quatro bytes criam três palavras, mais uma palavra verificadora; oito bytes criam seis palavras, mais uma palavra verificadora; e assim por diante.

A chave privada de visualização é derivada calculando o hash da semente usando Keccak-256, produzindo um segundo inteiro de 256 bits que é então enviado para uma função chamada sc_reduce32 para garantir que ele seja compatível com a curva elíptica. As sementes criadas por esse método sempre serão escalares válidos já que primeiramente eles foram enviados para a função sc_reduce32.

5.3.2 Derivação das chaves

5.3.2.1 Todas as chaves

A semente Monero descrita acima é, na verdade, sua chave secreta de gasto, a partir da qual todas as outras chaves são derivadas. A chave secreta de visualização é o hash reduzido da sua chave secreta de gasto, convertida para um escalar válido na curva Ed25519.

Essas duas chaves privadas são multiplicadas pelo ponto gerador para produzir duas chaves públicas da sua carteira (chave pública de gasto e chave pública de visualização). Refere-se a esse método de derivação das chaves como método determinístico.

5.3.2.2 Carteira somente leitura

Você pode conceder acesso somente leitura a uma conta Monero configurando uma carteira com sua chave secreta de visualização, mas NÃO com sua chave secreta de gasto. Essas carteiras somente leitura podem ver todas as transações de entrada, mas não conseguem gastar moneroj nem ver transações de saída.

Existem muitas situações em que é útil verificar transações de entrada sem ter acesso ao envio. Por exemplo, indivíduos com carteiras frias podem utilizar a chave de visualização para verificar que fundos foram recebidos, e ainda assim manter sua chave secreta de gasto guardada em segurança. Da mesma forma, desenvolvedores podem construir sistemas capazes de detectar e tomar ações com base em pagamentos recebidos sem precisar ter a habilidade de mover os fundos.

Essa característica é especialmente valiosa para instituições de caridade que podem compartilhar suas chaves de visualização para garantir transparência e prestação de contas em relação às doações. Se você enviar uma doação a um endereço público, poderá usar a chave de visualização para certificar-se que a instituição de caridade recebeu seus fundos.

Por exemplo, considere o endereço de doação do Fundo Geral do Monero:

44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A.

Uma vez que os endereços sigilosos previnem que o endereço público seja gravado ou pesquisado na blockchain, a comunidade também disponibiliza a chave de visualização (f359631075708155cc3d92a32b75a7d02a5dcf27756707b47a2b31b21c389501) para que as pessoas possam revisar as atividades relacionadas às doações.

E dado que qualquer um com a chave de visualização consegue ver a quantidade total de moneroj que uma carteira recebeu, uma instituição de caridade transparente que tenha recebido 100 XMR não poderá desviar 90 XMR e alegar que recebeu somente 10 XMR. Essa funcionalidade é especialmente valiosa para casos de financiamento coletivo onde uma certo valor em doações precisa ser atingido.

A impossibilidade de ver transações de saída em uma carteira somente leitura é uma característica, e não um bug! Se transações de saída fossem públicas, elas revelariam qual saída já foi gasta. Isso seria muito problemático, já que as assinaturas em anel dependem do estado de ambiguidade “gasto ou não gasto”. Suponha que uma instituição de caridade revele quando uma saída é gasta; todas as aparições dessa saída em assinaturas em anel, futuras ou passadas, poderiam ser identificadas como chamarizes. Assim, é necessário que transações de saída não sejam expostas para manter a integridade da privacidade geral da rede.

A característica de carteiras somente leitura do Monero poderá ainda ser útil como uma proteção contra regulamentações que tentem bani-lo em certas jurisdições. Uma vez que usuários individuais do Monero podem optar por compartilhar suas chaves privadas de visualização, eles poderiam também escolher fornecê-las a auditores para verificarem seus fundos. Tal possibilidade seria uma maneira sensata de satisfazer auditores e como resultado, afastar as preocupações de que o Monero são poderia funcionar dentro dos paradigmas das estruturas financeiras atuais.

5.3.3 Geração de endereços

Um endereço padrão da carteira Monero é composto por duas chaves públicas (a chave pública de gasto + chave pública de visualização) derivadas na última seção. Ele também contém uma verificação e um byte da rede que identifica tanto o tipo da rede quanto o tipo do endereço.  

5.3.3.1 Byte da rede

O byte da rede é utilizado para diferenciar entre várias criptomoedas e redes. Moedas CryptoNote especificam os valores apropriados no arquivo src/CryptoNote_config.h, por exemplo:

uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 18;

A rede principal do Monero utiliza o “18” para indicar um endereço primário (por isso o endereço primário do Monero começa com um “4”, que é sua representação ASCII). Os desenvolvedores do Monero utilizam também as redes testnet e stagenet, que possuem bytes próprios e únicos:

Nome Valor do código Valor ASCII
Endereço primário da rede principal 18 4
Subendereço da rede principal 42 8
Endereço primário da rede testnet 53 9
Subendereço da rede testnet 63 B
Endereço primário da rede stagenet 26 5
Subendereço da rede stagenet 36 7

5.3.3.2 Chaves públicas concatenadas

As chaves públicas de gasto e de visualização são concatenadas e anexadas ao byte da rede para produzir o endereço cru (tudo com exceção da soma de verificação). Embora este ainda seja um formato cru, ele contém todas as informações das chaves: chaves para criar transações e metadados da rede para garantir que as transações sejam anunciadas para a rede correta.

5.3.3.3 Soma de verificação

Já que transações Monero são irreversíveis, é crucial que os pagamentos sejam enviados ao endereço certo! Para ajudar a evitar erros e pequenos equívocos, o endereço inclui uma soma de verificação. Assim, se o remetente cometer um erro de digitação ou não inserir o endereço completo, a soma de verificação não irá corresponder, indicando que o texto inserido não é um endereço válido.

Essa soma de verificação é gerada usando o hash Keccak das informações do endereço coletadas na seção anterior. A saída do hash é reduzida aos primeiros 4 bytes e utilizada como verificador.

5.3.3.4 Colocando tudo junto: finalização do endereço

Por fim, o byte da rede, as chaves e a soma de verificação são concatenados de acordo com a especificação Monero:

Índice Tamanho em bytes Descrição
0 1 identifica o tipo da rede e o tipo do endereço – “18” para a mainnet e “53” para a testnet (na base-58, “4” e “9” respectivamente)
1 32 chave pública de gasto
33 32 chave pública de visualização
64 4 soma de verificação (hash criado com a função Keccak dos 65 bytes anteriores, reduzido aos 4 primeiros bytes)

Finalmente, essa saída com 69 bytes é codificada para o formato base-58 do Monero. A conversão aumenta o comprimento para uma sequência com 95 caracteres que é fácil de ler e escrever. E isso é tudo! Os endereços primários do Monero simplesmente contém:

[byte da rede + chave pública de gasto + chave pública de visualização + soma de verificação]

Exemplo de um endereço padrão:

4BKjy1uVRTPiz4pHyaXXawb82XpzLiowSDd8rEQJGqvN6AD6kWosLQ6VJXW9sghopxXgQSh1RTd54JdvvCRsXiF41xvfeW5

O pseudocódigo abaixo descreve o processo de geração de um endereço público, usando Hs() para representar a função hash Keccak e “||” para representar a concatenação de sequências de caracteres.

Soma de verificação = Hs(Varint(Prefixo) || chave pública de gasto || chave pública de visualização)
SequênciaDeCaracteresSerializada = Base58(Prefixo || chave pública de gasto || chave pública de visualização || soma de verificação)

O Capítulo 7 inclui códigos reais em Python para você gerar chaves e endereços sozinho!

5.3.4 Subendereços

A privacidade nas transações Monero é atingida por três construções principais: assinaturas em anel, endereços sigilosos (de uso único) e RingCT. Juntas, elas mitigam o risco das transações serem associadas ao analisar-se dados da blockchain. Entretanto, deve-se considerar os riscos de associações “fora da blockchain” (em outras palavras, informações coletadas de outras fontes que não seja a blockchain em si).

Por exemplo, imagine que seu endereço primário tenha recebido pagamentos de várias pessoas diferentes. Graças à tecnologia de endereços sigilosos do Monero, seu endereço público nunca é explicitamente armazenado nas transações, então ninguém pode associar essas transações ao analisar a blockchain (incluindo quem lhe enviou). Porém, essa privacidade criptográfica é inteiramente contornada se dois dos seus pagadores comunicarem-se um com o outro e descobrirem que eles têm enviado moneroj para o mesmo endereço!

Você pode evitar esse risco gerando múltiplos subendereços e compartilhando um único com cada pessoa que lhe for enviar moneroj. Os subendereços são derivados a partir das mesmas chaves que seu endereço primário, então fundos recebidos por qualquer subendereço são transmitidos para o saldo da mesma carteira. Entretanto, é impossível associar os vários subendereços criptograficamente, ou seja, várias pessoas enviando moneroj para a mesma carteira não conseguem reconhecer que eles pertencem a mesma pessoa ao comparar suas listas de endereços.

5.3.4.1 Criando um subendereço

Lembre-se que cada carteira têm dois pares de chaves. A chave privada de visualização (pV0) e a chave privada de gasto (pS0) são mantidas em segredo, enquanto que a chave pública de visualização (PV0) e a chave pública de gasto (PS0) são codificadas em cada endereço. Conforme discutido, as chaves públicas são geradas multiplicando-se as chaves privadas pelo ponto gerador (G) na curva elíptica, por exemplo (PV0, PS0) = (pV0, pS0)G.

Sua carteira pode criar um grande número de subendereços, cada um com um índice “i” diferente (geralmente partindo-se de i = 1). Cada subendereço terá seu próprio conjunto de chaves para cada índice, com chaves privadas (pVi, pSi) e públicas (PVi, PSi) únicas.

A fórmula para criar uma chave pública de gasto para o iº subendereço é:

PSi = Hs(pV0||i)G+PS0

O processo tem início concatenando-se o índice “i” com a chave privada de visualização do endereço primário (pV0) e passando o resuldado através da função hash_to_scalar (nota: na prática, a carteira cliente de referência também concatena a sequência de caracteres SubAddr aos dados, como um “sal” para o hash). O escalar resultante é multiplicado pelo ponto gerador da curva e adicionado à chave de gasto do endereço primário através da adição de ponto em curvas elípticas.

A chave pública de gasto desse subendereço é multiplicado pela chave privada de visualização do endereço primário para retornar a chave pública de visualização do subendereço:

PVi = pV0*PSi

As chaves públicas do subendereço são codificadas no endereço público seguindo a mesma convenção dos endereços primários:

Subendereço_i = base58(byte da rede || PSi || PVi || soma de verificação)

Porém, o byte da rede mainnet para subendereços é 0x42, por isso todos eles começam com o dígito “8”.

5.3.4.2 Enviando para um subendereço

É crucial que esse primeiro identificador da rede seja diferente, já que transações para subendereços precisam ser construídas de forma ligeiramente diferente do normal.

Quando estão construindo uma transação, normalmente as carteiras geram 32 bytes aleatórios para servir como chave privada. Quando estão enviando para um endereço primário, essa chave aleatória é multiplicada pelo ponto gerador na curva elíptica através da multiplicação escalar em curvas elípticas para retornar a chave pública da transação. Entretanto, quando estão enviando para um subendereço, a chave privada da transação é, em vez disso, multiplicada pela chave pública de gasto do subendereço do destinatário.

5.3.4.3 Recebendo em um subendereço

Devido à natureza ofuscada da blockchain do Monero, as carteiras precisam escanear toda transação para determinar se ela pertence ou não ao dono da carteira. Para determinar se uma saída X (com chave pública da transação R) foi enviada ao endereço primário, a carteira verifica alguns cálculos baseados na sua chave pública de visualização e chave pública de gasto. Se a igualdade X==Hs(pV0*R)G+PSi for verdadeira, então aquela saída pode ser desbloqueada e gasta!

Entretanto, o processo é ligeiramente diferente para verificar quais saídas pertencem aos subendereços. O cálculo é praticamente igual, exceto que o termo hash_to_scalar é subtraído da saída e comparado com as chaves públicas de gasto do subendereço. A carteira sabe que encontrou uma saída que lhe pertence se a igualdade PSi==X-Hs(pV0*R)G for verdadeira.

5.3.5 Outros métodos para derivação de chaves

Para aumentar a confusão, atualmente existem pelo menos 3 métodos diferentes de derivação das chaves privadas utilizados no Monero (isso também é verdade para o Bitcoin). Estes métodos variam em poucas questões “chaves”:

  • Original (estilo não determinístico): As chaves privadas de gasto e de visualização para criar uma conta são escolhidas aleatoriamente e de forma independente. Não existe uma forma melhor de fazer backup de uma conta não determinística senão manter cópias de cada arquivo. Devido a melhores alternativas, esse método complicado não é mais recomendado.

  • Mnemônico (estilo determinístico ou “Electrum”): Neste estilo, todas as chaves são derivadas a partir de uma única chave privada de gasto, também chamada de semente. A chave privada de visualização é derivada calculando-se o hash Keccak-256 da chave privada de gasto para produzir um escalar EdDSA válido. Essas contas são fáceis de fazer backup já que você só precisa escrever e armazenar a semente (que geralmente é expressa na forma de uma frase mnemônica na base-1626).

  • Estilo MyMonero: A família de carteiras MyMonero utiliza um método similar à convenção Electrum, porém, a frase da semente contém 13 palavras ao invés das 25 habituais. As 13 palavras são convertidas em um inteiro de 128 bits que é usado para deviração tanto das chaves de gasto quanto das chaves de visualização. O inteiro da semente é executado através do hash Keccak-256 e convertido para formar a chave privada de gasto. Essa chave privada de gasto é novamente executada através do hash Keccak-256 e convertida para formar a chave privada de visualização.

Você deve ter notado uma diferença importante entre os estilos das sementes MyMonero e Electrum. O estilo MyMonero cria a chave privada de visualização calculando o hash de um inteiro aleatório, enquanto que o estilo Electrum calcula o hash da chave privada de gasto. Isso significa que as sementes de 13 e 25 palavras não são compatíveis entre si – não é possível criar uma conta no estilo Electrum que coincida com uma conta no estilo My-Monero (ou vice-versa) porque o par de chaves de visualização sempre serão diferentes.

5.4 As tecnologias de privacidade

5.4.1 Endereço sigiloso

O Capítulo 3 descreveu conceitualmente como endereços de uso único, também conhecidos como endereços sigilosos, permitem que transações sejam transmitidas à rede sem revelar o endereço real do destinatário. Essa seção irá aprofundar na explicação criptográfica por trás dessa chave pública de uso único.

5.4.1.1 Enviando

O protocolo CryptoNote calcula o endereço de uso único de destino de acordo com a fórmula X=Hs(r*PV|i)G+PS. Vamos entender o significado desses símbolos e como Maria poderia gerar um endereço de uso único quando fosse enviar dinheiro a George.

A variável r é a chave privada da transação, que é um escalar pseudoaleatório de 256 bits. Maria (o remetente) é a única pessoa que saberá essa chave; até mesmo George (que é o destinatário) nunca saberá o número aleatório que a carteira de Maria escolheu para r.

Maria então multiplica a chave pública de visualização de George, PV, por r e depois anexa o índice da saída, i. Essa quantia (r*PV|i) é executada através da função hash_to_scalar, Hs(). Essa função calcula o hash da entrada usando o algoritmo Keccak-256, depois pega o hash resultante e calcula seu módulo com o número primo 2^255 + 27742317777372353535851937790883648493.

O termo Hs(r*PV|i), calculado no parágrafo acima, é multiplicado pelo ponto base Ed25519, G. Por fim, Maria adiciona essa quantia à chave privada de gasto de George, PS, para produzir a saída final, X, que é o endereço sigiloso.

Esse processo complicado permite que Maria esconda na blockchain a transação para George, utilizando um endereço de uso único gerado aleatoriamente que ninguém conseguirá associar a ele.

5.4.1.2 Recebendo

Tendo em conta quão bem Maria escondeu os moneroj que ela estava enviando a George (escondido por uma chave privada da transação que nem mesmo o George sabe), você deve estar se perguntando como ele poderá achá-los!

Conforme descrito no Capítulo 3, George precisa escanear a blockchain para identificar quais saídas pertençam a ele. Esse processo é bastante similar ao método que Maria utilizou para gerar o endereço.

George pega a chave pública da transação, R, da blockchain e a multiplica por sua chave privada de visualização, pV. Seguindo passos semelhantes aos de Maria, George anexa o índice da saída, i, e depois aplica a função hash_to_scalar ao termo (pV*R|i). Ele então multiplica o resultado por G e adiciona sua própria chave pública de gasto, PS. Se esse valor corresponder com a saída, então ela pertence a ele.

Em outras palavras, a carteira de George escaneia todas as transações na blockchain para identificar saídas em que X=Hs(pV*R|i)G+PS.

5.4.2 Transações confidenciais em anel

Transações confidenciais em anel (RingCT) ocultam a quantidade de moneroj enviados em uma transação. A RingCT foi implementada em Janeiro de 2017 e tornou-se obrigatória em todas as transações a partir de Setembro de 2017.

Somente transações que cunham novos moneroj na forma de recompensas coinbase têm valores visíveis, não ocultados pela RingCT. Esta é uma característica de auditoria que permite que qualquer participante da rede conte e verifique exatamente quantos moneroj já foram gerados. Após a emissão pública de moedas, essas transações são convertidas para saídas RingCT antes de serem usadas novamente.

Todas as transações que não são coinbase fazem uso da RingCT para criptografar o valor da transação. O valor de cada transação é criptografado de duas formas diferentes, e ambas formas são incluídas na mensagem.

Primeiro, o valor é criptografado por uma chave derivada de informações públicas presentes no endereço do destinatário. Essa versão é armazenada no campo edchInfo e só pode ser descriptografada e lida pelo destinatário, usando o segredo compartilhado da transação.

Em segundo lugar, o valor é integrado em um comprometimento de Pedersen, permitindo que outros usuários do Monero verifiquem a validade da transação por si mesmos. Ninguém consegue extrair o valor da transação de um comprometimento de Pedersen, porém qualquer um pode inspecionar o resultado e verificar matematicamente que as saídas são iguais às entradas. Isso previne que transações tentem falsificar moneroj.

Existem dois aspectos principais para a verificação da RingCT:

  1. O remetente prova, de forma verificável, que todas as saídas possuem um valor positivo, usando para isso uma prova de intervalo. A prova de intervalo demonstra que o número ocultado pode ser gerado como a soma de potências de 2 positivas, sem revelar quais são essas potências. Sem as provas de intervalo, um usuário trapaceiro com 5 XMR poderia criar uma transação com um par de saídas contendo +13 XMR e -8 XMR.

  2. O remetente também demonstra que as entradas são iguais às saídas, o que não é trivial de se fazer dado que as assinaturas em anel contém chamarizes para prevenir que a parte verificadora descubra a verdadeira origem das entradas e dos fundos! Comprometimentos homomórficos de Pedersen permitem que o remetente prove que uma das entradas possíveis têm uma diferença menor que zero com as saídas, sem revelar o valor no processo.

Para uma analogia mais simples, considere as seguintes equações de exemplo. Assim como os valores ocultos nas transações, você pode verificar se cada uma das equações são válidas ou não, sem precisar saber o valor de A.

A = nossa saída, ninguém sabe o valor

5A + 1A + 4A = 10A	VERDADEIRO! Verificado, mesmo sem conhecer o valor de A

6A + 4A + 2A = 14A	FALSO! Não verificado, rejeitado!

5.4.3 Assinaturas em anel

O Monero utiliza a tecnologia de assinatura em anel para proteger a privacidade de todos remetentes de transações. Uma assinatura em anel é um tipo de assinatura criptográfica que permite que um participante ativo assine uma mensagem em nome de um grupo. A chave privada do signatário ativo é misturada com informações das chaves públicas dos demais membros para produzir uma única assinatura. Qualquer pessoa pode validar a mensagem assinada usando as chaves públicas para verificar que um dos membros do anel inicializou a assinatura, porém, é impossível determinar qual membro contribuiu com a chave privada.

No contexto do Monero, a mensagem é uma transação autorizada pela assinatura em anel. A saída que realmente está sendo gasta é a do verdadeiro signatário e as chaves públicas das demais saídas (de transações passadas) são misturadas na forma de signatários chamarizes. O verdadeiro signatário e os signatários chamarizes são igualmente válidos matematicamente; a assinatura em anel resultante não pode ser examinada criptograficamente para determinar qual membro efetivamente inicializou a assinatura. Consequentemente, nenhuma pessoa externa (incluindo o destinatário) pode determinar qual das saídas referenciadas em uma transação foram realmente gastas.

Cada assinatura em anel produz uma única imagem-chave que é derivada da saída que está sendo gasta. Este é um processo criptograficamente seguro: cada saída corresponde a uma única imagem-chave e produzir a imagem-chave não revela o verdadeiro signatário no anel.

Quando o dono de uma saída a gasta em uma nova transação, a rede armazena a imagem-chave que foi produzida pela assinatura em anel. Dado que a rede não consegue identificar quais saídas estão gastas, ela mantém, em contrapartida, a relação de quais imagens-chave estão gastas! Se o dono tentasse, de forma fraudulenta, gastar a saída novamente, a mesma imagem-chave seria produzida e assim a rede saberia que precisa rejeitar a transação.

Vamos aprofundar na matemática necessária para gerar uma assinatura em anel. Ao longo deste exemplo, considere que HS seja uma função hash que retorna escalares (no campo apropriado) e que HP seja uma função hash que retorne pontos (no grupo apropriado da curva). Estamos propositalmente evitando definir esses domínios e codomínios para não complicar tanto. Considere que G seja um ponto fixo conhecido por todos.

Você irá assinar a mensagem da transação M com uma assinatura em anel. Atualmente, o Monero requer onze membros no anel para cada assinatura, porém, vamos considerar um exemplo simplificado com três membros no anel. Você tem o par de chaves (pública e privada) para a saída que está gastando e seleciona duas outras saídas (e suas chaves públicas) para servirem como chamarizes. Naturalmente, a indexação dos membros do anel deveria ser aleatória, já que a anonimidade criptográfica seria contornada se o verdadeiro signatário sempre estivesse na posição número 1. Para o exemplo simplificado com três membros no anel, suponha que sua carteira tenha selecionado aleatoriamente a posição 2 para colocar a verdadeira origem dos fundos.

Você extrai da blockchain as chaves públicas das saídas chamarizes (P1 e P3), e você tem a chave privada (p2) e a chave pública (P2 = p2G) da saída que está gastando. Você começa escolhendo um número aleatório u, que será descartado posteriormente. Primeiro você forma o seguinte compromisso, começando pelo índice imediatamente após ao que você selecionou para sua chave:

c3 = Hs(M,uG,uHp(P2))

Para formar os comprometimentos restantes, você também escolhe os números aleatórios s3 e s1 que serão usados posteriormente:

c1 = Hs(M,s3G + c3P3 , s3Hp(P3) + c3p2Hp(p2))

Note aqui que você está incluindo várias informações: a chave pública P3 que você pegou na blockchain, o número aleatório s3 que você inventou, o compromisso anterior c3 e o valor p2Hp(P2) formado a partir da sua própria chave. Você continua:

c2 = Hs(M, s1G + c1P1, s1Hp(P1) + c1p2Hp(P2))

Mas ainda não acabou! Para esconder onde sua verdadeira chave está, você inteligentemente define que s2 = u – c2 p2. A assinatura que você envia para a blockchain e para o mundo contém várias quantidades: (c1, s1, s2, s2, J), onde J = p2Hp(P2) é a imagem-chave utilizada em cada compromisso. Nós a renomeamos aqui para evidenciar o fato de que o público não sabe quais informações foram usadas para gerá-la.

Aqui está o porquê isso é inteligente: ao definir s2 = u – c2 p2, você pode reorganizar os termos de forma que u = s2 + c2 p2. Isso significa que o público vê o primeiro comprometimento c3 que você fez como sendo:

c3 = Hs(M, s2G + c2P2, s2Hp(P2) + c2p2Hp(P2))

Isso se parece exatamente igual aos demais compromissos! Embora você nunca transmita u, ele é usado de forma inteligente para fazer com que todos compromissos pareçam idênticos aos olhos de observadores. Este é o poder da assinatura em anel. Ninguém consegue determinar qual compromisso esconde sua chave verdadeira, mas todo mundo consegue verificar matematicamente que:

  • o remetente conhecia uma das chaves privadas representadas pelas chaves públicas
  • o imagem-chave foi calculada corretamente

Observe que a imagem-chave J = p2Hp(P2) foi exclusivamente calculada a partir do par de chaves da verdadeira saída, sem qualquer número aleatório ou chaves públicas de chamarizes. Assim, qualquer tentativa fraudulenta de gastar a saída uma segunda vez irá gerar uma imagem-chave idêntica. Uma vez que a rede armazena quais imagens-chave já foram usadas, qualquer tentativa de reutilizar saídas é facilmente detectada e rejeitada.

Note que o exemplo acima de uma assinatura em anel no estilo LSAG foi mostrado com propósito educativo e não deve ser utilizado como referência para nenhuma implementação em produção.

5.4.4 Recursos adicionais

Se você deseja se aventurar ainda mais nos cálculos por trás dessas tecnologias, confira o livro “Zero to Monero”, de Alonso, K.M. e Koe. O livro é um guia altamente técnico e matemático que também está disponível na forma de um PDF gratuito financiado pela comunidade.

5.5 A blockchain do Monero

Agora, você já está familiarizado com a importância e a utilidade das blockchains como registros públicos distribuídos. Esses blocos são estruturados e ordenados em um banco de dados imutável que só aceita adições, protegidos por ferramentas criptográficas que previnem quaisquer manipulações ou fraudes. A blockchain do Monero é única e discutiremos suas tecnologias e especificações nesta seção.

5.5.1 Lightning Memory Mapped Database

O Monero utiliza o sistema Lightning Memory Mapped Database (LMDB) para armazenar sua blockchain. LMDB é uma biblioteca de software que fornece um banco de dados transacional embutido e de alta performance na forma de um banco de dados chave-valor. Isso significa que ele é altamente eficiente e fácil de procurar.

O LMDB é escrito em C++ com conexões via API para várias linguagens de programação e foi desenvolvido pela Symas Corporation. Aqui estão algumas características do LMDB:

  • Armazenamento de pares chave/dados arbitrários como arrays de bytes
  • Capacidade de pesquisa baseada em intervalos
  • Suporte para uma única chave com múltiplos itens de dados
  • Métodos avançados para anexar registros ao final do banco de dados, resultando em considerável aumento de performance quando comparado a bancos de dados similares

5.5.2 A estrutura de um bloco

O padrão CryptoNote define especificações para armazenar e delimitar dados dentro de blocos e na blockchain. A estrutura do bloco contém três componentes principais:

  • O cabeçalho do bloco
  • A transação base
  • Uma lista de identificadores de transações (hashes das transações mineradas no bloco)

5.5.2.1 O cabeçalho do bloco

Cada bloco começa com um cabeçalho que contém metadados importantes. O campo “major_version” define as regras de análise do cabeçalho para que ele seja interpretado corretamente. O campo “minor_version” define os detalhes da interpretação que não estão relacionados com a análise principal do cabeçalho.

Mesmo se a versão secundária for desconhecida, sempre será seguro analisar o cabeçalho de um bloco para uma versão principal em particular. Analisar o cabeçalho do bloco com uma versão principal desconhecida é arriscado, já que o conteúdo do cabeçalho do bloco pode ser mal interpretado.

Campo Tipo Conteúdo
major_version varint Versão principal do cabeçalho do bloco
minor_version varint Versão secundária do cabeçalho do bloco
timestamp varint Data de criação do bloco (horário UNIX)
prev_id hash Identificador do bloco anterior
nonce 4 bytes Qualquer valor que é utilizado no algoritmo de consenso da rede

5.5.2.2 Transação base

Todo bloco válido contém uma única transação base que direciona a recompensa coinbase para o minerador. Essa transação base deve seguir as regras de emissão de moeda e incluir o campo da altura do bloco.

5.5.2.3 Lista de identificadores de transações

Campo Tipo Conteúdo
version varint Versão do formato da transação
unlock_time varint Horário UNIX
input_num varint Número de entradas. Sempre 1 para transações base
input_type byte Sempre 0xff para transações base
height varint Altura do bloco que contém a transação
output_num varint Número de saídas
outputs array Lista de saídas em forma de array

A transação base é seguida por uma lista de identificadores de transações. Esses identificadores são calculados pegando o hash Keccak do corpo da transação. A lista começa com a quantidade de identificadores e é seguida pelos identificadores em si (se o bloco não estiver vazio).

5.5.2.4 Cálculo do identificador do bloco

O identificador de um bloco é produzido calculando-se o hash Keccak-256 dos seguintes dados:

  • tamanho do block_header
  • block_header
  • hash da Merkle root
  • número de transações (varint)

O hash da Merkle root “anexa” as transações referenciadas no corpo do bloco ao cabeçalho do bloco: uma vez que o hash da Merkle root é fixado, as transações não podem ser modificadas. Essa característica de segurança mantém as blockchains seguras contra manipulação ou qualquer tipo de modificação retroativa.

5.5.3 A economia da mineração

Recompensas do bloco e taxas foram mencionadas de forma conceitual nos Capítulos 2 e 4. Agora, você irá realmente aprender sobre a complexidade do tamanho de bloco, das recompensas e sua relação com a taxas.

5.5.3.1 Recompensa coinbase da mineração

Conforme discutido no Capítulo 4, todos moneroj são originados na forma de recompensas pagas aos mineradores por completarem blocos com sucesso. O tamanho desse pagamento coinbase depende a oferta atual (A) e o número inicial de unidades atômicas (S = 264 – 1). Uma unidade atômica é a menor divisão de Monero reconhecida atualmente pela rede (1x10^-12 XMR):

Recompensa base = 2 * ((S – A) * 2-20 * 10-12)

O Monero possui uma emissão em cauda, que é uma pequena recompensa fixa que continuará existindo mesmo após a maior parte da oferta ter sido minerada. A recompensa base mínima do Monero é 0,6 XMR por bloco, assim os mineradores nunca terão que subsistir somente das taxas.

5.5.3.2 Tamanho de bloco dinâmico

O Monero possui um tamanho de bloco dinâmico, possibilitando ajustes contínuos conforme a rede cresce, em contraste com muitas criptomoedas que utilizam um tamanho de bloco estático (fixo). Por exemplo, o tamanho de bloco inicial do Bitcoin fixo em 1 MB gerou problemas de escalabilidade ao limitar o número de transações que poderiam ser incluídas em cada bloco (consequentemente limitando o volume total de transações na rede). Em 2017, esse gargalo resultou em períodos com taxas extremamente altas e atrasos no processamento das transações. Várias soluções foram propostas e apresentadas, resultando em um período de debates contenciosos.

Para evitar esses problemas, o Monero utiliza um mecanismo com tamanho de bloco dinâmico que permite que os mineradores utilizem blocos maiores para acomodar o aumento de tráfego na rede. Porém, se o tamanho de bloco fosse mantido sem quaisquer restrições, a rede Monero estaria vulnerável a ataques de spam, por exemplo, quando várias pequenas transações são enviadas com o objetivo de exaurir a rede e os recursos de armazenamento, fazendo com que a blockchain expanda muito rapidamente.

Para impedir o crescimento excessivo do tamanho de bloco, o protocolo de mineração do Monero inclui uma função de multa que reduz a recompensa coinbase em blocos acima do tamanho “normal”. Os autores do CryptoNote original incluíram essa regra de consenso para limitar a taxa de expansão do tamanho de bloco e evitar uma rápida sobrecarga da blockchain.

Se um bloco é minerado com tamanho (B) maior que a mediana dos últimos 100 blocos, parte da recompensa base é retida, de acordo com a fórmula:

Multa = RecompensaBase * ((B / MN) – 1)2

Os mineradores recebem a recompensa completa para qualquer tamanho de bloco até 300 kB; para qualquer bloco maior, a função de multa “entra em vigor”. O tamanho máximo de bloco é 2 * MN, ponto no qual a recompensa coinbase é retida por completo.

5.5.3.3 Taxas

Quando o volume de transações está baixo e o tamanho de bloco pequeno, os mineradores são recompensados com a coinbase completa e as taxas são mínimas.

Entretanto, imagine um cenário diferente: O que acontece se a mediana do tamanho dos últimos 100 blocos crescer mais que o tamanho de bloco sem multa (300 kB)? Se isso acontecer, o algoritmo de taxas dinâmicas entra em cena!

As taxas são calculadas com base no peso em kB das transações. Transações maiores (“mais pesadas”) implicam em uma taxa maior. O cálculo da taxa dinâmica é complexo, pois leva em consideração vários fatores do ecossistema do Monero e a prioridade da transação (o remetente pode incentivar os mineradores a incluírem mais rapidamente uma transação urgente se optar por uma taxa maior). As taxas necessárias para ser competitivo em um bloco próximo são calculadas de acordo com a expressão:

Taxa por kB = (R/R0) * (M0/M) * F0 * (60/300) * 4
  • R é a recompensa base
  • R0 é recompensa base de referência (10 XMR)
  • M é o limite do tamanho de bloco
  • M0 é o limite mínimo do tamanho de bloco (300 kB)
  • F0 é 0,002 XMR
  • 60/300 é o fator de ajuste para levar em conta o aumento no limite do tamanho de bloco sem multa (ajustado de 60 kB para 300 kB em 2017)
  • 4 é o fator de ajuste para levar em conta o multiplicador da taxa padrão (o menor nível de taxa utiliza um multiplicador de x1 e uma transação com prioridade normal utiliza x4)

Assim, as taxas levam em consideração o aumento da mediana do tamanho de bloco em relação ao tamanho mínimo de bloco. Por exemplo, um tamanho de bloco de 600 kB (duas vezes o mínimo) reduz as taxas pela metade.

Idealmente, um aumento na taxa de câmbio e uso do Monero resultaria em uma redução das taxas absolutas (por exemplo, em termos de XMR). Esse mecanismo de redução das taxas tem menos efetividade durante aumentos radicais de preço que sejam desproporcionalmente maiores que o aumento no volume de transações (e consequentemente, tamanho de bloco).

O algoritmo de taxas dinâmicas foi projetado para funcionar quando a mediana do tamanho de bloco permanece acima de 300 kB consistentemente. Embora o sistema tente levar em consideração do aumento de preço, o uso não é perfeitamente correlacionado ao preço, não sendo deste modo um indicador perfeito.

5.5.4 Bulletproofs

Bulletproofs são uma nova característica que reduzem drasticamente o tamanho das transações, que por sua vez reduzem as taxas gerais por transação! As transações do Monero costumavam ser bastante grandes (geralmente > 12 kB), assim, as Bulletproofs foram uma melhoria muito aguardada.

As características de privacidade do Monero necessitam de vários “testes” complexos durante a validação de transações para prevenir abusos e spam. Isso inclui a verificação dos valores ocultados, das taxas e a confirmação de que nenhum gasto duplo está ocorrendo.

Muitos desenvolvedores já se depararam com erros de “transbordo”, que ocorre quando uma operação cria um valor fora do limite que pode ser representado. Infelizmente, “infinito” é um conceito abstrato para a computação, que muitas vezes encontram obstáculos ao trabalhar com número grandes.

Uma vez que a RingCT oculta o valor das transações, cálculos complicados são necessários para verificar se as entradas correspondem as saídas. As propriedades algébricas úteis dos comprometimentos são valiosas por permitirem transações ocultadas cuja validade pode ser confirmada por qualquer participante.

Contudo, é igualmente importante garantir que os valores sejam positivos e não causem um erro de transbordo. E é aqui que as provas de intervalo entram, permitindo que qualquer um verifique que um comprometimento representa uma quantidade dentro de um intervalo especificado, sem revelar nada mais sobre seu valor. Cada prova de intervalo costumava ocupar ~7 kB, assim, elas correspondiam a maior parcela do tamanho da transação. A maioria das transações possui duas saídas (o endereço de destino e o troco), necessitando pelo menos ~12 kB.

As Bulletproofs aplicam alguns truques matemáticos inteligentes para construir a prova de intervalo usando um mecanismo mais eficiente. Isso reduz o tamanho de uma única prova de intervalo para ~2 kB!

Antes das Bulletproofs, transações com múltiplas saídas requeriam múltiplas provas de intervalo separadas. Consequentemente, o tamanho da transação subia linearmente conforme o número de saídas (por exemplo, 1 saída = 7 kB, 2 saídas = 14 kB). Com as Bulletproofs, em contrapartida, o tamanho da transação sobe em escala logarítmica conforme o número de saídas (por exemplo, 1 saída = 2 kB, 2 saídas = 2,5 kB).

Ao reduzir o tamanho de cada prova de intervalo e permitir que elas sejam combinadas de uma maneira mais eficiente, as Bulletproofs diminuem drasticamente o tamanho das transações e consequentemente as taxas. As Bulletproofs foram ativadas na atualização de rede do Monero (v0.13.0) em Outubro de 2018, na forma de uma característica opcional que tornou-se obrigatória na atualização subsequente.

5.6 Fungibilidade

Como você pode ver, o Monero utiliza diversos protocolos criptográficos altamente sofisticados para proteger sua rede e aderir aos princípios fundamentais de privacidade e descentralização. Com a ajuda do Laboratório de Pesquisa do Monero e várias entidades de auditoria, o Monero continuará a identificar e validar tecnologias criptográficas de ponta para torná-las o mais rápido, seguro, privado e eficiente possível.

Uma das principais características do dinheiro é uma propriedade conhecida como fungibilidade. Fungibilidade significa que uma unidade de valor é igual a outra unidade de valor com a mesma quantidade. Um grama de ouro é igual a um grama de ouro. Ou em nosso caso, um Monero é igual um Monero. Os protocolos de encriptação utilizados pelo Monero tornam-o fungível e permitem que ele alcance seu objetivo de ser dinheiro digital de verdade.

Criptomoedas que são transparentes em sua camada principal (base layer) não utilizam essas camadas de encriptação e, como resultado, não são fungíveis. Uma moeda que pode ser rastreada até a darknet será manchada e moedas que foram recém cunhadas ou vendidas em leilões por agências governamentais poderão vender a um prêmio (mais caras). No caso de criptomoedas transparentes, uma moeda não é igual a outra moeda com o mesmo valor. Elas não são fungíveis. E isso é genuinamente problemático para o objetivo de ser dinheiro digital.

Então, além dos protocolos sofisticados de encriptação do Monero manterem boa segurança, privacidade e descentralização, eles também garantem a fungibilidade, um componente essencial do dinheiro.