WEB3DEV

Cover image for Contratos Inteligentes com estado em Bitcoin SV
Dimitris Carvalho Calixto
Dimitris Carvalho Calixto

Posted on

Contratos Inteligentes com estado em Bitcoin SV

Ao contrário da crença popular, o Bitcoin¹ vem com capacidade de contratação inteligente desde seu início, com uma linguagem de programação nativa baseada em pilha, chamada Script. Cada transação em Bitcoin consiste de entradas e saídas. Cada saída bloqueia alguns bitcoins com um script que dita as obrigações de um contrato. Se uma entrada vem com um script que cumpre o contrato de uma saída, ele desbloqueia bitcoins² nessa saída e os move para novas saídas. É assim que funciona a transferência de propriedade de bitcoins.

A bitcoin transaction

O script é geralmente considerado como extremamente limitado e, portanto, incapaz de sofisticadas contratações inteligentes. Uma deficiência frequentemente citada da contratação inteligente de Bitcoin é sua falta de estado. É uma limitação importante que o Ethereum supõe superar e que justifica sua existência.

Pré-requisito: OP_PUSH_TX

Antes de analisarmos como manter o estado nos contratos inteligentes Bitcoin, introduzimos uma técnica poderosa chamada OP_PUSH_TX. Ela pode ser considerada como um pseudo opcode³ que empurra a transação atual para a pilha, que pode então ser inspecionada em tempo de execução. Mais precisamente, ela permite a inspeção da pré-imagem utilizada na verificação da assinatura definida no BIP143. O formato da pré-imagem é o seguinte:

Signature hash preimage

Implementação de contratos com estado

Uma vez que podemos inspecionar o contexto da transação de um contrato, podemos colocar restrições arbitrárias em suas entradas e saídas.

Uma maneira de implementar o estado em contrato é dividir o contrato no roteiro de bloqueio em duas partes: dados e código. A parte de dados é o estado. A parte de código contém a lógica comercial de um contrato que codifica regras para a transição do estado. Os dados são anexados passivamente ao código como OP_RETURN <dados> ou OP_PUSHDATA <dados> OP_DROP. Mesmo não sendo avaliados, ainda afetam a validade de um contrato, uma vez que a parte de código anterior o valida.

Contract in a locking script is divided into code and data

Usando OP_PUSH_TX, podemos obter o roteiro de travamento da saída sendo gasta da parte 5 e o da nova saída da parte 8. Para manter o estado, exigimos que a parte de código do script de travamento não mude e que as mudanças de dados/estado cumpram as regras de transição de estado na parte de código. Isto é análogo ao conceito de objeto na Programação Orientada a Objetos, sendo o código métodos e dados variáveis membros de um objeto. Os métodos são imutáveis. As variáveis de membros são encapsuladas e só podem ser alteradas através de métodos⁵. Os métodos são chamados a partir do script de desbloqueio, codificando o método a ser chamado e seus argumentos.

State is carried across UTXOs in a contract

Um exemplo de contrato: Contador

Vejamos um exemplo simples de um contrato com estado: um contra-contrato que rastreia quantas vezes sua função increment() foi chamada. Seu código é mostrado abaixo com comentários em linha.


contract Counter {

    public function increment(SigHashPreimage txPreimage, int amount) {

        require(Tx.checkPreimage(txPreimage));

        // deserializar o estado (i.e., valor do contador)

        bytes scriptCode = Util.scriptCode(txPreimage);

        int scriptLen = len(scriptCode);

        // contador está no final

        int counter = unpack(scriptCode[scriptLen - Util.DataLen :]);

        // incrementa o contador

        counter++;

        // serializa o estado

        bytes outputScript = scriptCode[: scriptLen - Util.DataLen] + num2bin(counter, Util.DataLen);



        bytes output = Util.buildOutput(outputScript, amount);

        // garantir que a produção seja esperada: a quantidade é a mesma especificada

        // também o script de saída é o mesmo com o scriptCode, exceto o contador incrementado

        require(hash256(output) == Util.hashOutputs(txPreimage));

    }

}

Enter fullscreen mode Exit fullscreen mode

A linha 3 garante que a pré-imagem é da transação atual. Recebemos o script de bloqueio anterior na Linha 6, também conhecido como scriptCode na parte 5 da pré-imagem. O estado do contador anterior é extraído do scriptCode na Linha 9, após o qual é incrementado e colocado no novo script de travamento na Linha 15. Observe que o contador é a única parte que muda no script de travamento. O restante garante que a saída contenha o novo script de travamento.

Aqui está o código para implantar o contrato e chamar repetidamente a função increment(). Uma instância do contrato com incremento de contador de 0 a 9 pode ser encontrada: 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9. Observe que o estado do contador está no final do script da primeira saída da transação.

Counter at state 9

Conclusão

Isto é parte de uma série que estamos escrevendo para demonstrar o que os contratos inteligentes Bitcoin podem fazer e como implementá-los. Muitas supostas limitações do Script são devidas ao fracasso na realização de seu potencial. Como explicamos e demonstramos mais sobre o que o Script pode alcançar, as pessoas vão achar que ele é extremamente extensível, versátil e orientado para o futuro. Mostraremos que o Bitcoin, sem limites artificiais, pode executar qualquer contrato inteligente que outras blockchains possam executar, ao mesmo tempo em que é capaz de escalonamento ilimitado. Ela pode ser alavancada para tornar muitas aplicações em todas as indústrias mais eficientes e seguras através de incentivos econômicos.

Agradecimentos

Agradecimentos especiais vão para nChain por fornecer a idéia original de OP_PUSH_TX. Agradecemos também a George Papageorgiou, James Belding, Brenton Gunning e Joel Dalais pelas valiosas sugestões sobre uma versão anterior deste artigo.


[1]: No artigo, nos referimos ao Bitcoin SV como Bitcoin, pois segue o desenho original do protocolo.

[2]: Existe uma exceção que algumas saídas contêm zero bitcoins, marcados por, por exemplo, OP_RETURN.

[3]: Um opcode é a unidade básica do script.

[4]: Há alguma exceção a esta regra geral em algumas linguagens dinâmicas do OOP.

[5]: Há também algumas exceções a esta regra geral.

Artigo escrito por sCrypt. A versão original pode ser encontrada aqui. Traduzido e adaptado por Dimitris Calixto.

Latest comments (0)