Estamos interessados há muito tempo na questão da anonimidade nas criptomoedas e tentamos acompanhar o desenvolvimento das tecnologias nessa área. Em nossos artigos, já discutimos detalhadamente os princípios de funcionamento no Monero, assim como fizemos um das tecnologias existentes nesse campo. No entanto, todas as criptomoedas anônimas atualmente são baseadas no modelo de dados proposto pelo Bitcoin — Unspent Transaction Output (UTXO). Para blockchains baseados em conta, como o Ethereum, as soluções existentes para implementar anonimidade e confidencialidade (por exemplo, ou ) tentaram replicar o modelo UTXO em contratos inteligentes.
Em fevereiro de 2019, um grupo de pesquisadores da Universidade de Stanford e da Visa Research lançamos intitulado "Zether: Em Direção à Privacidade no Mundo dos Contratos Inteligentes". Os autores propuseram pela primeira vez uma abordagem para garantir anonimidade em blockchains baseados em conta e apresentaram duas variantes de contratos inteligentes: para transações confidenciais (ocultação de saldos e valores de transferências) e anônimas (ocultação do recipiente e do remetente). Achamos a tecnologia proposta interessante e gostaríamos de compartilhar como ela funciona, além de discutir por que a questão da anonimidade em blockchains baseados em conta é considerada muito complexa e se os autores conseguiram resolvê-la completamente.
Sobre o funcionamento desses modelos de dados
No modelo UTXO, uma transação consiste em "entradas" e "saídas". O equivalente direto às "saídas" são as cédulas em sua carteira: cada "saída" tem um determinado valor. Quando você paga a alguém (forma uma transação), você gasta uma ou mais "saídas", tornando-as "entradas" na transação, e a blockchain as marca como gastas. O recipiente do seu pagamento (ou você mesmo, se precisar de troco) recebe novas "saídas" geradas. Esquematicamente, isso pode ser representado assim:

Blockchains baseados em conta funcionam de maneira semelhante à sua conta bancária. Eles operam apenas com o saldo da sua conta e o valor da transferência. Quando você transfere um valor da sua conta, não queima nenhuma "saída", e a rede não precisa lembrar quais moedas foram gastas e quais não foram. No caso mais simples, a verificação da transação se resume a verificar a assinatura do remetente e o saldo de sua conta:

Análise da tecnologia
A seguir, vamos discutir como o Zether oculta o valor das transações, o destinatário e o remetente. Ao descrever os princípios de seu funcionamento, destacaremos as diferenças entre as versões confidencial e anônima. Como garantir a confidencialidade em blockchains baseadas em contas é muito mais fácil, algumas das limitações impostas pela anonimização não serão relevantes para a versão confidencial da tecnologia.
Ocultação de saldos e valores das transferências
Para a criptografia dos saldos e valores das transferências no Zether, é utilizada um esquema de criptografia . Funciona da seguinte forma. Quando Alice quer enviar a Bob b moedas para o endereço (sua chave pública) Y, ela escolhe um número aleatório r e criptografa o valor:

onde C — valor criptografado, D — valor auxiliar necessário para descriptografar esse valor, G — um ponto fixo na curva elíptica, a multiplicação da qual pelo segredo resulta na chave pública.
Quando Bob recebe esses valores, ele simplesmente os acrescenta ao seu saldo, que também está criptografado, o que torna esse esquema conveniente.
Da mesma forma, Alice subtrai de seu saldo os mesmos valores, usando como Y sua chave pública.
Ocultação do destinatário e do remetente
A mistura de 'saídas' em UTXO surgiu desde os primórdios das criptomoedas e ajuda a ocultar o remetente. Para isso, o próprio remetente, ao realizar a transferência, seleciona 'saídas' aleatórias na blockchain e as mistura com as suas. Em seguida, assina as 'saídas' com uma assinatura em anel — um mecanismo criptográfico que permite convencer o verificador de que entre as 'saídas' misturadas estão as moedas do remetente. As moedas misturadas, é claro, não são gastas.
No entanto, para ocultar o destinatário, não conseguiremos gerar 'saídas' falsas. Portanto, em UTXO, cada 'saída' tem seu próprio endereço único, que está criptograficamente ligado ao endereço do destinatário dessas moedas. Atualmente, não há como identificar a conexão entre o endereço único da 'saída' e o endereço do destinatário sem conhecer suas chaves secretas.
No modelo baseado em contas, não podemos usar endereços temporários (caso contrário, isso já seria um modelo de "saídas"). Portanto, é necessário misturar o destinatário e o remetente entre outras contas na blockchain. Nesse processo, as contas misturadas são debitadas de 0 moedas criptografadas (ou adicionadas com 0 — no caso da mistura do destinatário), sem mudar seu saldo real.
Como o remetente e o destinatário sempre têm um endereço fixo, surge a necessidade de usar os mesmos grupos para mistura em transferências para os mesmos endereços. É mais fácil entender isso com um exemplo.
Suponha que Alice decidiu fazer uma doação para a organização de caridade de Bob, mas prefere que essa transferência permaneça anônima para um observador externo. Assim, para se ocultar no campo do remetente, ela insere as contas de Adam e Adele. E para esconder Bob — no campo do destinatário, ela adiciona as contas de Ben e Bill. Na próxima doação, Alice decidiu adicionar Alex e Amanda ao seu campo e Bruce e Benjamin ao de Bob. Neste caso, ao analisar a blockchain, haverá apenas um par de participantes sobreposto nessas duas transações — Alice e Bob, o que desanonimiza essas transações.

Corridas de Transações
Como já mencionamos, para ocultar seu saldo em sistemas baseados em contas, o usuário cifra seu saldo e o valor da transferência. Neste processo, ele deve provar que o saldo em sua conta permanece não negativo. O problema é que, ao criar uma transação, o usuário constrói a prova em relação ao seu estado atual da conta. E se Bob enviar uma transação para Alice, e ela for aceita antes da enviada por Alice? Então, a transação de Alice será considerada inválida, pois a prova de saldo foi construída antes da aceitação da transação de Bob.

A primeira solução que vem à mente em tal situação é congelar a conta até a realização da transação. Mas essa abordagem não é viável, pois além da complexidade de resolver essa tarefa em um sistema distribuído, em um esquema anônimo, não fica claro qual conta deve ser bloqueada.
Para resolver esse problema, a tecnologia separa transações de entrada e saída: o gasto de fundos tem um efeito imediato no saldo, enquanto as receitas têm um efeito retardado. Para isso, introduz-se o conceito de "épocas" — grupos de blocos de tamanho fixo. A "época" atual é determinada pela divisão da altura do bloco pelo tamanho do grupo. Ao processar uma transação, a rede atualiza imediatamente o saldo do remetente, enquanto os fundos do destinatário são acumulados. Os fundos acumulados ficam disponíveis para o destinatário do pagamento somente com o início de uma nova "época".
Como resultado, o usuário pode enviar transações independentemente de quão frequentemente ele recebe fundos (dentro do que seu saldo permitir, é claro). O tamanho da época é determinado com base na rapidez com que os blocos se espalham pela rede e quão rápido uma transação entra em um bloco.
Essa solução funciona bem em casos de transferências confidenciais, no entanto, com transações anônimas, como veremos mais adiante, ela cria sérios problemas.
Proteção contra ataques de repetição
Em blockchains baseados em contas, cada transação é assinada pela chave privada do remetente, o que convence o verificador de que a transação não foi alterada e foi criada pelo proprietário dessa chave. Mas o que acontece se um invasor que está ouvindo o canal de transmissão interceptar essa mensagem e enviar uma segunda exatamente igual? O verificador irá comparar a assinatura da transação e ficará convencido de sua autoria, e a rede irá deduzir a mesma quantia do saldo do remetente novamente.
Esse ataque é chamado de ataque de repetição. No modelo UTXO, tais ataques não são relevantes, pois o invasor tentaria usar saídas gastas, o que por si só não é válido e é rejeitado pela rede.
Para evitar que isso aconteça, uma campo com dados aleatórios é embutido na transação, que é chamado de nonce ou simplesmente "sal". Ao re-enviar a transação com o "sal", o verificador verifica se esse nonce já foi utilizado anteriormente e, se não, considera a transação válida. Para não armazenar todo o histórico de nonces dos usuários na blockchain, geralmente na primeira transação ele é considerado igual a zero e depois aumenta em um. A rede só precisa verificar se o nonce da nova transação é diferente do anterior por um unidade.
Em um esquema anônimo de transferências, surge o problema da validação dos nonces das transações. Não podemos vincular o nonce explicitamente ao endereço do remetente, pois isso, evidentemente, desanonimiza a transferência. Também não podemos incrementar os nonces de todas as contas envolvidas, pois isso pode entrar em conflito com outras transferências que estão sendo processadas.
Os autores do Zether sugerem gerar o nonce criptograficamente — dependendo da "época". Por exemplo:

Aqui x — a chave secreta do remetente, e Gepoch — um gerador adicional para a época, obtido pela hash de uma string do tipo 'Zether + '. Agora, aparentemente, o problema está resolvido — não revelamos o nonce do remetente e não interferimos nos nonces dos participantes não envolvidos. Mas essa abordagem impõe uma limitação séria: uma conta pode enviar não mais do que uma transação por 'época'. Esse problema, infelizmente, permanece sem solução e, neste momento, torna a versão anônima do Zether, em nossa opinião, pouco utilizável.
Dificuldade das provas de zero conhecimento
No UTXO, o remetente deve provar à rede que não está gastando um montante negativo, caso contrário, a geração de novas moedas do nada se torna possível (por que isso é possível, escrevemos em uma das anteriores ). E também assinar as "entradas" com uma assinatura em anel, para provar que entre as moedas misturadas existem fundos que lhe pertencem.
Na versão anônima de um blockchain baseado em contas, as expressões para prova tornam-se muito mais complexas. O remetente prova que:
- O montante enviado é positivo;
- O saldo permanece não negativo;
- O remetente criptografou corretamente os montantes das transferências (incluindo os nulos);
- O saldo só muda para o remetente e o destinatário;
- O remetente possui a chave secreta da sua conta e realmente está na lista de remetentes (entre os misturados);
- O nonce utilizado na transação é formado corretamente.
Para tal prova complexa, os autores utilizam uma mistura (um dos autores, a propósito, participou de sua criação) e , a qual chamam de Sigma-bullets. A prova formal de tal afirmação é uma tarefa bastante complicada e limita fortemente o número de interessados em implementar a tecnologia.
Qual é o resultado?
Na nossa opinião, a parte Zether que traz privacidade para blockchains baseados em contas pode ser utilizada já agora. Mas, neste momento, a versão anônima da tecnologia impõe sérias limitações ao seu uso, e sua complexidade dificulta a implementação. No entanto, não devemos desconsiderar o fato de que os autores a lançaram apenas há alguns meses, e talvez alguém encontre uma solução para os problemas atuais. Afinal, é assim que a ciência avança.
Fonte: habr.com
