Introdução: Recentemente, Vitalik e alguns estudiosos co-publicaram um novo artigo, mencionando como o Tornado Cash implementa um esquema anti-lavagem de dinheiro (essencialmente permitindo ao sacador provar que seu registro de depósito pertence a um conjunto que não contém dinheiro sujo), mas o artigo carece de uma interpretação detalhada da lógica do negócio e dos princípios do Tornado Cash, deixando alguns leitores perplexos.
Vale ressaltar que os projetos de privacidade representados pela Tornado são aqueles que realmente utilizam a propriedade de conhecimento zero do algoritmo ZK-SNARK, enquanto a maioria dos projetos rotulados com ZK apenas usa a concisão do ZK-SNARK. As pessoas frequentemente confundem a diferença entre Prova de Validade e ZK, e a Tornado serve como um excelente caso para entender a aplicação de ZK. O autor deste artigo escreveu sobre os princípios da Tornado em 2022 para a Pesquisa Web3Caff e hoje seleciona e expande algumas seções desse artigo, organizando-o neste texto para entender sistematicamente o Tornado Cash.
Link do Artigo Original: https://research.web3caff.com/zh/archives/2663?ref=157
Tornado Cash utiliza um protocolo de mistura de moedas baseado em provas de conhecimento zero, com sua versão mais antiga lançada em 2019 e uma nova versão beta lançada no final de 2021. A versão mais antiga do Tornado alcançou um alto nível de descentralização, com seus contratos on-chain sendo de código aberto e não controlados por nenhum mecanismo de multiassinatura, e seu código frontend também sendo de código aberto e backup na rede IPFS. Devido à estrutura mais simples e compreensível da versão antiga do Tornado, este artigo se concentra em explicá-lo. A ideia principal por trás do Tornado é misturar um grande número de ações de depósito e retirada. Depois de depositar tokens no Tornado, os depositantes apresentam uma Prova ZK para provar que fizeram um depósito e, em seguida, retiram para um novo endereço, cortando assim o vínculo entre os endereços de depósito e retirada.
Mais especificamente, o Tornado age como uma caixa de vidro cheia de moedas depositadas por muitas pessoas. Podemos ver quem depositou as moedas, mas como as moedas são altamente homogeneizadas, é difícil rastrear qual moeda foi depositada por quem se alguém desconhecido retirar uma moeda.
(Fonte: rareskills)Este cenário é um tanto comum; por exemplo, quando trocamos ETH em uma pool Uniswap, não podemos saber de quem estamos recebendo o ETH, pois muitos forneceram liquidez à Uniswap. No entanto, a diferença é que toda vez que você troca tokens na Uniswap, você precisa usar outros tokens como custo equivalente, e não pode transferir fundos de forma 'privada' para outra pessoa; enquanto que, com um mixer, você só precisa mostrar uma prova de depósito para sacar. Para que as ações de depósito e saque pareçam homogêneas, cada depósito em uma pool Tornado e cada saque dela são mantidos consistentes em termos de quantidade. Por exemplo, se houver 100 depositantes e 100 sacadores em uma pool, embora visíveis, eles parecem não estar ligados, e a quantidade depositada e sacada por cada um é a mesma.
Isso pode obscurecer a rastreabilidade das transferências de fundos, oferecendo uma conveniência natural para transações anonimizadas. A questão chave é: como um sacador prova que fez um depósito?
O endereço que faz o saque não está vinculado a nenhum endereço de depósito, então como sua elegibilidade para saque pode ser determinada? O método mais direto parece ser o sacador revelar qual registro de depósito é seu, mas isso revelaria diretamente sua identidade. É aqui que entram as provas de conhecimento zero. Ao apresentar uma prova ZK de que tem um registro de depósito no contrato Tornado que ainda não foi retirado, um sacador pode iniciar com sucesso uma retirada. As provas de conhecimento zero protegem inerentemente a privacidade, revelando apenas que a pessoa realmente fez um depósito no pool de fundos, sem revelar a qual depositante ela corresponde.
Para provar 'Eu fiz um depósito no pool de fundos do Tornado' pode ser traduzido para 'Meu registro de depósito pode ser encontrado no contrato do Tornado.' Se usarmos Cn para representar um registro de depósito, o problema se torna: dado que o conjunto de registros de depósito do Tornado é {C1, C2, ...C100...}, o sacador, Bob, prova que usou sua chave para gerar algum Cn nos registros de depósito sem revelar qual Cn específico é. Isso envolve a propriedade especial de Prova de Merkle. Todos os registros de depósito do Tornado são incorporados em uma Árvore de Merkle construída on-chain, com esses registros como seus nós folha de nível inferior. O número total de folhas é cerca de 2^20 > 1 milhão, a maioria das quais está em estado em branco (atribuído um valor inicial). Sempre que um novo depósito ocorre, o contrato registra seu valor único, Compromisso, em uma folha e, em seguida, atualiza a raiz da Árvore de Merkle.
Por exemplo, se o depósito de Bob foi o 10.000º na história do Tornado, o valor característico Cn associado a este depósito seria inserido no 10.000º nó folha da Árvore de Merkle, ou seja, C10000 = Cn. O contrato então calcula automaticamente uma nova Raiz e a atualiza. Para economizar recursos computacionais, o contrato Tornado armazena em cache dados de um lote de nós previamente alterados, como Fs1, Fs2 e Fs0 no diagrama abaixo.
(Fonte: RareSkills)
A Prova de Merkle, por sua natureza, é concisa e leve, aproveitando a simplicidade das estruturas de dados em árvore nos processos de busca/rastreamento. Para provar externamente que uma transação TD existe em uma Árvore de Merkle, só é necessário fornecer uma Prova de Merkle correspondente à Raiz, o que é bastante direto. Se a Árvore de Merkle for especialmente grande, com 2^20 folhas no nível inferior de potência (ou seja, 1 milhão de registros de depósito), uma Prova de Merkle só precisaria incluir os valores de 21 nós, o que é muito curto.
Para provar que uma transação H3 está de fato contida em uma Árvore de Merkle, deve-se demonstrar que usando H3 e outras partes de dados na Árvore de Merkle, a Raiz pode ser gerada, e os dados necessários para gerar a Raiz (incluindo Td) constituem a Prova de Merkle. Quando Bob faz um saque, ele precisa provar que seu certificado corresponde a um hash de depósito Cn registrado na Árvore de Merkle no livro-razão do Tornado. Em outras palavras, ele deve provar duas coisas: Cn existe dentro da Árvore de Merkle fictícia do Tornado na cadeia, especificamente construindo uma Prova de Merkle contendo Cn; Cn está associado ao certificado de depósito de Bob.
No código frontend da interface do usuário do Tornado, muitas funcionalidades são pré-implementadas. Quando um depositante abre a página da Tornado Cash e clica no botão de depósito, o código frontend acompanhante gera localmente dois números aleatórios, K e r. Em seguida, calcula o valor de Cn=Hash(K, r) e passa Cn (referido como compromisso no diagrama abaixo) para o contrato Tornado, que o insere na Árvore de Merkle registrada por este último. Essencialmente, K e r atuam como chaves privadas. Eles são cruciais, e o sistema solicita aos usuários que os salvem com segurança. K e r são necessários novamente durante a retirada.
(A opção de encryptedNote permite que os usuários criptografem o credencial K e r com uma chave privada e armazenem-na no blockchain para evitar esquecimento) Importante, todas essas operações ocorrem off-chain, o que significa que o contrato Tornado e observadores externos não têm conhecimento de K e r. Se K e r vazarem, é semelhante ao roubo de chaves privadas da carteira.
Ao receber um depósito de um usuário e a submissão de Cn=Hash(K, r), o contrato Tornado registra Cn na camada inferior da Árvore de Merkle como um novo nó folha, também atualizando o valor da Raiz. Portanto, Cn está diretamente ligado à ação de depósito do usuário, permitindo que terceiros saibam qual usuário corresponde a cada Cn, quem depositou tokens no mixer e os registros de depósito Cn de cada depositante.
Durante o processo de retirada, o retirante insere a credencial/chave privada (os números aleatórios K e r gerados durante o depósito) na página da web frontend. O programa no código frontal do Tornado Cash usa K e r, Cn=Hash(K, r), e a Prova de Merkle correspondente a Cn como parâmetros de entrada para gerar uma Prova de Conhecimento Zero. Isso prova que Cn existe na Árvore de Merkle como um registro de depósito, e K e r são as credenciais correspondentes a Cn. Esta etapa essencialmente prova: Eu conheço a chave correspondente a um registro de depósito na Árvore de Merkle. Quando a Prova de Conhecimento Zero é enviada para o contrato do Tornado, esses quatro parâmetros são ocultados, protegendo a privacidade. A geração da Prova de Conhecimento Zero envolve parâmetros adicionais, incluindo a raiz de Merkle registrada no contrato do Tornado no momento da retirada, um endereço de destinatário personalizado A, e um identificador nf para evitar ataques de repetição. Esses três parâmetros são publicamente divulgados no blockchain, o que não compromete a privacidade.
Um detalhe a notar é o uso de dois números aleatórios, K e r, para gerar Cn em vez de um único número aleatório, fornecendo maior segurança contra colisões. A representa o endereço do destinatário da retirada, escolhido pelo retirante. O identificador nf, projetado para evitar ataques de repetição, é calculado como nf=Hash(K), onde K é um dos dois números aleatórios usados na etapa de depósito para gerar Cn. Isso vincula nf diretamente a Cn, estabelecendo uma correlação de um para um entre cada Cn e seu nf correspondente. O objetivo de evitar ataques de repetição é devido à característica de design do mixer, que mantém a associação entre os valores de retirada e folhas específicas da árvore de Merkle (Cn) desconhecida, permitindo o potencial abuso de retiradas repetidas até que o pool de fundos seja esgotado.
O identificador nf funciona de forma semelhante ao nonce associado a cada endereço Ethereum, impedindo repetições de transações. Quando ocorre um saque, uma verificação garante que o nf submetido não tenha sido usado antes; se não utilizado, o saque é válido, e o nf é registrado. Qualquer tentativa de gerar um nf não associado a nenhum depósito registrado Cn falhará em produzir uma Prova ZK válida, tornando o saque sem sucesso.
Se alguém gerar aleatoriamente um contrato não fungível (nf) não registrado, funcionaria? Claro que não. Quando o sacador gera uma Prova de Conhecimento Zero (Prova ZK), ele deve garantir que nf seja igual ao Hash (K), onde o número aleatório K está associado ao registro de depósito Cn. Isso significa que nf está vinculado a um depósito registrado Cn. Se alguém fabricar um nf arbitrariamente, este nf não corresponderá a nenhum registro de depósito, tornando impossível gerar uma Prova ZK válida. Consequentemente, o processo de retirada não pode ser concluído com êxito e a operação de retirada falhará. Alguns podem perguntar: é possível prosseguir sem nf? Uma vez que o retirador precisa enviar uma prova ZK durante a retirada para provar sua associação com um determinado Cn, por que não apenas verificar se a Prova ZK correspondente foi submetida ao blockchain toda vez que uma retirada ocorre? No entanto, essa abordagem é altamente dispendiosa porque o contrato Tornado Cash não armazena permanentemente as provas ZK passadas devido ao desperdício significativo de espaço de armazenamento. Comparar cada nova prova ZK enviada ao blockchain com provas existentes é menos eficiente do que definir um pequeno identificador como nf e armazená-lo permanentemente.
De acordo com o exemplo de código da função de retirada, os parâmetros necessários e a lógica de negócios são os seguintes: O usuário envia uma Prova ZK e nf (NullifierHash) = Hash (K), especifica um endereço de destinatário para a retirada, e a Prova ZK oculta os valores de Cn, K e r, tornando impossível para os outsiders determinar a identidade do usuário. O destinatário muitas vezes usa um endereço novo e limpo, que não revela informações pessoais.
No entanto, há um problema menor: quando os usuários sacam para permanecerem indetectáveis, muitas vezes iniciam a transação de saque a partir de um endereço recém-criado. Nesse momento, o novo endereço não tem ETH para pagar as taxas de gás. Portanto, ao iniciar um saque, o endereço de saque deve declarar explicitamente um relayer para pagar a taxa de gás em seu nome. Em seguida, o contrato de mistura deduz uma parte do saque do usuário para compensar o relayer.
Em resumo, o Tornado Cash pode obscurecer a conexão entre os retirantes e os depositantes. Em situações com uma grande base de usuários, é como um criminoso se misturando em uma multidão em uma área movimentada, tornando difícil para a polícia rastrear. O processo de retirada envolve o uso de ZK-SNARKs, com a parte da testemunha oculta contendo informações críticas sobre o retirante, que é um aspecto-chave de todo o misturador. Atualmente, o Tornado parece ser um dos projetos de camada de aplicação mais engenhosos relacionados ao ZK.
Поділіться
Introdução: Recentemente, Vitalik e alguns estudiosos co-publicaram um novo artigo, mencionando como o Tornado Cash implementa um esquema anti-lavagem de dinheiro (essencialmente permitindo ao sacador provar que seu registro de depósito pertence a um conjunto que não contém dinheiro sujo), mas o artigo carece de uma interpretação detalhada da lógica do negócio e dos princípios do Tornado Cash, deixando alguns leitores perplexos.
Vale ressaltar que os projetos de privacidade representados pela Tornado são aqueles que realmente utilizam a propriedade de conhecimento zero do algoritmo ZK-SNARK, enquanto a maioria dos projetos rotulados com ZK apenas usa a concisão do ZK-SNARK. As pessoas frequentemente confundem a diferença entre Prova de Validade e ZK, e a Tornado serve como um excelente caso para entender a aplicação de ZK. O autor deste artigo escreveu sobre os princípios da Tornado em 2022 para a Pesquisa Web3Caff e hoje seleciona e expande algumas seções desse artigo, organizando-o neste texto para entender sistematicamente o Tornado Cash.
Link do Artigo Original: https://research.web3caff.com/zh/archives/2663?ref=157
Tornado Cash utiliza um protocolo de mistura de moedas baseado em provas de conhecimento zero, com sua versão mais antiga lançada em 2019 e uma nova versão beta lançada no final de 2021. A versão mais antiga do Tornado alcançou um alto nível de descentralização, com seus contratos on-chain sendo de código aberto e não controlados por nenhum mecanismo de multiassinatura, e seu código frontend também sendo de código aberto e backup na rede IPFS. Devido à estrutura mais simples e compreensível da versão antiga do Tornado, este artigo se concentra em explicá-lo. A ideia principal por trás do Tornado é misturar um grande número de ações de depósito e retirada. Depois de depositar tokens no Tornado, os depositantes apresentam uma Prova ZK para provar que fizeram um depósito e, em seguida, retiram para um novo endereço, cortando assim o vínculo entre os endereços de depósito e retirada.
Mais especificamente, o Tornado age como uma caixa de vidro cheia de moedas depositadas por muitas pessoas. Podemos ver quem depositou as moedas, mas como as moedas são altamente homogeneizadas, é difícil rastrear qual moeda foi depositada por quem se alguém desconhecido retirar uma moeda.
(Fonte: rareskills)Este cenário é um tanto comum; por exemplo, quando trocamos ETH em uma pool Uniswap, não podemos saber de quem estamos recebendo o ETH, pois muitos forneceram liquidez à Uniswap. No entanto, a diferença é que toda vez que você troca tokens na Uniswap, você precisa usar outros tokens como custo equivalente, e não pode transferir fundos de forma 'privada' para outra pessoa; enquanto que, com um mixer, você só precisa mostrar uma prova de depósito para sacar. Para que as ações de depósito e saque pareçam homogêneas, cada depósito em uma pool Tornado e cada saque dela são mantidos consistentes em termos de quantidade. Por exemplo, se houver 100 depositantes e 100 sacadores em uma pool, embora visíveis, eles parecem não estar ligados, e a quantidade depositada e sacada por cada um é a mesma.
Isso pode obscurecer a rastreabilidade das transferências de fundos, oferecendo uma conveniência natural para transações anonimizadas. A questão chave é: como um sacador prova que fez um depósito?
O endereço que faz o saque não está vinculado a nenhum endereço de depósito, então como sua elegibilidade para saque pode ser determinada? O método mais direto parece ser o sacador revelar qual registro de depósito é seu, mas isso revelaria diretamente sua identidade. É aqui que entram as provas de conhecimento zero. Ao apresentar uma prova ZK de que tem um registro de depósito no contrato Tornado que ainda não foi retirado, um sacador pode iniciar com sucesso uma retirada. As provas de conhecimento zero protegem inerentemente a privacidade, revelando apenas que a pessoa realmente fez um depósito no pool de fundos, sem revelar a qual depositante ela corresponde.
Para provar 'Eu fiz um depósito no pool de fundos do Tornado' pode ser traduzido para 'Meu registro de depósito pode ser encontrado no contrato do Tornado.' Se usarmos Cn para representar um registro de depósito, o problema se torna: dado que o conjunto de registros de depósito do Tornado é {C1, C2, ...C100...}, o sacador, Bob, prova que usou sua chave para gerar algum Cn nos registros de depósito sem revelar qual Cn específico é. Isso envolve a propriedade especial de Prova de Merkle. Todos os registros de depósito do Tornado são incorporados em uma Árvore de Merkle construída on-chain, com esses registros como seus nós folha de nível inferior. O número total de folhas é cerca de 2^20 > 1 milhão, a maioria das quais está em estado em branco (atribuído um valor inicial). Sempre que um novo depósito ocorre, o contrato registra seu valor único, Compromisso, em uma folha e, em seguida, atualiza a raiz da Árvore de Merkle.
Por exemplo, se o depósito de Bob foi o 10.000º na história do Tornado, o valor característico Cn associado a este depósito seria inserido no 10.000º nó folha da Árvore de Merkle, ou seja, C10000 = Cn. O contrato então calcula automaticamente uma nova Raiz e a atualiza. Para economizar recursos computacionais, o contrato Tornado armazena em cache dados de um lote de nós previamente alterados, como Fs1, Fs2 e Fs0 no diagrama abaixo.
(Fonte: RareSkills)
A Prova de Merkle, por sua natureza, é concisa e leve, aproveitando a simplicidade das estruturas de dados em árvore nos processos de busca/rastreamento. Para provar externamente que uma transação TD existe em uma Árvore de Merkle, só é necessário fornecer uma Prova de Merkle correspondente à Raiz, o que é bastante direto. Se a Árvore de Merkle for especialmente grande, com 2^20 folhas no nível inferior de potência (ou seja, 1 milhão de registros de depósito), uma Prova de Merkle só precisaria incluir os valores de 21 nós, o que é muito curto.
Para provar que uma transação H3 está de fato contida em uma Árvore de Merkle, deve-se demonstrar que usando H3 e outras partes de dados na Árvore de Merkle, a Raiz pode ser gerada, e os dados necessários para gerar a Raiz (incluindo Td) constituem a Prova de Merkle. Quando Bob faz um saque, ele precisa provar que seu certificado corresponde a um hash de depósito Cn registrado na Árvore de Merkle no livro-razão do Tornado. Em outras palavras, ele deve provar duas coisas: Cn existe dentro da Árvore de Merkle fictícia do Tornado na cadeia, especificamente construindo uma Prova de Merkle contendo Cn; Cn está associado ao certificado de depósito de Bob.
No código frontend da interface do usuário do Tornado, muitas funcionalidades são pré-implementadas. Quando um depositante abre a página da Tornado Cash e clica no botão de depósito, o código frontend acompanhante gera localmente dois números aleatórios, K e r. Em seguida, calcula o valor de Cn=Hash(K, r) e passa Cn (referido como compromisso no diagrama abaixo) para o contrato Tornado, que o insere na Árvore de Merkle registrada por este último. Essencialmente, K e r atuam como chaves privadas. Eles são cruciais, e o sistema solicita aos usuários que os salvem com segurança. K e r são necessários novamente durante a retirada.
(A opção de encryptedNote permite que os usuários criptografem o credencial K e r com uma chave privada e armazenem-na no blockchain para evitar esquecimento) Importante, todas essas operações ocorrem off-chain, o que significa que o contrato Tornado e observadores externos não têm conhecimento de K e r. Se K e r vazarem, é semelhante ao roubo de chaves privadas da carteira.
Ao receber um depósito de um usuário e a submissão de Cn=Hash(K, r), o contrato Tornado registra Cn na camada inferior da Árvore de Merkle como um novo nó folha, também atualizando o valor da Raiz. Portanto, Cn está diretamente ligado à ação de depósito do usuário, permitindo que terceiros saibam qual usuário corresponde a cada Cn, quem depositou tokens no mixer e os registros de depósito Cn de cada depositante.
Durante o processo de retirada, o retirante insere a credencial/chave privada (os números aleatórios K e r gerados durante o depósito) na página da web frontend. O programa no código frontal do Tornado Cash usa K e r, Cn=Hash(K, r), e a Prova de Merkle correspondente a Cn como parâmetros de entrada para gerar uma Prova de Conhecimento Zero. Isso prova que Cn existe na Árvore de Merkle como um registro de depósito, e K e r são as credenciais correspondentes a Cn. Esta etapa essencialmente prova: Eu conheço a chave correspondente a um registro de depósito na Árvore de Merkle. Quando a Prova de Conhecimento Zero é enviada para o contrato do Tornado, esses quatro parâmetros são ocultados, protegendo a privacidade. A geração da Prova de Conhecimento Zero envolve parâmetros adicionais, incluindo a raiz de Merkle registrada no contrato do Tornado no momento da retirada, um endereço de destinatário personalizado A, e um identificador nf para evitar ataques de repetição. Esses três parâmetros são publicamente divulgados no blockchain, o que não compromete a privacidade.
Um detalhe a notar é o uso de dois números aleatórios, K e r, para gerar Cn em vez de um único número aleatório, fornecendo maior segurança contra colisões. A representa o endereço do destinatário da retirada, escolhido pelo retirante. O identificador nf, projetado para evitar ataques de repetição, é calculado como nf=Hash(K), onde K é um dos dois números aleatórios usados na etapa de depósito para gerar Cn. Isso vincula nf diretamente a Cn, estabelecendo uma correlação de um para um entre cada Cn e seu nf correspondente. O objetivo de evitar ataques de repetição é devido à característica de design do mixer, que mantém a associação entre os valores de retirada e folhas específicas da árvore de Merkle (Cn) desconhecida, permitindo o potencial abuso de retiradas repetidas até que o pool de fundos seja esgotado.
O identificador nf funciona de forma semelhante ao nonce associado a cada endereço Ethereum, impedindo repetições de transações. Quando ocorre um saque, uma verificação garante que o nf submetido não tenha sido usado antes; se não utilizado, o saque é válido, e o nf é registrado. Qualquer tentativa de gerar um nf não associado a nenhum depósito registrado Cn falhará em produzir uma Prova ZK válida, tornando o saque sem sucesso.
Se alguém gerar aleatoriamente um contrato não fungível (nf) não registrado, funcionaria? Claro que não. Quando o sacador gera uma Prova de Conhecimento Zero (Prova ZK), ele deve garantir que nf seja igual ao Hash (K), onde o número aleatório K está associado ao registro de depósito Cn. Isso significa que nf está vinculado a um depósito registrado Cn. Se alguém fabricar um nf arbitrariamente, este nf não corresponderá a nenhum registro de depósito, tornando impossível gerar uma Prova ZK válida. Consequentemente, o processo de retirada não pode ser concluído com êxito e a operação de retirada falhará. Alguns podem perguntar: é possível prosseguir sem nf? Uma vez que o retirador precisa enviar uma prova ZK durante a retirada para provar sua associação com um determinado Cn, por que não apenas verificar se a Prova ZK correspondente foi submetida ao blockchain toda vez que uma retirada ocorre? No entanto, essa abordagem é altamente dispendiosa porque o contrato Tornado Cash não armazena permanentemente as provas ZK passadas devido ao desperdício significativo de espaço de armazenamento. Comparar cada nova prova ZK enviada ao blockchain com provas existentes é menos eficiente do que definir um pequeno identificador como nf e armazená-lo permanentemente.
De acordo com o exemplo de código da função de retirada, os parâmetros necessários e a lógica de negócios são os seguintes: O usuário envia uma Prova ZK e nf (NullifierHash) = Hash (K), especifica um endereço de destinatário para a retirada, e a Prova ZK oculta os valores de Cn, K e r, tornando impossível para os outsiders determinar a identidade do usuário. O destinatário muitas vezes usa um endereço novo e limpo, que não revela informações pessoais.
No entanto, há um problema menor: quando os usuários sacam para permanecerem indetectáveis, muitas vezes iniciam a transação de saque a partir de um endereço recém-criado. Nesse momento, o novo endereço não tem ETH para pagar as taxas de gás. Portanto, ao iniciar um saque, o endereço de saque deve declarar explicitamente um relayer para pagar a taxa de gás em seu nome. Em seguida, o contrato de mistura deduz uma parte do saque do usuário para compensar o relayer.
Em resumo, o Tornado Cash pode obscurecer a conexão entre os retirantes e os depositantes. Em situações com uma grande base de usuários, é como um criminoso se misturando em uma multidão em uma área movimentada, tornando difícil para a polícia rastrear. O processo de retirada envolve o uso de ZK-SNARKs, com a parte da testemunha oculta contendo informações críticas sobre o retirante, que é um aspecto-chave de todo o misturador. Atualmente, o Tornado parece ser um dos projetos de camada de aplicação mais engenhosos relacionados ao ZK.