Compilando y Ejecutando Smart Contracts (1)

Published on Author lopezLeave a comment

Quisiera explorar en esta serie algunas de las opciones para compilar y ejecutar smart contracts en una blockchain. Alguna de estas opciones ya existen, y otras son más experimentales o solamente ideas. Aunque este primer post está centrado en smart contracts con Ethereum, planeo comentar otras implementaciones más adelante.

Si no conocen de smart contracts en Ethereum, recomiendo la lectura de:

A 101 Noob Intro to Programming Smart Contracts on Ethereum
Making Sense of Blockchain Smart Contracts
Writing a contract

El camino usual para programar y ejecutar un smart contra en esta plataforma, es escribir el código fuente en el lenguaje de programación Solidity, compilarlo a bytecodes, y ejecutar el programa resultante usando la Ethereum Virtual Machine:

Pero hay otras opciones en lenguajes de programación, que también compilan a bytecodes Ethereum, como Serpent, LLL:

Pero de lejos, Solidity es el lenguaje de programación más usado. Hay un creciente ecosistema de herramientas alrededor de Solidity, y muchos ejemplos están escritos en este lenguaje.

Otra opción (que yo sepa, aún no implementada), es compilar un lenguaje de programación clásico a bytecodes Ethereum (tal vez imponiendo algunas restricciones):

Esto no es una tarea fácil: el lenguaje de programación original (Java, JavaScript, C#) tiene su propia semántica, que aún con restricciones, podría no ser simple de implementar en bytecodes Ethereum. Pero una ventaja de este camino es que los desarrolladores podrían usar las herramientas (editores, IDEs, depuradores, tests…) original de esos lenguajes para escribir smart contracts.

Ejecutando los bytecodes en una Ethereum Virtual Machine implica leer bytecode por bytecode, y ejecutar su semántica en un gran “switch and loop”. Pero no es ésta la única opción. Los bytecodes podrían ser compilados a algo más optimizado:

Como una implementación de esta forma, hay código en la implementación Ethereum en Go: tienen un compilador JIT (Just In Time), leer el post Optimising the Ethereum Virtual Machine. Fragmento:

The go-ethereum repository implements —among the Ethereum client and tool suite— the Ethereum Protocol in the Go language. It contains two implementation of the EVM, one extremely simple byte code interpreter that simple loops over the byte code and a JIT-like interpreter that compiles the byte code in to manageable data types and structures.

Y todavía hay otro “approach”: compilar la semántica de los bytecodes directamente en un lenguaje de programación clásico, y entonces compilar/interpretar el código resultado usando el compilador/intérprete nativo de ese lenguaje:

El código fuente producido de esta manera podría usar las estructuras de datos de la Ethereum VM, como el almacén (storage) de los contratos. Un tema a resolver en este camino es que los bytecodes producidos pueden haber perdido algo de la intención original del código inicial del contrato (en Solidity, por ejemplo),  porque el compilador original puede haber transformado en formas complicadas la sentencias originales. Como ejemplo, una simple operación de un entero o un string en Solidity se mapea a muchos bytecods, porque no existen esas operaciones simples en la especificación de la Ethereum VM: la VM está orientada a manejar números enteros de 32 bytes (a veces, direcciones de 20 bytes). Entonces, los bytecodes no reflejan en general el código inicial de una forma clara y directa.

Una variante de lo anterior: en vez de generar código fuente en un lenguaje de programación clásico, la salida puede ser directamente bytecodes orientados al ejecutor fina, por ejemplo, bytecodes Java o bytecodes CLR .NET. Pero pienso que esto es sólo un caso de optimización de lo anterior, que primero hay que explorar la generación de código fuente, y recién cuando este camino demuestre alguna ventaja, pasar a generar los bytecodes finales directamente. Generando primero código fuente, sería más fácil investigar la calidad del código generador, depurarlo, mejorarlo. Generar directamente bytecodes finales lo dejaría para una segunda fase.

Otra idea que me gustaría investigar: compilar código fuente existente de un contrato (por ejemplo Solidity) en código fuente de un lenguaje de programación clásico:

De esta manera, la semántica original de enteros, strings, mapas podría ser implementado directamente en Java o en C#: al final, solamente el estado del almacén (storage) es importante en un smart contract Ethereum: es el modo de controlar que todos los nodos ejecutan el contrato de la misma forma. Si un contrato Solidity pudiera ser compilado de esta forma, sin alterar el resultado de su ejecución, es decir, produciendo cada vez que se ejecuta el mismo resultado que cuando es compilado a bytecodes EVM, entonces el programador de contratos podría usar e implantar ese código generado con las herramientas del lenguaje final.

Pienso que Solidity+Ethereum VM es la implementación más popular, en camino a ser el estándar “de facto”, con más y más herramientas en su ecosistema. Pero otras opciones igual merecen una implementación exploratoria.

Próximos posts: otras implementaciones fuera de Ethereum, como la de Lisk que ejecuta smart contracts en JavaScript usando NodeJS; más discusiones de las opciones enumeradas en este post; implementaciones alternativas; investigación de cómo se compila Solidity a bytecodes.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Leave a Reply

Your email address will not be published. Required fields are marked *