Implantar um contrato programável

O Universal Ledger oferece suporte a contratos programáveis que podem ser implantados em uma rede para automatizar e aplicar acordos entre os participantes interessados.

Este tutorial mostra aos desenvolvedores as etapas necessárias para desenvolver, implantar e interagir com um contrato programável em uma rede de livro-razão universal.

Antes de começar

Para concluir este tutorial, você vai precisar do seguinte:

  • No console do Google Cloud , ative o Cloud Shell.

    Ativar o Cloud Shell

  • Uma conta de usuário do Universal Ledger com o ROLE_CONTRACT_CREATOR. Essa conta vai se tornar a proprietária do contrato.

  • Uma ou mais contas de usuário do Universal Ledger com o ROLE_CONTRACT_PARTICIPANT. Pode ser a mesma conta do proprietário do contrato.

  • Se quiser, configure a CLI do Universal Ledger para poder assinar e enviar transações em nome dessas contas de usuário.

As funções do Universal Ledger podem ser atribuídas a uma conta de usuário quando criadas pelo gerente de contas, no momento em que a transação CreateAccount é enviada ou modificada posteriormente por uma transação AddRoles, se a conta já existir. Para fins de experimentação, também é possível usar a CLI do Universal Ledger para gerenciar contas.

Configurar o ambiente

Para simplificar a configuração, este tutorial foi escrito para o ambiente padrão fornecido em uma sessão do Cloud Shell. Talvez seja necessário modificar esses comandos se você estiver usando um ambiente diferente.

O compilador gculpyc usa o código-fonte escrito na linguagem GCULpy e produz bytecode para o Universal Ledger.

Execute cada um dos comandos a seguir para extrair a imagem Docker gculpyc, definir um alias para executar o binário e confirmar que ele funciona.

docker pull us-docker.pkg.dev/gcul-artifacts/images/client/gculpyc:preview
alias gculpyc="docker run --rm -i --user $(id -u):$(id -g) \
    --volume .:/workspace --workdir /workspace \
    us-docker.pkg.dev/gcul-artifacts/images/client/gculpyc:preview"
gculpyc --help

Escrever seu contrato

GCULpy é a linguagem usada para escrever contratos para o Universal Ledger. É um subconjunto de Python com tipagem estática, otimizado para uma lógica de contrato clara, auditável e compreensível. Esse design prioriza a gravação de código seguro e restringe comportamentos inesperados ou inseguros. Para mais detalhes, consulte a referência da linguagem GCULpy.

Como o GCULpy é um subconjunto estrito do Python, você pode continuar usando seus ambientes de desenvolvimento integrados (IDEs) preferidos com seus fluxos de trabalho e práticas de desenvolvimento atuais.

Por exemplo, seu código pode ser assim:

import gcul

class Counter(gcul.Contract):
    """Example contract implementing a counter."""

    value: int

    def increment(self) -> None:
        """Increments the counter value by 1."""
        self.value += 1

Copie este exemplo de código e salve-o em um arquivo chamado counter.py.

Testar localmente

Em breve, os desenvolvedores terão acesso a um ambiente de simulação local. Fornecido como parte do módulo Python gcul, ele foi projetado para oferecer as funcionalidades necessárias para simular nativamente uma rede Universal Ledger em um ambiente Python. Assim, você poderá executar contratos localmente e escrever testes de unidade usando seus frameworks de teste preferidos, garantindo a confiabilidade e a correção dos contratos antes da implantação.

Compile the contract

Compile o código-fonte do contrato anterior em bytecode usando o seguinte comando gculpyc:

gculpyc --source_file counter.py --output_file counter.bin

Implante o contrato

Implante o contrato em uma rede do Universal Ledger enviando uma transação CreateContract assinada por uma conta de usuário que tenha o ROLE_CONTRACT_CREATOR.

Se você estiver usando a CLI do Universal Ledger, execute o comando:

ul-cli contracts create \
    --alias counter-contract \
    --sender OWNER_ALIAS \
    counter.bin

Substitua:

  • OWNER_ALIAS: o alias de uma conta de usuário com o ROLE_CONTRACT_CREATOR.

Quando a transação for concluída, a saída desse comando vai incluir o ID do contrato recém-implantado. Exemplo:

Contract created: 1:CTR:005XvYfiSm3913Jwv4y8HVQucStJ2Ev15Sar6A1kNNX10

Invocar um método de contrato

Depois que um contrato é implantado, qualquer conta de usuário com o ROLE_CONTRACT_PARTICIPANT pode enviar uma transação InvokeContractMethod para invocar qualquer um dos métodos públicos no contrato.

Se você estiver usando a CLI do Universal Ledger, execute o comando:

ul-cli contracts invoke \
    --alias counter-contract \
    --method-name increment \
    --sender PARTICIPANT_ALIAS

Substitua:

  • PARTICIPANT_ALIAS: o alias de uma conta de usuário com o ROLE_CONTRACT_PARTICIPANT.

Ler o estado do contrato

Para concluir este tutorial, envie uma solicitação QueryAccount para ler e verificar o estado do contrato armazenado no livro-razão. Esse é o mesmo método de API usado para consultar e recuperar os detalhes de qualquer conta do Universal Ledger.

Usando a CLI do Universal Ledger, execute:

ul-cli accounts describe --alias counter-contract

Isso confirma que o valor do contador agora está definido como 1, produzindo uma saída como:

Account: 1:CTR:005XvYfiSm3913Jwv4y8HVQucStJ2Ev15Sar6A1kNNX10
Contract account details:
  Owner: 1:USR:XCL:022uF6cVkTJBaa6pViqTuYqP4455jnRbRc4bWannZGg0b
  Contract fields:
    value: int64_value:1

  Balances:
    None

A seguir