WEB3DEV

Cover image for Como Habilitar a Privacidade de Token na Solana com Provas de Conhecimento Zero do Elusiv
Panegali
Panegali

Posted on

Como Habilitar a Privacidade de Token na Solana com Provas de Conhecimento Zero do Elusiv

Visão Geral

Um obstáculo comum para a adoção da tecnologia Web3 é a necessidade de mais privacidade. As transações em blockchain são públicas, o que significa que qualquer pessoa pode visualizar os detalhes de uma transação, incluindo o remetente e o destinatário. Embora haja muitas aplicações em que essa transparência seja benéfica, há também muitos casos em que os usuários necessitam de privacidade. Por exemplo, se você é um empresário, pode não querer que seus concorrentes saibam quanto você paga aos seus funcionários. Ou, se você é um usuário, pode querer evitar que seus amigos saibam quanto você investe. A privacidade se tornará cada vez mais importante à medida que a Web3 atingir mais usuários e casos de uso.

Vários protocolos estão surgindo na Solana para possibilitar transações privadas. Neste guia, vamos mostrar como usar o Elusiv, um protocolo de privacidade de conhecimento zero (ZK) na Solana, para criar uma transferência privada de token SPL.

O Que Você Fará

Neste guia, você irá:

  1. Aprender sobre o Elusiv, um protocolo de privacidade de conhecimento zero (ZK) na Solana.
  2. Criar uma transferência privada de USDC usando o SDK do Elusiv.
  3. Verificar se a transação foi privada.

O Que Você Precisará

O Que é o Elusiv?

As transações na Solana são públicas. Qualquer pessoa com acesso a um explorador e à chave pública de um usuário pode rastrear e monitorar a atividade de transações desse usuário. O Elusiv visa quebrar a ligação entre remetentes e destinatários para possibilitar transações privadas. O Elusiv é um protocolo de privacidade baseado na Solana habilitado pela criptografia de conhecimento zero. O protocolo permite que usuários e aplicativos acessem criptografia e controles universais, permitindo-lhes escolher o que é compartilhado e o que não é. O Elusiv utiliza zk-SNARKS para transações privadas e soluções descentralizadas de conformidade.

O Elusiv tem duas funções principais:

  • Programa Elusiv: o Elusiv funciona gerenciando um pool compartilhado governado pelo programa Elusiv. Os usuários podem depositar e sacar fundos no pool (transações públicas) e, em seguida, transferir fundos para outros usuários no pool (transações privadas). Embora os detalhes da transação sejam privados para o iniciador do pagamento, o iniciador pode criar chaves de visualização para permitir que outros vejam transações específicas.
  • Guardião Elusiv: o Guardião Elusiv é responsável por transmitir solicitações de clientes para a rede e (no futuro) será responsável por gerenciar tarefas baseadas em conformidade (por exemplo, impedir que endereços na lista negra realizem transações).

O Elusiv criou uma aplicação simples para demonstrar a tecnologia que permite criar transferências privadas de token. Confira em https://app.elusiv.io/.

Vamos dar uma olhada no SDK Elusiv para ver como integrar essa funcionalidade em nossas aplicações.

Criar um Novo Projeto

mkdir elusiv-demo && cd elusiv-demo && echo > app.ts
Enter fullscreen mode Exit fullscreen mode

Instalar as dependências Web3 da Solana:

yarn init -y
yarn add @solana/web3.js @solana/spl-token @elusiv/sdk @noble/ed25519
Enter fullscreen mode Exit fullscreen mode

ou

npm init -y
npm install --save @solana/web3.js @solana/spl-token @elusiv/sdk @noble/ed25519
Enter fullscreen mode Exit fullscreen mode

Importar Dependências

Abra o arquivo app.ts em um editor de código de sua escolha e, na linha 1, importe o seguinte:

import { Connection, Keypair } from '@solana/web3.js';
import { createAssociatedTokenAccountIdempotent } from '@solana/spl-token';
import { airdropToken, Elusiv, getTokenInfo, SEED_MESSAGE } from '@elusiv/sdk';
import { sign } from '@noble/ed25519';
Enter fullscreen mode Exit fullscreen mode

Esses imports nos permitirão conectar à rede Solana, criar um token e interagir com o SDK Elusiv. Vamos abordar cada elemento com mais detalhes posteriormente no guia.

Criar um Novo Keypair

Primeiramente, precisaremos de um novo Keypair para usar em nossa demonstração. Gere um usando o widget abaixo e copie/cole a saída no seu editor de código.

Crie o par de chaves da carteira aqui:

Você verá algo assim - certifique-se de incluir o segredo gerado no widget:

const secret = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...]; // _cole seu segredo aqui_
const keyPair = Keypair.fromSecretKey(new Uint8Array(secret));
Enter fullscreen mode Exit fullscreen mode

Você precisará financiar a conta com alguns SOL da Rede de Desenvolvimento (Devnet) para executar transações. Você pode fazer isso visitando a Torneira Solana e colando sua nova chave pública ou usando o seguinte comando no terminal:

solana airdrop 1 <sua chave pública> -ud
Enter fullscreen mode Exit fullscreen mode

Se precisar de ajuda, confira nosso guia completo sobre o airdrop da Devnet SOL.

Conectar a um Cluster Solana com seu Ponto de Extremidade QuickNode

Para construir na Solana, você precisará de um ponto de extremidade de API para se conectar à rede. Você pode usar nós públicos ou implantar e gerenciar sua própria infraestrutura; no entanto, se desejar tempos de resposta 8 vezes mais rápidos, pode deixar o trabalho pesado para nós. Veja por que mais de 50% dos projetos na Solana escolhem o QuickNode e inscreva-se para uma conta gratuita aqui. Vamos usar um ponto de extremidade Solana Devnet.

Copie o link do provedor HTTP:

E então, use-o para se conectar à rede Solana com o seguinte código:

const cluster = 'devnet';
const quickNodeEndpoint = 'https://example.solana.quiknode.pro/012345' // 👈 _SUBSTITUA ISSO PELO SEU PONTO DE EXTREMIDADE_
const connection = new Connection(quickNodeEndpoint);
Enter fullscreen mode Exit fullscreen mode

Estruture a Aplicação

Em seguida, crie uma função principal e a chame no final do arquivo. É aqui que escreveremos nosso código.

async function main() {
    // _o código vai aqui_
}

main()
    .catch(err => console.error(err))
    .finally(() => process.exit());
Enter fullscreen mode Exit fullscreen mode

Ótimo. Estamos prontos para começar a construir nosso aplicativo.

Construa a Aplicação

Dentro de nossa função principal, vamos criar seis etapas para demonstrar como usar o SDK Elusiv:

  1. Criar uma instância do Elusiv
  2. Realizar uma distribuição gratuita de "USDC" para nossa conta de token associada ao USDC na devnet
  3. Verificar nosso saldo privado
  4. Recarregar o saldo privado, se necessário
  5. Enviar privadamente algum USDC para um endereço aleatório
  6. Verificar se nossa chave privada não estava na transação

Criar uma Instância do Elusiv

O SDK Elusiv nos permite criar uma instância do programa Elusiv passando uma semente, chave pública, conexão Solana e cluster.

Dentro da função principal, adicione a etapa 1:

// _Etapa 1 - Criar uma instância do Elusiv_

console.log('1. `Creating Elusiv instance`');
const seed = await sign(
    Buffer.from(SEED_MESSAGE, 'utf-8'),
    keyPair.secretKey.slice(0, 32),
);
const elusiv = await Elusiv.getElusivInstance(seed, keyPair.publicKey, connection, cluster);
Enter fullscreen mode Exit fullscreen mode

Consulte a seção 2. Uso básico da documentação do SDK Elusiv se você encontrar um erro do tipo "etc.sha512Sync not set". A semente que geramos é criada assinando uma constante que importamos do SDK Elusiv. Esta semente permite que qualquer pessoa descriptografe e gaste os ativos privados do usuário, então manipule isso com cuidado em produção.

Salvamos nossa instância do Elusiv como elusiv para que possamos usá-la em todo o nosso aplicativo.

Distribuir USDC na Devnet

O SDK Elusiv possui algumas ferramentas de teste úteis para distribuir tokens SPL. Como estaremos testando uma transferência privada de USDC, precisaremos de algum USDC na devnet para nossa demonstração. Adicione a etapa 2 à sua função principal:

// _Etapa 2 - Distribuir alguns "USDC" para nossa conta de token associada à devnet USDC_
console.log('2. `Airdropping USDC'`);
const usdcInfo = getTokenInfo('USDC');
const oneUsdc = 10 ** usdcInfo.decimals;
const usdcMint = usdcInfo.mintDevnet;

const ataAcc = await createAssociatedTokenAccountIdempotent(
    connection,
    keyPair,
    usdcMint,
    keyPair.publicKey,
    { commitment: 'finalized' }
);
await airdropToken(
    'USDC',
    1000 * oneUsdc,
    ataAcc,
);
Enter fullscreen mode Exit fullscreen mode

Antes de distribuir USDC, primeiro devemos determinar o endereço da cunhagem (mint) e depois criar (ou buscar) uma conta de token associada (ATA) para nosso par de chaves.

  • O Elusiv possui uma função auxiliar, getTokenInfo, que buscará os detalhes do token (por exemplo, endereço da cunhagem na rede principal e rede de desenvolvimento, casas decimais, etc.) para um token específico suportado pelo protocolo deles. Usamos isso para obter o endereço da cunhagem para o USDC na devnet e o número de casas decimais associadas ao token.
  • Definimos oneUsdc como 10 elevado à potência do número de casas decimais. Isso nos permitirá calcular facilmente quantidades de transferência sem nos preocuparmos com as casas decimais.
  • Em seguida, passamos essa cunhagem para uma função auxiliar de Token SPL, createAssociatedTokenAccountIdempotent. Isso criará uma nova ATA se necessário e retornará a chave pública dessa ATA. Para mais informações sobre ATAs, consulte nosso Guia: Como Encontrar o Endereço de Token Associado para uma Carteira Solana e Cunhagem.
  • Passamos nosso token, quantia e nova ATA para outra função de utilidade Elusiv, airdropToken. Isso colocará 1.000 USDC na ATA.

Verificar Saldo Privado

Antes de avançar, vamos verificar nosso saldo de conta privada (deve ser 0, já que ainda não fizemos nada). Adicione a Etapa 3 à sua função principal:

// _Etapa 3 - Verificar nosso saldo privado_
console.log('3. `Checking private balance`');
let privateBalance = await elusiv.getLatestPrivateBalance('USDC');
Enter fullscreen mode Exit fullscreen mode

O protocolo Elusiv lida com a descriptografia de saldos privados usando a instância Elusiv que criamos anteriormente.

Recarregar Saldo Privado

Como não teremos um saldo privado para nossos testes iniciais, vamos depositar (ou "recarregar") nossa conta de saldo privado.


// _Etapa 4 - Recarregar saldo privado, se necessário_
if (privateBalance === BigInt(0)) {
    console.log('4. `Topping up private balance`');
    const topupTx = await elusiv.buildTopUpTx(500 * oneUsdc, 'USDC');
    topupTx.tx.partialSign(keyPair);
    await elusiv.sendElusivTx(topupTx);
    privateBalance = await elusiv.getLatestPrivateBalance('USDC');
} else {
    console.log('4. Reca`Private balance top up not needed. Current Balance:` ', (privateBalance / BigInt(10 ** usdcInfo.decimals)).toString());
}
Enter fullscreen mode Exit fullscreen mode

Vamos detalhar isso:

  • Primeiro, verificamos se o saldo é 0. Se não for, pularemos esta etapa.
  • Em seguida, usamos a função buildTopUpTx do Elusiv para criar uma transação que recarregará nosso saldo privado com 500 USDC.
  • Parcialmente assinamos a transação com nosso par de chaves.
  • Finalmente, enviamos a transação para a rede e buscamos o último saldo privado.

Enviar USDC Privadamente

Após a etapa 4, devemos ter um saldo positivo em nossa conta privada. Vamos usá-lo para enviar uma transação privada. Faremos isso enviando alguns USDC para um endereço aleatório. Adicione a Etapa 5 à sua função principal:


// _Etapa 5 - Enviar alguns USDC para um endereço aleatório_
console.log('5. `Sending USDC to a random address`');
if (privateBalance <= BigInt(0)) {
    throw new Error("`Can't send from an empty private balance`");
}

const sendTx = await elusiv.buildSendTx(10 * oneUsdc, Keypair.generate().publicKey, 'USDC');
const sig = await elusiv.sendElusivTx(sendTx);

console.log(`   https://explorer.solana.com/tx/${sig.signature}?cluster=${cluster}`);
Enter fullscreen mode Exit fullscreen mode

Primeiro, verificamos novamente para garantir que realmente temos um saldo positivo em nossa conta privada. Se não tivermos, lançamos um erro. Em seguida, usamos a função buildSendTx do Elusiv para criar uma transação que enviará 10 USDC para um endereço aleatório. Em seguida, enviamos a transação para a rede e registramos a URL da transação no console.

Neste ponto, enviamos com sucesso uma transação privada. Ótimo trabalho!

Verificar Transação

Vamos adicionar uma etapa extra que verifica nossa transação para garantir que ela seja privada. Faremos isso usando o método getTransaction do SDK Web3 da Solana e, em seguida, analisaremos os resultados. Adicione a Etapa 6 à sua função principal:

// _Etapa 6 - Verificar se nosso par de chaves estava na transação_
console.log('6. `Checking if our keypair was in the transaction`');
const txDetail = await connection.getTransaction(sig.signature, {
    commitment: 'confirmed',
    maxSupportedTransactionVersion: 0
});
const readonly = txDetail?.meta?.loadedAddresses?.readonly ?? [];
const writable = txDetail?.meta?.loadedAddresses?.writable ?? [];
const allAccounts = [...new Set([...readonly, ...writable])];
const isSenderInTx = allAccounts.some(pubKey => pubKey.toBase58() === keyPair.publicKey.toBase58());
if (isSenderInTx) {
    console.log('❌ -`Our Keypair was in the transaction (unexpected)`');
} else {
    console.log('✅ - `Our Keypair was not in the transaction (expected)`');
}
Enter fullscreen mode Exit fullscreen mode

Vamos percorrer o novo código:

  • Primeiro, chamamos o método getTransaction em nossa assinatura de transação de transferência privada. Isso retornará os detalhes da transação.
  • Em seguida, analisamos os detalhes da transação para obter a lista de contas que foram carregadas na memória durante a transação. Estamos pegando as contas de leitura e escrita e depois as combinando em uma única matriz de todas as chaves públicas usadas na transação.
  • Finalmente, verificamos se nossa chave remetente estava na transação usando .some. Esperamos que nossa chave remetente não esteja na transação, então registramos uma mensagem de sucesso se não estiver. Se estiver, registramos um erro.

Executar a Aplicação

Agora que construímos nossa aplicação, vamos executá-la. No seu terminal, digite:

ts-node app.ts
Enter fullscreen mode Exit fullscreen mode

Você deverá ver algo assim:

qn elusiv-demo % ts-node app
1. Creating Elusiv instance
2. Airdropping USDC
3. Checking private balance
4. Private balance top-up not needed. Current Balance:  359777742
5. Sending USDC to a random address
  https://explorer.solana.com/tx/5fP4TvgCbYMWFRaQuzikmwovSgJWJM7F7c59kKMP82BJjgDurUPdwH49gbJxhhcjWHH1bxbxeYRorw9j6QFRE7HD?cluster=devnet
6. Checking if our keypair was in the transaction
✅ - Our Keypair was not in the transaction (expected)
Enter fullscreen mode Exit fullscreen mode

Nota: consulte a seção 2. Uso básico da documentação do SDK Elusiv se encontrar um erro do tipo "etc.sha512Sync not set". Se você vir a mensagem de sucesso no final, enviou com sucesso uma transação privada na Solana usando o SDK Elusiv. Você deve ser capaz de navegar na transação no Explorer da Solana e verificar que nossa carteira pagadora não está associada à transação. Bom trabalho!

Conclusão

Habilitar transações privadas em seu dapp pode ser uma ótima maneira de proteger a privacidade de seus usuários e diminuir as barreiras para a adoção da tecnologia Web3. O Elusiv facilita a integração dessa funcionalidade em seu aplicativo. Mal podemos esperar para ver o que você cria!

Se você tiver alguma pergunta ou ideia para compartilhar, nos avise no Discord ou Twitter! Você também pode conferir o Fórum QuickNode para explorar mais tópicos em discussão e colaborar com outros.

Nós ❤️ Feedback!

Deixe-nos saber se você tem algum feedback ou solicitações para novos tópicos. Adoraríamos ouvir de você.

Recursos


Artigo escrito por Aaron Milano. Traduzido por Marcelo Panegali.

Top comments (0)