Tema os magos. Não aqueles bruxos, bruxos de verdade.
Anunciado hoje pelo desenvolvedor Robin Linus da ZeroSync, uma associação fundada para ajudar a dimensionar o Bitcoin usando provas de conhecimento zero, o BitVM é uma proposta que abre portas muito interessantes para o desenvolvimento de aplicativos Bitcoin no futuro. Ele pode permitir praticamente qualquer cálculo arbitrário e usar esse cálculo para impor o que acontece com o bitcoin na cadeia.
Não requer nenhuma mudança de consenso no Bitcoin. O truque é retirar toda essa lógica da cadeia e ser capaz de desafiar algumas etapas da computação na cadeia se a outra parte afirmar um resultado desonesto. Em suma, o BitVM trará computação arbitrária Turing-completa, de forma executável, para o próprio bitcoin – hoje.
O básico das portas lógicas
Para realmente compreender os mecanismos por trás da proposta, precisamos entender um pouco sobre a base física e lógica da computação.
Todo mundo sabe que, nos bastidores, seu computador está apenas passando 1s e 0s individuais para fazer tudo o que faz, mas como isso funciona? O que isso significa? Cada chip do seu computador é composto de milhões ou bilhões de coisas individuais chamadas portas lógicas.
Esses pequenos dispositivos pegam um ou dois “bits” de informação, um 1 ou um 0, e realizam uma operação lógica simples neles para produzir um 1 ou um 0 como saída, que então alimenta a próxima porta lógica.
Existem muitos tipos diferentes de portas lógicas, algumas que pegam apenas um único bit e colocam o mesmo número nele (a porta buffer). Outros pegam um único bit e geram o valor oposto que recebe (a porta NOT ou um inversor). Alguns pegam dois bits e geram 1 se ambos os bits de entrada forem 1, com qualquer outra combinação gerando 0 (a porta AND). Por último, pelo menos aqui hoje nesta lista de exemplos, há uma porta que recebe dois bits e produz 0 se ambas as entradas forem 1s, e produz 1 para todas as outras combinações de bits (a porta NAND).
O interessante sobre uma porta NAND é que você pode construir qualquer outro tipo de porta lógica apenas a partir de portas NAND. Definitivamente não será tão eficiente e apenas fará uma versão para fins especiais do outro portão, mas dará conta do recado. Assim, dado que você pode construir qualquer porta lógica a partir de portas NAND, você pode construir circuitos para qualquer cálculo arbitrário a partir de portas NAND.
Construindo NAND em Bitcoin
Agora, como você constrói uma porta NAND com o script Bitcoin existente? Hashlocks e dois outros códigos operacionais com os quais você provavelmente não está familiarizado: OP_BOOLAND e OP_NOT.
Primeiro, vamos dar uma olhada nos hashlocks. Você cria um script de ramificação que pode ser gasto de duas maneiras, revelando a pré-imagem para o hashlock A ou revelando a pré-imagem para o hashlock B. O caminho A colocaria o número 1 na pilha e o caminho B colocaria o número 0.
Isso permite que você “desbloqueie” um bit para ser usado como entrada para a porta NAND que estamos construindo, fornecendo a pré-imagem para o hashlock. Você só pode cumprir o script com um ou outro, não com ambos, e há motivos que abordaremos em breve para isso. Esta primitiva simples existe apenas para permitir que os usuários se comprometam com bits únicos por vez para uso em um script de porta NAND.
Agora pense no que é uma porta NAND, ela leva dois bits e gera um. Se os bits de entrada forem ambos 1s, a saída deverá ser zero. Se os bits de entrada forem qualquer outra combinação, a saída será 1. Você pode usar o truque de hashlock de dois caminhos acima para confirmar ambas as entradas, bem como a saída, você só precisa de uma maneira de verificar se a saída está correta. É aqui que entram OP_BOOLAND e OP_NOT.
Depois de escolher quais valores atribuir como entradas e qual valor de saída verificar, você pode aproveitar um truque interessante. OP_BOOLAND faz exatamente o oposto que NAND faz, se ambas as entradas forem 1s, a saída é 1. Todo o resto gera 0. OP_NOT pega qualquer valor de entrada e o inverte, 1 se torna zero e vice-versa. Isso permite que você pegue os dois valores de entrada e faça uma operação NAND neles na pilha de scripts. Você pode então verificar a saída disso em relação à saída declarada comprometida com o truque de hashlock usando OP_EQUALVERIFY. O script não passará na avaliação se a saída real da operação NAND criada na pilha não corresponder à saída que o usuário afirma que produzirá.
Agora você tem uma porta NAND implementada em script Bitcoin, de uma forma que na verdade, impõe com o script Bitcoin que o portão NAND virtual funcione corretamente.
Onde entra a computação arbitrária
Então, o que você pode fazer agora para criar uma única porta NAND no script Bitcoin? Você pode criar uma árvore tapleaf inteira que cubra cada etapa de qualquer cálculo arbitrário, assim como as portas lógicas reais fazem para criar processadores de computador.
Para realizar cálculos complexos, as pessoas colocam portas lógicas juntas em série, de modo que, depois de alimentar as entradas iniciais nas primeiras portas, a saída de cada uma delas alimente diretamente em outra porta como entrada. A mesma coisa é realizada aqui, amarrando os hashlocks de maneira adequada entre os portões. Ou seja, se um script de porta tiver uma escolha entre as pré-imagens para o valor C1 ou C2 como saída, a próxima porta da série usará esses mesmos valores de hashlock na entrada correspondente. Dessa forma, a única maneira de alguém mentir sobre o resultado da porta anterior é revelar o outro hashlock C. Podemos usar isso como um mecanismo de penalidade.
Ambos os usuários pegam qualquer cálculo que desejam realizar e dividem-no em um circuito de apenas portas NAND fazendo o cálculo porta por porta. Eles então pegam e codificam cada porta individual no circuito, com as opções de hashlock apropriadas para cada etapa do circuito, e codificam-nas em uma árvore tapleaf na qual um único UTXO pode ser bloqueado. Existe uma versão da árvore para o usuário que tenta provar que está executando o programa corretamente e uma versão para a pessoa que verifica se ele está sendo executado corretamente. Agora o que eles fazem é pré-assinar uma série de transações para um jogo de desafio e resposta que pode ser executado em cadeia. Idealmente, toda a computação é executada e verificada fora da cadeia, e os usuários resolvem-na cooperativamente, gastando os fundos juntos para a pessoa apropriada com base no resultado da computação. No entanto, se o provador parar de cooperar, o verificador poderá desafiá-lo na cadeia.
O primeiro passo é colocar dinheiro no esquema. Um caminho de script permitirá que o provador reivindique o dinheiro unilateralmente após um intervalo de tempo. O próximo caminho de script permitirá que o verificador reivindique o dinheiro instantaneamente se puder mostrar as pré-imagens para ambos os valores possíveis para qualquer entrada ou saída do portão atual. O próximo caminho do script permitirá que o verificador force o provador a executar qualquer contrato de portão específico na cadeia (ou seja, aquele logo após ele parar de cooperar com o off-chain). Este caminho exige que o verificador libere outra pré-imagem de hashlock que só ele possui, funcionando como um bloqueio para cada desafio de portão para o provador. Isso garante que o provador só poderá executar aquela porta específica. A transação pré-assinada do verificador para esse caminho irá gastá-la em um script com os seguintes caminhos de script: o verificador pega as moedas após um timelock, ou o provador executa o portão e gasta a moeda de volta em um script como o primeiro, o o provador pode reivindicar o dinheiro após um timelock, o verificador pode reivindicá-lo instantaneamente se mostrar ambas as pré-imagens para qualquer par de hashlock único, ou o verificador pode desafiar o provador novamente.
Apenas algumas rodadas deste esquema garantirão que o contrato seja liquidado corretamente. Ou o verificador fica sem transações pré-assinadas para continuar desafiando o provador, porque o provador continua demonstrando a execução correta de cada portão, e o provador reivindica o fundo; ou, o provador não responde a um desafio porque isso permitiria que ele fosse penalizado, e o verificador reivindica os fundos após um bloqueio de tempo; ou o provador realmente executa um portão incorretamente na cadeia e o verificador reivindica os fundos imediatamente. Idealmente, tudo acontece fora da cadeia e é resolvido de forma cooperativa, mas se a cooperação falhar, literalmente não há outro resultado após apenas algumas rodadas na cadeia do que a liquidação correta do contrato.
Para onde ir a partir daqui
Certamente, uma proposta desta magnitude será discutida daqui a algumas semanas.
A quantidade de dados necessários para serem processados e gerados é enorme. Estamos falando de taptrees com folhas numeradas na casa dos bilhões e transações pré-assinadas para acompanhá-las com pelo menos alguns saltos de comprimento para garantir uma liquidação precisa.
O custo de gerenciamento de dados fora da cadeia é absolutamente enorme.
A outra grande limitação é que este esquema só funcionará com duas partes, uma desempenhando o papel de provar a execução correta e a segunda desempenhando o papel de verificá-la.
Embora seja possível que pesquisas futuras encontrem uma maneira de generalizar isso para mais participantes, pelo menos não vejo um caminho claro para conseguir isso. Além disso, mesmo abordando esse problema específico, não vejo como evitar que este seja um protocolo interativo que exige a participação permanente de todos os participantes no caso cooperativo.
No entanto, esta é uma demonstração muito interessante de como programas complexos podem ser usados para impor controle condicional sobre o Bitcoin. Definitivamente, há espaço para otimização em termos de quanta lógica pode ser compactada em um único script de folha ou o que pode ser feito com diferentes códigos de operação para tornar todo o esquema mais eficiente. A simples desconstrução das operações básicas e dos equilíbrios teóricos dos jogos pode impor qualquer cálculo arbitrário usando Bitcoin.
Verdadeiramente a criação de magos.
Fonte: bitcoinmagazine.com