Aiken: Um impulso para Cardano - Parte 1

Aiken: Um impulso para Cardano - Parte 1

Para criar um ecossistema rico em torno de uma tecnologia, em primeiro lugar – embora possa parecer óbvio – são necessárias pessoas que a utilizem e, em segundo lugar, pessoas que criem ferramentas sobre ela. Isto torna-se mais evidente se a tecnologia de que falamos for uma criptomoeda, uma vez que o seu objetivo final se baseia na sua robustez e confiança. Isso fica evidente porque trabalhamos com transações monetárias. Para conseguir isso, você precisa de programadores interessados ​​em produzir aplicativos em seu sistema para conquistar usuários.

Cardano é uma criptomoeda que utiliza um blockchain baseado em prova de aposta, considerada uma alternativa a outras como Ethereum e Bitcoin e que utiliza o algoritmo de prova de trabalho. Mas, talvez, uma das principais bandeiras da Cardano, que a diferencia da concorrência, seja a sua confiabilidade. Isso se traduz em um código mais seguro, algo que requer uma linguagem de programação com um sistema de tipos robusto. Haskell foi o escolhido de Cardano.

Por um lado, esta seleção é apreciada, pois evita cometer erros previsíveis em contratos inteligentes, e por outro, tem sido criticada por ser uma linguagem com uma curva de aprendizagem acentuada. Haskell não é fácil e isso é uma barreira de entrada para que mais desenvolvedores se interessem por Cardano. O mesmo acontece em outro tipo de indústria: as empresas que utilizam Haskell são poucas se comparadas às que utilizam Java, Python ou mesmo C++.

Este artigo está organizado da seguinte forma: Primeiramente começarei com uma introdução às linguagens de programação presentes em Cardano. Depois falarei sobre Aiken, uma nova linguagem que dá um novo impulso ao Cardano, começando pela instalação. Posteriormente mostrarei suas características através de exemplos simples. Concluirei com algumas considerações antes de apresentar Aiken.

Minha intenção – e espero cumpri-la – é que esta seja a primeira parte de uma série de artigos dedicados a Aiken.

Haskell e Plutus

O coração do Cardano está escrito em Haskell, mas a linguagem que ele usa para criar aplicações e interagir com seu blockchain se chama Plutus, criada pela IOHK. Este é um DSL (Domain Specific Language) baseado em Haskell e projetado especificamente para entender o contexto de Cardano.

Ou seja, para trabalhar com Cardano você não usa especificamente Haskell e sim Plutus. Embora, claro, para manter maior compatibilidade com sua implementação, o Plutus é semelhante ao Haskell. Portanto, conhecimento de Haskell e, acima de tudo, de alguma linguagem de programação funcional pura é um pré-requisito.

A arquitetura de Cardano possui uma máquina virtual que possibilita rodar nela outras ferramentas, como, por exemplo, outra linguagem de programação. E, como mencionei antes, Haskell não roda diretamente na blockchain Cardano, mas sim em cada nó existe um interpretador Plutus.

Este interpretador transforma seu código em Plutus Core, que consiste em dois tipos: Typed Plutus Core (TPC) e Untyped Plutus Core (UPC), linguagens de baixo nível baseadas em System F e Polymorphic Lambda Calculus (essas são construções teóricas, só as menciono para os curiosos sobre a teoria das linguagens de programação).

Por exemplo, o código UPC é o que é executado no Cardano (veja a imagem abaixo). Pode-se pensar, de forma análoga, ao que acontece em Java, quando seu código é compilado com sua máquina virtual JVM e produz bytecodes.

Fonte: https://cardanofoundation.org/en/news/aiken-the-future-of-smart-contracts/

Portanto, nosso próximo convidado (Aiken) adiciona um novo intérprete, uma alternativa ao Plutus, através desta nova linguagem, encarregado de gerar o UPC.

Aiken: uma alternativa para facilitar o caminho para Cardano

Aiken foi originado pelo Cardano Foundation e apresentado em abril de 2023. Além disso, está sob a licença Apache 2.0. Uma breve observação: o nome vem de Howard H. Aiken, um físico americano e pioneiro em ciência da computação.

Assim como o Plutus, o Aiken é uma DSL e foi projetado para contratos inteligentes no Cardano, mas ao contrário do Plutus, o Aiken possui recursos que o tornam mais simples de usar. E foi inspirado em linguagens como Rust, Gleam ou Elm. Todos eles compartilham um sistema de tipo seguro que implica menor possibilidade de erros em tempo de execução. Uma pergunta que nem todas as linguagens oferecem, a saber: Python.

Além disso, quando uma linguagem possui um sistema de tipos robusto, ela tende a ser mais complexa de programar do que uma linguagem com tipagem flexível, já que o compilador coloca mais "barreiras" para evitar que você cometa erros. Por outro lado, em outra linguagem, como o JavaScript, essas barreiras não existem, aumentando os problemas de execução (embora ganhem velocidade de desenvolvimento).

Na apresentação de Aiken foi mencionado o seguinte:

[Aiken] é apresentado em uma sintaxe fácil de aprender, projetada para integração fácil com outras ferramentas e linguagens, e inclui vários recursos de ponta que atendem às expectativas dos desenvolvedores atuais.

Mas como mencionei em meu artigo anterior sobre a linguagem de programação Mojo, essas são afirmações esperadas que todos os criadores de tecnologia repetem, seja para causar impacto na comunidade ou para conquistar usuários. Em suma, devemos ser cautelosos.

Antes de mostrar as suas características e verificar se estas palavras são sustentadas e próximas da realidade, passamos à instalação.

Instalação

Aiken é escrito em Rust, então você verá arquivos .rs (extensão de arquivo Rust).

Linux e MacOS

Você pode abrir o terminal e digitar:

curl -sSfL https://install.aiken-lang.org | bash

Depois, pode ser necessário reiniciar seu terminal para executar:

aikup
Caso seu terminal não reconheça o programa aikup, reinicie-o.


MS Windows

No caso do Windows, você pode instalar primeiro o cargo (gerenciador de pacotes Rust) e então:

cargo install aiken 

Aiken Playground

Você pode usar Aiken Playground caso você queira escrever código sem precisar instalá-lo em seu computador.

Caracteristicas

As características de Aiken são divididas em dois grupos: internas e externas.

  • Os internos são específicos da linguagem: tipagem estática forte, tudo é expressão (como as linguagens do dialeto Lisp), tipos genéricos, tipos customizados, possui módulos e gerenciador de pacotes, entre outros assuntos.
  • Os externos correspondem ao seu ambiente de desenvolvimento. Possui integração com Visual Code e Vim/NeoVim, boa documentação e mensagens de erro são agradáveis.

Criando um novo projeto

Os programas em Aiken têm a extensão .ak e inicie um novo projeto com:

aiken new test/check-even
Neste exemplo o projeto será chamado test/check-even.

Os seguintes arquivos são criados no diretório atual:

.
├── README.md
├── aiken.toml
├── lib
│   └── foo
└── validators

Com o comando aiken build você compila o projeto, enquanto aiken check permite verificar se o programa está em conformidade com o uso correto dos tipos.

Obs: no arquivo .toml você pode modificar os metadados do projeto e adicionar as dependências que seu projeto necessita (este arquivo é utilizado por linguagens modernas como Julia e Rust). Mais informações neste link.

A seguir apresentarei duas características da linguagem.

(1) Sistemas de tipo robusto

Ao observar a sintaxe do Aiken podemos notar uma certa semelhança com Rust e Haskell. Por exemplo, considerei o seguinte código que avalia se um número é par ou não.

fn check_is_even(number: Int) -> Bool {
  (number % 2 == 0)
}

test is_even_0() {
  check_is_even(2) == True
}

A digitação forte pode ser derivada do fato de que a função check_is_even aceita apenas um argumento do tipo Int.

Observe que as apresentações em Aiken começam com fn (assim como Rust) e quando a palavra test é usada significa que será uma função de teste que será executada automaticamente.

Além disso, a palavra reservada não é necessária return para indicar qual valor deve ser retornado. Em vez disso, ele assume que a última expressão avaliada é aquela que é retornada (semelhante ao funcionamento do Scala). Neste caso, a última expressão avaliada é (number % 2 == 0).

Um caso de erro: se dermos um decimal como argumento check_is_even(2.123), retornaria a seguinte mensagem:

I found an unexpected token '"123"'.

Isso mostra que as mensagens de erro no Aiken ainda são imaturas, pois o erro retornado não fornece informações suficientes para entender rapidamente o motivo do erro. Em vez disso, uma mensagem de erro melhor poderia avisar: "Estas intentando pasar un valor decimal en lugar de un Int". Isto certamente será corrigido nas próximas versões do Aiken.

Também no Aiken é possível definir cadastro de tipos customizados:

type Person {
  Person { name : String, age: Int}
}

fn is_member(p : Person) -> Bool {
  when p.age is {
    x if (x > 30) -> True
    _ -> False
  }
}

test create_person() {
  let p = Person { name: @"Aurora", age: 34 }
  is_member(p) == True
}

Isso seria semelhante a definir uma estrutura em C ou uma classe em Python. Uma maneira de encapsular o registro em um tipo. Isso nos lembra Haskell (veja aqui).

Este programa cria um tipo Person, isso tem um nome (name) e idade (age). Em seguida, verifique se essa pessoa é membro. Para fazer isso, você deve ter mais de 30 anos.

A função is_member aplica pattern matching analogamente a linguagens como Rust e Haskell. Se o atributo age do tipo Person é maior que 30 retornará True, se não, False. Observe que a variável x dentro do bloco when é um apelido de p.age. E o símbolo _ (conhecido como wildcard) indica que aceita qualquer tipo, ou seja, se não for maior que 30 sempre retornaráFalse.

(2) Containers

Containers são estruturas de dados para armazenar valores com um respectivo tipo de dados.

Exemplo: Quicksort, um algoritmo para ordenar listas de valores numéricos que divide a lista em duas partes (menor que um número e maior que esse mesmo número) até que seja ordenada do menor para o maior. Usando a estrutura list que vem com a biblioteca padrão Aiken, podemos declarar uma lista de valores inteiros numéricos List<Int>.

use aiken/list

fn quicksort(xs: List<Int>) -> List<Int> {
  when xs is {
    [] ->
      []
    [p, ..tail] -> {
      let before = tail |> list.filter(fn(x) { x < p }) |> quicksort
      let after = tail |> list.filter(fn(x) { x >= p }) |> quicksort
      list.concat(before, [p, ..after])
    }
  }
}

test quicksort_0() {
  quicksort([]) == []
}

test quicksort_1() {
  quicksort([3, 2, 1, 4]) == [1, 2, 3, 4]
  }

test quicksort_2() {
  quicksort([1, 2, 3, 4, 0, -4, 10]) == [-4, 0, 1, 2, 3, 4, 10]
}

O símbolo |> é conhecido como operador de fluxo ou pipeline, porque opera da esquerda para a direita. Tomemos, por exemplo, a seguinte linha:

tail |> list.filter(fn(x) { x < p }) |> quicksort

A lista se aplica aqui tail para a função filter (da esquerda para a direita), então o resultado da função filter é passado como um argumento para quicksort (novamente, da esquerda para a direita). Esta forma de invocar é semelhante à forma como o operador funciona | no Unix. Este é um mecanismo para executar um fluxo de operações encadeadas.

Então, se você executar o código Quicksort, poderá verificar se as três funções test passam nos testes.

Conclusão

Deixo algumas recomendações:

  • Vá além dos fundamentos. Antes de começar com Aiken, conheça Blockchain, Cardano e Smart Contracts (você pode encontrar artigos nesta comunidade) pois, por não ser uma linguagem de programação para todos os tipos de problemas, está projetada para o contexto de criptomoedas e é essencial para tem uma base anterior.
  • Navegue pela sua documentação. No site da Aiken você encontra diversos exemplos para se aprofundar no idioma. Aproveite, porque a documentação está bem concebida.

Também é importante mencionar que, como qualquer nova linguagem, certamente evoluirá no futuro, por isso é uma boa ideia revisar seu repositório, de tempos em tempos, para estar atento às últimas mudanças.

Na parte II veremos como um contrato inteligente é criado em Aiken.

Referências

Para uma introdução geral ao Aiken você pode consultar:

Aiken: the Future of Smart Contracts
Aiken | Installation Instructions
A modern smart contract platform for Cardano

Para entender os aspectos teóricos do Plutus Core, remeto-me a este excelente artigo:

An Introduction to Plutus Core
Plutus Core (PLC) is the programming language that “runs” on the Cardano Blockchain. A blockchain is just a distributed data structure though, so programs do not literally run on it. What we mean is that Plutus Core programs are stored on the blockchain in binary form and can be referenced by transa…

Para uma introdução à programação funcional usando linguagens fortemente tipadas como Haskell e Agda, recomendo meu artigo.

Sucesso!

💡
As opiniões e comentários expressos neste artigo são de propriedade exclusiva de seu autor e não representam necessariamente o ponto de vista da Revelo.

A Revelo Content Network acolhe todas as raças, etnias, nacionalidades, credos, gêneros, orientações, pontos de vista e ideologias, desde que promovam diversidade, equidade, inclusão e crescimento na carreira dos profissionais de tecnologia.