Marlowe Playground - Cumbre Virtual de Cardano del 2020

Sesión de Marlowe Playground de la Cumbre Virtual de Cardano del 2020.
Con subtítulos de transcripción en inglés corregidos, y traducciones al español y al francés.

Hola, soy Pablo, y yo haré la primera mitad de esta presentación,entonces Alex hará la segunda mitad.

Así que, antes de las criptocurrencias,si quisieras hacer una transferencia a través de la internet necesitabas un intermediario, como un banco, y el banco básicamente tiene un libro de cuentas con la cantidad de dinero que tienes en tu cuenta
y cuando hagas la transferencia tienes que decírselo al banco:
OK, ahora tengo menos dinero y el destinatario de la transferencia tiene más dinero.

Y lo que hacen las criptocurrencias es que simplemente distribuyen el libro de cuentas para que todos tengan una copia del libro de cuentas. Con eso podemos esencialmente superar la necesidad de confiar en un tercero, de confiar en el banco.

Pero esto no siempre es suficiente, a veces necesitas hacer otras cosas, como por ejemplo cambiar una cantidad de dinero en una moneda por una cantidad de dinero de una moneda diferente, y no puedes hacer dos transferencias porque entonces una de las dos partes tiene que confiar que la otra parte haga su parte, quienquiera que vaya en segundo lugar, que no se quedará con ambas partes, no, y para eso son los Contratos Inteligentes (“Smart Contracts”).

Los contratos inteligentes son básicamente como los contratos normales, pero están escritos en el libro de contabilidad distribuido, y en lugar de estar escrito en un lenguaje natural están escritos en un lenguaje de programación,
son esencialmente programas de ordenador, y no son interpretados por un juez,son interpretados por una computadora.

No se aplican por ley, …tienen que ser auto-ejecutables. Por ejemplo, un contrato inteligente no puede obligarte a hacer algo o a pagar algo, que es una limitación, pero si transfieres una cantidad de dinero a un contrato, o por ejemplo a una ficha, entonces el contrato puede decidir qué hacer con él.

Así que es autosuficiente en ese sentido. La otra cosa es porque no hay un juez, si cometes un error al escribir un contrato inteligente, entonces no hay nadie que interprete la intención original de ese contrato. El error modificará el contrato, y esas serán las consecuencias del contrato. Así que por ejemplo, puede ser que el dinero terminará yendo a las manos equivocadas,
o incluso puede suceder que el dinero será destruido para siempre. Así que eso es bastante malo.

Entonces, ¿qué hacemos con esto? El lenguaje Marlowe es un Lenguaje de Dominio Específico que tiene como objetivo específico la redacción de Contratos Inteligentes encima de las criptocurrencias, y es muy simple.
Así que si sabes Haskell, puedes generar contratos inteligentes Marlowe muy fácilmente, porque la sintaxis de Marlowe se define como una Tipo de datos Haskell, que puedes ver en esta línea, (lo siento, la sintaxis), y la semántica se define como una función, un conjunto de funciones en Haskell.

Así que es muy, muy sencillo. Además de eso…
así que, ¿por qué querrías usar a Marlowe en lugar de los idiomas de uso general?
Y la razón es que los idiomas de propósito general te dan más flexibilidad de la que probablemente necesites para realizar las transacciones cotidianas o para hacer contratos inteligentes. Con esas flexibilidades también llega la oportunidad para introducir errores en los contratos.

Así que Marlowe ya es bueno porque reduce el número de posibilidades, y también es bueno porque está diseñado para ser fácil de leer, para ser claro, para ser explícito, y para evitar la mayoría de los errores que puedes hacer, bueno, los errores más comunes que puedes hacer, mientras escribes contratos inteligentes, como por ejemplo, olvidándose de dar un tiempo de espera
para que las partes hagan cosas - por ejemplo para hacer un depósito - así que si no le das un tiempo de espera a una parte
la parte puede decidir detener el contrato, que puede resultar en un problema para las otras partes, puede ser aprovechado.

Y también puedes olvidar, por ejemplo, de devolver el dinero si el contrato es abortado, ¿verdad?
Y todo esto lo hace cumplir Marlowe. Además, debido a que es de alcance limitado, somos capaces de analizar estáticamente
contratos Marlowe automáticamente. Así que puedes decir, por ejemplo, que puedes asegurarte que si un contrato de Marlowe
dice que va a pagar una cantidad de dinero, podemos analizar estáticamente si en ese punto en la ejecución del contrato habrá con seguridad suficiente dinero para hacer ese pago.

Así que podemos asegurarnos de que los contratos de Marlowe cumplen sus promesas, ¿verdad?
Y también hemos desarrollado un IDE, un IDE web, que llamamos el Marlowe Playground, que es de lo que trata esta presentación.
Y este Marlowe Playground te permite crear, editar, simular, analizar los contratos, y tanto Alex como yo estaremos usando el Marlowe Playground a partir de ahora para demostrar cómo funciona Marlowe, cómo crear los contratos de Marlowe, y, por supuesto, cómo funciona el Marlowe Playground.

Así que, dame un segundo para compartir mi pantalla…
Bien, déjame darte un tour del Marlowe Playground. El Marlowe Playground tiene tres pestañas, que corresponden a tres formas diferentes de editar los contratos de Marlowe. La pestaña de simulación además de permitirte editar los contratos de Marlowe,
también te permite simular aquí en el lado derecho tienes algunos ejemplos que puedes cargar haciendo clic aquí en la parte superior, por ejemplo aquí está el contrato de custodia ves que en el lado derecho te da las opciones que tendrás para este contrato de custodia.

Alex te mostrará con más detalle cómo funciona esto en la parte inferior se puede ver el estado del contrato, puedes ver la herramienta de análisis estático que puedes usar para los contratos, y se pueden ver advertencias, errores, y el registro de la ejecución, y también vale la pena mencionar que tienes el tutorial aquí. Si quieres saber más sobre Marlowe, encontrarás muchos más detalles aquí.
Déjame mostrarte…
y también encontrarás estos pequeños botones azules alrededor del playground si les das un clic actualizará este contenido desde nuestro centro que también te informará sobre el playground.

La segunda pestaña, Editor de Haskell, te permite generar contratos de Marlowe usando Haskell, y Alex también te mostrará cómo usar esto con más detalle. Y la pestaña Blockly usa Blockly para generar los contratos de Marlowe. Y Blockly es como un rompecabezas para crear contratos, para escribir programas en lenguajes de programación. Y voy a empezar mostrándote la parte de Blockly porque creo que es la manera más fácil para los principiantes de escribir los contratos de Marlowe. Así que, pongámonos manos a la obra.

Quiero mostrarte cómo hacer un contrato que resuelve el problema del que estábamos hablando de intercambiar dinero. Así que voy a escribir un contrato para intercambiar 1.000 dólares por 12.000 Ada. El principal elemento de los contratos es la construcción CONTRACT, y la puedes encontrar aquí. Hay seis construcciones CONTRACT que puedes usar, y todas se ejecutan inmediatamente excepto WHEN.

WHEN es el que toma la entrada de los usuarios y el que toma los activos de los usuarios, así que usaremos WHEN, PAY, y LET.
IF, bueno, IF es lo mismo que de costumbre en lenguajes de programación, toma una observación y dependiendo de la observación
pasará por una rama o por la otra. Las observaciones son simples Booleans, como en un programa normal, tienes TRUE/FALSE, tienes combinaciones de esos, y puedes comparar los valores. Y los valores son enteros que representan cantidades o épocas, no son números.

Y en general los contratos de Marlowe tienen esta estructura, están anidados así, ¿verdad?
Y la cosa que está en la parte superior, la construcción que está en la parte superior es la primera que se ejecuta, y una vez que esa construcción se ejecuta entonces será removida y tomará una de las continuaciones para ser el nuevo contrato.

Así seguirá adelante, desmantelando el contrato, hasta que nos quedemos con la construcción de Close, que es el único que cierra, que no tiene ningún hueco, ¿verdad?
Así que una vez que nos quedemos con el contrato cerrado, el contrato devolverá todo el dinero que tiene, y terminará.
Como dije, vamos ahora a hacer un contrato de intercambio. Así que empecemos por pedirle a los participantes de depositar las cantidades de activos. En este caso queremos que Alice deposite ADA y Bob deposite dólares.

Así que, primero Alice: Verás que la construcción de When tiene un hueco para las Acciones, Las Acciones son estas onstrucciones de aquí, tenemos tres tipos de Acciones, una es para el depósito de activos, una es para hacer Elecciones, y una es la Notificación, que es para esperar que una observación sea cierta. Así, puedes enchufarlo aquí.
Y también puedes tener varias acciones que son alternativas, para que los participantes puedan elegir cualquiera de ellas.
Y también puedes elegir no tener acciones aquí y esto sólo actuará como un timeout.

Así que si dices que este contrato sólo esperará hasta el slot 100 y continuará como- cualquier cosa que pongas aquí. Pero pongamos un depósito de ADA… así que queremos que Alice deposite ADA tenemos dos formas de especificar las partes:
por una Clave Pública, o puedes usar “Role”, que, a diferencia de Public Key es algo que puedes transferir porque está representado por un símbolo. Así que vamos a usar el Role Voy a llamar al Role Alice, y luego tenemos la cantidad de moneda que queremos depositar, y eso está escrito con el tipo Value.

Así que usemos la Constante, y dije que íbamos a depositar 12.064 ADA y ahora tenemos que especificar cuál es la moneda. La moneda se especifica con la construcción Token así que tenemos ADA, muy convenientemente, y tenemos un Token diferente que está representado por dos hashes: el nombre de la moneda y el nombre del token. Pero pongamos Ada para Alice y luego tenemos que especificar en qué cuenta queremos guardar el dinero.

Las cuentas están representadas por un número y un propietario, en este caso queremos que Alice sea la dueña de la cuenta El dueño de la cuenta dice quién va a recibir el dinero cuando lleguemos al final. Así que si al final del contrato todavía hay dinero en esta cuenta irá a Alice. Es por eso que en principio queremos decir que Alice es la dueña de esta cuenta.

Ya he escrito 30 aquí y este es el momento para cuando esperamos que Alice deposite el dinero. Si Alice no ha depositado el dinero por el slot 30 entonces continuará aquí y en este caso sólo queremos cerrar el contrato. Pero si Alice deposita el dinero, entonces queremos que Bob haga lo mismo, así que voy a duplicar esto y ponerlo… oh, espera, necesitamos otra construcción de Wait - y esta vez para Bob vamos a esperar hasta el slot 40

Voy a poner esto dentro… ahora el rol es Bob y la cantidad va a ser de 1.000 y queremos dólares, y no tenemos dólares, pero vamos a imaginar que tenemos una ficha que representa Dólares y su valor de hash va a ser 0000 y 85bb65ff y aquí queremos guardarlo en la cuenta de Bob.

Bien, también queremos cerrar si Bob no deposita el dinero. Así que noten aquí que si Bob no deposita el dinero estamos cerrando, así que el dinero de Alice volverá a Alice porque lo hemos depositado en una cuenta que pertenece a Alice. Pero si llegamos hasta aquí, entonces sabemos que el contrato ya tiene el dinero para Alice y Bob para que podamos intercambiar y se dan el uno al otro el recurso que acaban de depositar.

Así que para eso usamos la construcción Pay, esto es muy similar a Depósito primero tenemos que decir a quién estamos pagando,
así que primero paguemos a Alice, Voy a duplicar esto de nuevo y cuando intentamos encajar aquí vemos que no funciona, la razón por la que no funciona es porque Pay también puede tomar una cuenta como receptor del pago así que tenemos que usar el tipo Payee en su lugar.

Ya ves que puedes poner una cuenta aquí, pero pongamos un Party y luego pongamos el Role real dentro de la construcción del Party. Ahora, la cantidad que queremos pagar a Alice es la que depositó Bob, así que voy a duplicar esto de nuevo. Estoy usando el control V para duplicar esto más rápido, Voy a duplicar el tipo de moneda también, y también la cuenta desde la que estamos pagando, que es la cuenta de Bob.

Y hacemos lo mismo con Bob. Esta vez le pagamos a Bob, y la cantidad que pagamos es esta. Y esta vez le pagamos Ada, y pagamos desde la cuenta de Alice. Así que eso es todo, ahora podemos cerrar el contrato y hemos terminado. Ahora podemos extraer el contrato de Marlowe desde aquí haciendo click en “To Code”, y esto nos lleva a la lengüeta de simulación.

Podemos ver que aquí seríamos capaces de simular esta edición del contrato, y vemos que ya se pide que Alice deposite 12.000 Ada, y si aceptamos eso, entonces se nos pide que Bob deposite 1000, etc, etc. Una cosa que te puedes preguntar es ¿cómo sabemos qué construcción usamos en qué hueco, ¿verdad?
Por ejemplo aquí tuve algunos problemas porque No lo sabía… Intenté encajar un Role en un Party, y tenemos 8 tipos de construcciones en Marlowe.

Así que por ensayo y error esto requiere mucho tiempo, pero hay otra manera de construir los contratos de Marlowe que no requiere que sepas lo que va en cada hueco, y eso se llama Holes ( hoyos ). Así que, noten que si trato de convertir en código un contrato que está incompleto, donde antes teníamos espacios vacíos, ahora tenemos un Hole, que es esta frase que comienza con un signo de interrogación.

Fíjese que el editor ya encontró que hay algo incompleto aquí. Si haces clic aquí, ves que encontró el Hole de tipo Payee que es el tipo que estamos buscando, y si hacemos click en “Quick Fix”, obtenemos todas las construcciones posibles para ese tipo.
Así que en este caso queríamos Party, y podemos hacer lo mismo, podemos de hecho construir un contrato completo haciendo esto.

Por ejemplo, aquí tenemos ya sea Public-Key o Role, así que si hacemos click en “Role” obtendremos esto - …un símbolo erróneo… otra vez, tenemos un texto predeterminado que fue llenado para nosotros, pero aquí queríamos a Bob, creo. Además, podemos cambiar entre Panel de simulación y Blockly, como dije, así que puedes hacer clic aquí para volver a Blockly, así que puedes usar cualquier herramienta que quieras usar en cada punto.

Bien, déjame mostrarte algo más de la funcionalidad de Marlowe, y hagamos este contrato un poco más complicado. Digamos que no queremos especificar cuánto dinero Alice y Bob quieren intercambiar, dejemos que Alice y Bob decidan cuánto. Podemos hacerlo anidando esto más allá… movamos esto a un lado temporalmente.
Pongamos otro " When", pero esta vez vamos a pedir un Choice.

Así que este Choice lo voy a llamar aliceChoice, y la dueña va a ser Alice, que es quien está tomando la decisión, y para los límites de elección estamos usando el tipo Bound que sólo dice entre qué números Alice tiene que elegir. Así que, digamos que entre cien y diez mil. Y vamos a dar hasta el slot diez para hacer esta elección y si no, cerramos el contrato.
Hagamos lo mismo con Bob, démosle a Bob la oportunidad de opinar, y llamamos a esto BobChoice y el Role es Bob en este caso.

Y vamos a dar hasta el slot veinte. Ahora, vamos a calcular cuál es el mínimo que han acordado de la cantidad de dólares a cambiar, y usar eso para calcular la cantidad real que intercambiaremos. Así que para eso vamos a usar la construcción Let, y voy a llamar a esto el amountOfDollars.

Ahora la cantidad de dólares, queremos que sea el mínimo de estas dos cantidades, así que para eso calculamos un valor y usamos el " If Then Else" (Si es así, entonces) que es del tipo Value y queremos decir si la cantidad de Alice es menor que la de Bob
entonces usamos la cantidad de Alice, si no usamos la cantidad de Bob. Para referirnos a las opciones usamos este otro constructo de Value, que se llama …choice by…

Elección en este caso, por ejemplo, aliceChoice, de Alice, representa el valor elegido, y tiene un valor por defecto en caso de que no haya sido elegido, que en este caso es imposible porque estamos en una rama en la que ha sido elegida, así que pongamos la Constante cero aquí. Y hagamos lo mismo con la elección de Bob. …Bob…

Y ahora podemos comparar ambos valores usando la observación Value Is Less Than así que si aliceChoice es menos que el de Bob
entonces ponemos a Alice sino ponemos a Bob. Así que voy a ponerlos en orden inverso… Alice… y if… y ponemos esto aquí.

Así que esto nos da el amountOfDollars y ahora podemos usar este amountOfDollars para calcular la cantidad de Ada y podemos hacer esto usando Let otra vez, y aquí decimos amountOfAda y para hacer una referencia a esta cantidad de dólares usamos el Value Use amountOfDollars pero no queremos que sea lo mismo, queremos tener una tasa de conversión y hacemos la tasa de conversión usando el combinador de escalas y he calculado que esto es 15081 sobre 1250 así que ahora tenemos el amountOfDollars
y el amountOfAda.

Voy a usar esto para todos ellos. amountOfAda así que aquí ahora podemos reemplazar la cantidad de ADA para la variable, también aquí… y la amountOfDollars para el valor y podemos volver a poner el resto del contrato. Así que eso es todo ahora tenemos un contrato más interactivo y si lo enviamos de vuelta al simulador podemos ver que ahora lo primero que pasa es que a Alice se le pide una pregunta así que podemos poner aquí 2000 por ejemplo, y podemos imaginar que Bob dice 1000 y el contrato calcula automáticamente la cantidad de Ada que Alice tiene que poner y la cantidad de dólares que Bob tiene que poner.

Así que eso es básicamente todo. Ahora Alex explicará cómo utilizar el análisis estático para asegurar que los contratos se comporten de la forma en que se deben comportar, y también te mostrará cómo usar el editor de Haskell para generar contratos.

Hola, soy Alex Namish. Veamos el análisis estático y los elementos del editor de Haskell.

Marlowe es un lenguaje no Turing-completo, eso significa que todos los contratos terminan en algún momento, y sabemos el tiempo máximo que un contrato puede tomar de antemano. Por lo tanto, es imposible bloquear el dinero para siempre. En el contrato que Pablo creó el tiempo de expiración es de 40 y podemos ver que en realidad es el máximo tiempo que estamos esperando después de lo cual cerramos el contrato.

La belleza del diseño de Marlowe es que es posible analizar los contratos de forma estática, usando solucionadores SMT. Los solucionadores SMT son una clase de software que resuelve ecuaciones en forma simbólica. Representamos un contrato de Marlowe como una ecuación y preguntamos al solucionador si puede encontrar una secuencia de entradas de usuario que llevaría a un pago parcial o fallido.

Por ejemplo, en el contrato de Pablo, si por error preguntáramos para pagar amountOfAda en lugar de amountOfDollars aquí, que en este caso sería una cantidad mayor, eso podría conducir potencialmente a un pago fallido, porque no tenemos suficiente dinero en la cuenta y esto se puede pasar por alto fácilmente durante el desarrollo porque es fácil cometer un error. Pero si le preguntamos al solucionador si pudiera encontrar una secuencia de entradas que conducen a un error, dice que sí!

El solucionador podría encontrar un contraejemplo y la advertencia fue emitida. Pudo encontrar un pago parcial de la cuenta de Bob a Alice, y la cantidad que se espera pagar es 15081 pero la cuenta en este punto contiene sólo 1250, y aquí están los valores exactos aportados por los usuarios que podrían llevar a este error.

Así que vemos que tomamos decisiones, 1250, 1251, hacemos los respectivos depósitos, y después de eso usamos el valor equivocado
y tratamos de pagar una cantidad equivocada. Quiero mostrarte la función de Holes que Pablo mencionó en su parte de la charla.
Podemos crear contratos usando la función “Quick Fix” del editor. Construyamos un simple contrato de fondo fiduciario.

Alice deposita dinero en un contrato de una manera que su hijo Bob puede obtener el dinero en la fecha de vencimiento. El contrato permite a Alice recuperar su dinero antes de la fecha de vencimiento si cambia de opinión. Primero, tenemos que hacer un depósito, digamos antes del slot 3, de lo contrario no hacemos nada.

La acción que esperamos es el depósito, en la cuenta de Alice, hecho por Alice … (Papel … Alice …) Podemos dar formato a nuestro documento para hacerlo más legible. Esperemos la ficha por defecto, y el valor de 1 millón. Aquí Alice hizo un depósito,
dejemos que cambie de opinión. Para eso esperamos un Choice, llamémoslo reembolso.

Esta elección debe ser hecha por Alice, por supuesto, y el único valor que necesitamos es un valor único, cero está bien. Eso sería que Alice decide reembolsar. En este caso simplemente cerramos el contrato porque el dinero depositado en la cuenta de Alice será reembolsado al cierre del contrato. Digamos que la fecha de vencimiento es el 10, slot 10, en este caso necesitamos pagarle dinero a Bob.

Utilizamos el constructo Pay de la cuenta de Alice, pagamos a Bob … ficha por defecto … … valor … vamos a copiar-pegar … …y luego cerramos. Vemos que este contrato expira en el slot 10, y si lo analizamos estáticamente vamos a ver una advertencia, porque cometí un error, y recibimos una advertencia de pago parcial. Se supone que el contrato debe hacer un pago
de 10 millones de unidades, pero sólo hay un millón.

El análisis estático también muestra la lista de los aportes esperados que llevan a este resultado. Por ejemplo, vemos aquí que primero esperamos una transacción con las siguientes entradas: esperamos un depósito de Alice de 1 millón de unidades, entonces esperamos una transacción vacía con un intervalo de 10 a 10, eso significa que necesitamos producir una transacción después del slot 10.

En este caso, llegaremos a esta construcción de pago que intenta pagar 10 millones de unidades en lugar de un millón. Una forma de evitar este tipo de error es usar una construcción especial, AvailableMoney (Dinero Disponible), para que podamos tomar todo el dinero disponible en la cuenta de Alice, de la Ficha de Default. Eso debería funcionar. Simulemos la ejecución de este contrato, utilizando el compositor de entradas y el compositor de transacciones.

En la blockchain, se ejecuta un contrato para validar una transacción que transfiere fichas. Un contrato de Marlowe recibe insumos y asegura que la transacción está entregando fichas de acuerdo con las entradas y la lógica del contrato. Una transacción puede contener 0, 1, o muchas entradas a la vez.

Nuestro compositor de entrada inteligente analiza un contrato y proporciona una lista de posibles aportaciones en cada paso de un contrato. En este caso la única entrada posible actualmente disponible es depositar 1 millón de unidades de ADA en la cuenta de Alice. Podemos presionar este botón Más para añadir esta entrada a la transacción.

Si lo aplicamos, vemos en los registros que depositamos 1 millón de unidades en la cuenta de Alice, y sobre el estado actual
vemos que la cuenta 0 de Alice contiene un millón de unidades. Entonces, esperamos el reembolso, y si Alice decide reembolsar
vemos que la elección se hace y una vez que veamos que la participante Alice elige 0 para un reembolso ella recuperó su dinero.

Asumamos que todo funciona como se espera, y recibimos dinero de Alice, y esperamos hasta el bloque 14. Entonces vemos en los registros que en realidad Bob recibió todo el millón y el contrato está cerrado. Muchos errores comunes se muestran inmediatamente por el Marlowe playground. Digamos que tratas de elegir un valor fuera de los límites Recibes una advertencia
y no puedes usar esta entrada.

Si intentas utilizar una cuenta equivocada para el pago tienes una advertencia que dice que el pago se hace antes de que se haya hecho un depósito y si el tiempo de espera inicial ha pasado, ni siquiera puedes hacer un depósito inicial. Todo esto es genial,
pero, ¿y si hacer fondos fiduciarios es tu negocio y te gustaría hacer esos contratos de forma regular, te gustaría hacer una plantilla de este contrato, para instanciarla con una cantidad particular a pagar, o diferentes roles o diferentes tiempos de espera.

Para eso puedes usar la lengüeta de editor de Haskell en el Marlowe playground. Este es un programa de Haskell de un solo archivo que se compila y se ejecuta como AWS lambda. Se supone que imprime un contrato de Marlowe a la salida estándar.
Esencialmente puedes usar todo el sistema de Haskell para generar un contrato de tamaño y complejidad arbitraria.

Si sólo copio/pego el contrato que acabamos de desarrollar, Puedo compilarlo, y recuperar el contrato de Marlowe. Puedo enviarlo al simulador y probarlo como lo hicimos antes pero ahora puedo generalizar este contrato. Por ejemplo, quiero añadir una cantidad y fecha de vencimiento como parámetros.

Cantidad usaría para la cantidad a pagar y la fecha de vencimiento yo usaría aquí. Ahora bien, si aplico cinco mil y slot doce
y yo compilo, Puedo crear una instancia del fondo fiduciario de cinco mil unidades que expira en el slot doce.

[música]