Mergulhe no Move – a linguagem de programação blockchain Libra do Facebook

A seguir, consideraremos em detalhes as principais características da linguagem Move e quais são suas principais diferenças com outra linguagem já popular para contratos inteligentes - Solidity (na plataforma Ethereum). O material é baseado em um estudo do white paper de 26 páginas disponível online.

Introdução

Move é uma linguagem de bytecode executável usada para executar transações de usuários e contratos inteligentes. Observe dois pontos:

  1. Enquanto Move é uma linguagem de bytecode que pode ser executada diretamente na máquina virtual Move, Solidity (linguagem de contrato inteligente da Ethereum) é uma linguagem de nível superior que é compilada em bytecode antes de ser executada em um EVM (Ethereum Virtual Machine).
  2. O Move pode ser usado não apenas para implementar contratos inteligentes, mas também para transações personalizadas (mais sobre isso mais tarde), enquanto o Solidity é uma linguagem apenas para contratos inteligentes.


A tradução foi realizada pela equipe do projeto INDEX Protocol. Já traduzimos grande material descrevendo o projeto Libra, agora é hora de examinar a linguagem Move com um pouco mais de detalhes. A tradução foi realizada em conjunto com Habrauser coolsiu

Um recurso importante do Move é a capacidade de definir tipos de recursos personalizados com semântica baseada em lógica linear: um recurso nunca pode ser copiado ou excluído implicitamente, apenas movido. Funcionalmente, isso é semelhante aos recursos da linguagem Rust. Os valores em Rust só podem ser atribuídos a um nome por vez. Atribuir um valor a um nome diferente torna-o indisponível com o nome anterior.

Mergulhe no Move – a linguagem de programação blockchain Libra do Facebook

Por exemplo, o seguinte snippet de código gerará um erro: Uso do valor movido 'x'. Isso ocorre porque não há coleta de lixo no Rust. Quando as variáveis ​​saem do escopo, a memória a que se referem também é liberada. Simplificando, só pode haver um "proprietário" dos dados. Neste exemplo x é o dono original e então y passa a ser o novo proprietário. Leia mais sobre esse comportamento aqui.

Representação de ativos digitais em sistemas abertos

Existem duas propriedades de ativos físicos que são difíceis de representar digitalmente:

  • Raridade (Escassez, originalmente escassez). O número de ativos (emissão) no sistema deve ser controlado. A duplicação de ativos existentes deve ser proibida e a criação de novos é uma operação privilegiada.
  • Controle de acesso... O participante do sistema deve ser capaz de proteger ativos usando políticas de controle de acesso.

Essas duas características, que são naturais para ativos físicos, devem ser implementadas para objetos digitais se quisermos considerá-los como ativos. Por exemplo, um metal raro tem uma escassez natural e só você tem acesso a ele (segurando-o nas mãos, por exemplo) e pode vendê-lo ou gastá-lo.

Para ilustrar como chegamos a essas duas propriedades, vamos começar com as seguintes frases:

Sugestão # 1: A regra mais simples sem escassez e controle de acesso

Mergulhe no Move – a linguagem de programação blockchain Libra do Facebook

  • G [K]: = n denota uma atualização para um número acessível por uma tecla К no estado global do blockchain, com um novo significado n.
  • transação ⟨Alice, 100⟩ significa definir o saldo da conta de Alice para 100.

A solução acima tem vários problemas principais:

  • Alice pode receber um número ilimitado de moedas simplesmente enviando transação ⟨Alice, 100⟩.
  • As moedas que Alice envia para Bob são inúteis, pois Bob pode enviar a si mesmo um número ilimitado de moedas usando a mesma técnica.

Sugestão # 2: Levando em consideração o déficit

Mergulhe no Move – a linguagem de programação blockchain Libra do Facebook

Agora estamos monitorando a situação para que o número de moedas Ka era pelo menos igual n antes da transação de transferência. No entanto, embora isso resolva o problema da escassez, não há informações sobre quem pode enviar as moedas de Alice (por enquanto, qualquer pessoa pode fazer isso, o principal é não violar a regra de limitação de quantidade).

Proposta nº 3: Combinando escassez e controle de acesso

Mergulhe no Move – a linguagem de programação blockchain Libra do Facebook

Resolvemos este problema com um mecanismo de assinatura digital verificar_sig antes de verificar o saldo, o que significa que Alice usa sua chave privada para assinar a transação e confirmar que ela é a dona de suas moedas.

Linguagens de programação Blockchain

As linguagens blockchain existentes enfrentam os seguintes problemas (todos eles foram resolvidos no Move (nota: infelizmente, o autor do artigo apela apenas a Ethereum em suas comparações, portanto, vale a pena tomá-las apenas neste contexto. Por exemplo, a maioria dos itens a seguir também é resolvida no EOS.)):

Representação indireta de ativos. Um ativo é codificado usando um número inteiro, mas um número inteiro não é o mesmo que um ativo. Na verdade, não existe nenhum tipo ou valor que represente Bitcoin/Ether/<Qualquer Moeda>! Isso torna a escrita de programas que usam ativos difícil e sujeita a erros. Padrões como passar ativos de/para procedimentos ou armazenar ativos em estruturas requerem suporte especial da linguagem.

O déficit não é expansível... A linguagem representa apenas um ativo escasso. Além disso, os remédios contra a escassez são integrados diretamente na semântica da própria linguagem. O desenvolvedor, se quiser criar um ativo personalizado, deve controlar cuidadosamente todos os aspectos do recurso por conta própria. Esses são exatamente os problemas dos contratos inteligentes da Ethereum.

Os usuários emitem seus ativos, tokens ERC-20, usando números inteiros para determinar o valor e o fornecimento total. Sempre que novos tokens são criados, o código de contrato inteligente deve verificar de forma independente a conformidade com as regras de emissão. Além disso, a apresentação indireta de ativos leva, em alguns casos, a erros graves - duplicação, gasto duplo ou mesmo perda total de ativos.

Falta de controle de acesso flexível... A única política de controle de acesso em uso hoje é um esquema de assinatura usando criptografia assimétrica. Como a proteção contra escassez, as políticas de controle de acesso estão profundamente embutidas na semântica da linguagem. Mas como estender a linguagem para permitir que os programadores definam suas próprias políticas de controle de acesso é geralmente uma tarefa muito complicada.

Isto também é verdade no Ethereum, onde os contratos inteligentes não têm suporte de criptografia nativa para controle de acesso. Os desenvolvedores devem definir manualmente o controle de acesso, por exemplo, usando o modificador onlyOwner.

Mesmo sendo um grande fã do Ethereum, acredito que as propriedades dos ativos devem ser suportadas nativamente pela linguagem para fins de segurança. Em particular, a transferência do Ether para um contrato inteligente envolve despacho dinâmico, que introduziu uma nova classe de bugs conhecidos como vulnerabilidades de reentrada. O despacho dinâmico aqui significa que a lógica de execução do código será determinada em tempo de execução (dinâmico) e não em tempo de compilação (estático).

Assim, no Solidity, quando o contrato A chama uma função no contrato B, o contrato B pode executar código que não foi planejado pelo desenvolvedor do contrato A, o que pode resultar em vulnerabilidades de reentrada (o contrato A acidentalmente atua como contrato B para sacar dinheiro antes que os saldos das contas sejam realmente deduzidos).

Fundamentos do Move Language Design

Recursos de primeira ordem

Em um alto nível, a interação entre módulos / recursos / procedimentos na linguagem Move é muito semelhante ao relacionamento entre classes / objetos e métodos em linguagens OOP.
Os módulos de movimentação são semelhantes aos contratos inteligentes em outras cadeias de blocos. O módulo declara tipos de recursos e procedimentos que definem as regras para criar, destruir e atualizar recursos declarados. Mas tudo isso são apenas convenções (“jargão”) Em movimento. Ilustraremos esse ponto um pouco mais tarde.

Flexibilidade

Move adiciona flexibilidade ao Libra por meio de scripts. Cada transação em Libra inclui um script, que é essencialmente o procedimento central da transação. O script pode executar uma ação específica, por exemplo, pagamentos para uma lista específica de destinatários, ou reutilizar outros recursos - por exemplo, chamando um procedimento no qual a lógica geral é especificada. É por isso que os scripts de transação Move oferecem maior flexibilidade. Um script pode usar comportamentos únicos e repetidos, enquanto o Ethereum só pode executar scripts repetíveis (chamando um método em um método de contrato inteligente). A razão pela qual é chamado de “reutilizável” é porque as funções de um contrato inteligente podem ser executadas várias vezes. (observação: A questão aqui é muito sutil. Por um lado, scripts de transação na forma de pseudo-bytecode também existem no Bitcoin. Por outro lado, pelo que entendi, o Move expande essa linguagem, de fato, ao nível de uma linguagem de contrato inteligente completa).

segurança

O formato executável do Move é bytecode, que é, por um lado, uma linguagem de nível superior à linguagem assembly, mas de nível inferior ao código-fonte. O bytecode é verificado em tempo de execução (on-chain) quanto a recursos, tipos e segurança de memória usando um verificador de bytecode e, em seguida, executado pelo interpretador. Essa abordagem permite que o Move forneça a segurança do código-fonte, mas sem o processo de compilação e a necessidade de adicionar um compilador ao sistema. Tornar o Move uma linguagem de bytecode é uma solução muito boa. Não precisa ser compilado a partir do código-fonte, como é o caso do Solidity, e não há necessidade de se preocupar com possíveis falhas ou ataques à infraestrutura do compilador.

Verificabilidade

Nosso objetivo é realizar as verificações da maneira mais fácil possível, já que tudo isso é feito on-chain (nota: online, durante a execução de cada transação, portanto, qualquer atraso leva a uma desaceleração de toda a rede), entretanto, inicialmente o design da linguagem está pronto para usar ferramentas de verificação estática fora da cadeia. Embora isto seja mais preferível, por enquanto o desenvolvimento de ferramentas de verificação (como um kit de ferramentas separado) foi adiado para o futuro, e agora apenas a verificação dinâmica em tempo de execução (on-chain) é suportada.

Modularidade

Os módulos de movimentação fornecem abstração de dados e localizam operações críticas em recursos. O encapsulamento fornecido pelo módulo, combinado com a proteção fornecida pelo sistema de tipo Move, garante que as propriedades definidas nos tipos do módulo não possam ser violadas por código fora do módulo. Este é um design de abstração bastante bem pensado, o que significa que os dados dentro do contrato só podem mudar dentro da estrutura do contrato, mas não fora.

Mergulhe no Move – a linguagem de programação blockchain Libra do Facebook

Visão geral da movimentação

O exemplo de script de transação demonstra que ações maliciosas ou descuidadas por um programador fora de um módulo não podem comprometer a segurança dos recursos de um módulo. A seguir, veremos exemplos de como módulos, recursos e procedimentos são usados ​​para programar a blockchain Libra.

Pagamentos ponto a ponto

Mergulhe no Move – a linguagem de programação blockchain Libra do Facebook

O número de moedas especificado no valor será transferido do saldo do remetente para o destinatário.
Existem algumas coisas novas aqui (destacadas em vermelho):

  • 0x0: endereço da conta onde o módulo está armazenado
  • Moeda: nome do módulo
  • Moeda: tipo de recurso
  • O valor da moeda retornado pelo procedimento é um valor de recurso do tipo 0x0.Currency.Coin
  • mover (): o valor não pode ser usado novamente
  • cópia de(): o valor pode ser usado mais tarde

Analise o código: na primeira etapa, o remetente chama um procedimento chamado retirar_do_sender de um módulo armazenado em 0x0.Moeda. Na segunda etapa, o remetente transfere fundos para o destinatário, transferindo o valor do recurso moeda para o procedimento de depósito do módulo 0x0.Moeda.

Aqui estão três exemplos de erros no código que serão rejeitados pelas verificações:
Duplique fundos alterando a chamada mover (moeda) em cópia (moeda). Os recursos só podem ser movidos. Tentar duplicar uma quantidade de um recurso (por exemplo, chamando cópia (moeda) no exemplo acima) resultará em um erro ao verificar o bytecode.

Reutilização de fundos especificando mover (moeda) duas vezes . Adicionando uma linha 0x0.Currency.deposit (copiar (some_other_payee), mover (moeda)) por exemplo, o acima permitirá que o remetente “gaste” as moedas duas vezes - a primeira vez com o beneficiário e a segunda com algum_outro_pagador. Este é um comportamento indesejável que não é possível com um ativo físico. Felizmente, o Move rejeitará este programa.

Perda de fundos devido à recusa mover (moeda). Se você não mover o recurso (por exemplo, excluindo a linha que contém mover (moeda)), um erro de verificação de bytecode será gerado. Isso protege os programadores do Move contra perda acidental ou maliciosa de fundos.

Módulo de moeda

Mergulhe no Move – a linguagem de programação blockchain Libra do Facebook

Cada conta pode conter 0 ou mais módulos (mostrados como retângulos) e um ou mais valores de recursos (mostrados como cilindros). Por exemplo, uma conta em 0x0 contém módulo 0x0.Moeda e o valor do tipo de recurso 0x0.Moeda.Moeda. Conta no endereço 0x1 possui dois recursos e um módulo; Conta no endereço 0x2 tem dois módulos e um valor de recurso.

Alguns momentos:

  • O script de transação é atômico - ou é executado completamente ou não é executado.
  • Um módulo é um trecho de código de longa duração acessível globalmente.
  • O estado global é estruturado como uma tabela hash, onde a chave é o endereço da conta
  • As contas não podem conter mais do que um valor de recurso de um determinado tipo e não mais do que um módulo com um determinado nome (conta em 0x0 não pode conter um recurso adicional 0x0.Moeda.Moeda ou outro módulo chamado Moeda)
  • O endereço do módulo declarado faz parte do tipo (0x0.Moeda.Moeda и 0x1.Moeda.Moeda são tipos separados que não podem ser usados ​​de forma intercambiável)
  • Os programadores podem armazenar várias instâncias desse tipo de recurso em uma conta definindo seu recurso personalizado - (recurso TwoCoins {c1: 0x0.Currency.Coin, c2: 0x0.Currency.Coin})
  • Você pode referir-se a um recurso pelo seu nome sem conflitos, por exemplo, você pode referir-se a dois recursos usando Duas Moedas.c1 и Duas Moedas.c2.

Anúncio de recurso de moeda

Mergulhe no Move – a linguagem de programação blockchain Libra do Facebook
Módulo nomeado Moeda e um tipo de recurso chamado Moeda

Alguns momentos:

  • Moeda é uma estrutura com um campo do tipo u64 (inteiro não assinado de 64 bits)
  • Apenas procedimentos de módulo Moeda pode criar ou destruir valores do tipo Moeda.
  • Outros módulos e scripts só podem escrever ou referenciar o campo de valor através de procedimentos públicos fornecidos pelo módulo.

Venda de depósito

Mergulhe no Move – a linguagem de programação blockchain Libra do Facebook

Este procedimento aceita um recurso Moeda como entrada e combina-o com o recurso Moedaarmazenado na conta do destinatário:

  1. Destruir o recurso de entrada Moeda e registrar seu valor.
  2. Receber um link para um recurso de moeda exclusivo armazenado na conta do destinatário.
  3. Alterando o valor da quantidade de Moedas pelo valor passado no parâmetro ao chamar o procedimento.

Alguns momentos:

  • Descompacte, BorrowGlobal - procedimentos integrados
  • Descompacte Esta é a única maneira de excluir um recurso do tipo T. O procedimento pega um recurso como entrada, destrói-o e retorna o valor associado aos campos do recurso.
  • EmpréstimoGlobal recebe um endereço como entrada e retorna uma referência a uma instância única de T publicada (de propriedade) por esse endereço
  • &mut Moeda este é um link para o recurso Moeda

Implementação de retirar_from_sender

Mergulhe no Move – a linguagem de programação blockchain Libra do Facebook

Este procedimento:

  1. Obtém um link para um recurso exclusivo Moeda, vinculado à conta do remetente
  2. Diminui o valor de um recurso Moeda através do link para o valor especificado
  3. Cria e retorna um novo recurso Moeda com saldo atualizado.

Alguns momentos:

  • Depositar pode ser causado por qualquer pessoa, mas retirar_do_sender só tem acesso às moedas da conta de chamada
  • GetTxnSenderAddress igual a mensagem.sender em solidez
  • Rejeitar a menos que igual a requerer em Solidez. Se esta verificação falhar, a transação será interrompida e todas as alterações serão revertidas.
  • Pacote também é um procedimento interno que cria um novo recurso do tipo T.
  • Assim como Descompacte, Pacote só pode ser chamado dentro do módulo onde o recurso está descrito T

Conclusão

Examinamos as principais características da linguagem Move, comparamos com Ethereum e também nos familiarizamos com a sintaxe básica dos scripts. Por fim, recomendo fortemente conferir papel branco original. Inclui muitos detalhes sobre os princípios de design de linguagens de programação, bem como muitos links úteis.

Fonte: habr.com

Adicionar um comentário