Uso de Marlowe desde la línea de comandos de ghci

Este tutorial muestra cómo utilizar Marlowe desde Haskell, y en particular muestra cómo ejercer un contrato utilizando la semántica dada anteriormente.

 

Marlowe en Haskell

Este tutorial funciona en la versión 3.0 de Marlowe que se encuentra en la rama master del repositorio:

 

Atravesar por los contratos

Como hemos visto antes, la semántica de una transacción individual está definida por la función

donde los tipos se definen así:

States se definen así, con una función de ayuda para definir un estado inicialmente vacío:

Podemos utilizar las prestaciones de ghci para recorrer un contrato transacción por transacción, y, en este caso, lo haremos con el contrato de depósito en garantía incluido en `EscrowSimmpleV2.hs <https://github.com/input-output-hk/marlowe/blob/master/semantics-3.0/src/Language/Marlowe/Examples/EscrowSimpleV2.hs>`_.

Para ir paso a paso, puedes trabajar en ghci de esta manera, utilizando la facilidad de hacer enlaces locales:

Prelude> :set -XOverloadedStrings

Prelude> :l Language/Marlowe/Examples/EscrowSimpleV2.hs

 ...

*Lang...V2> let (TransactionOutput txWarn1 txPay1 state1 con1) = computeTransaction (TransactionInput (0, 0) [IDeposit "alice" "alice" ada 450]) (emptyState 0) contract

Al hacer esto, hemos comparado el patrón de salida de una aplicación de computeTransaction, que toma tres entradas: la segunda es un estado inicial (en el slot número 0) y la tercera es el contrato de custodia inicial. La primera es un TransactionInput que contiene un SlotInterval – aquí SlotInterval 0 0 – y un depósito de 450 Lovelace de "alice" a su cuenta "alice" , es decir, IDeposit "alice" "alice" ada 450.

 

Nota

Si quieres probar esto por ti mismo en ghci, puedes copiar y pegar de los ejemplos de código en el documento original (ver enlace al final de la página): están en ventanas de desplazamiento horizontal.

 

La salida está relacionada con TransactionOutput txWarn1 txPay1 state1 con1 para poder examinar los distintos componentes por separado:

*Lang...V2> txWarn1

[]

*Lang...V2> txPay1

[]

*Lang...V2> state1

State {accounts = fromList [("alice", ada), 450)], choices = fromList [], boundValues = fromList [], minSlot = 0}

*Lang...V2> con1

When [Case (Choice (ChoiceId "choice" "alice") [Bound 0 1])

 ...

Esto muestra que la transacción no genera advertencias ni pagos, pero actualiza el estado para mostrar el saldo en la cuenta "alice", y actualiza el contrato, listo para recibir una elección de Alice o Bob.

En el siguiente estado el contrato está a la espera de la entrada, y si tanto Alice como Bob están de acuerdo en hacer un pago a Bob eligiendo 0, entonces se genera un pago a Bob. Esto se verifica a través de esta interacción en GHCI:

*Lang...V2> let (TransactionOutput txWarn2 txPay2 state2 con2) = computeTransaction (TransactionInput (SlotInterval 0 0) [IChoice (ChoiceId "choice" "alice") 0, IChoice (ChoiceId "choice" "bob") 0]) state1 con1

*Lang...V2> txPay2

[Payment "bob" ada 450]

*Lang...V2> con2

Close

*Lang...V2> state2

State {accounts = fromList [], choices = fromList [(ChoiceId "choice" "alice",0),(ChoiceId "choice" "bob",0)], boundValues = fromList [], minSlot = 0}

Una forma alternativa de hacerlo es añadir estas definiciones a un archivo de trabajo, por ejemplo Build.hs, donde se conservarán estas definiciones. De hecho, sería muy sensato incluir algunas de las definiciones utilizadas anteriormente en dicho archivo.

 

Rutas alternativas a través del contrato

Los enlaces locales se pierden cada vez que un comando :load o :l se ejecuta, lo que nos permite reutilizar algunos comandos anteriores. Una ejecución alternativa del contrato viene dada por

  • Primer paso: Alicia deposita el dinero como en el ejemplo anterior.
  • Segundo paso: Alice y Bob seleccionan diferentes opciones. Esto puede hacerse así:

*Lang...V2> let (TransactionOutput txWarn2 txPay2 state2 con2) = computeTransaction (TransactionInput (SlotInterval 0 0) [IChoice (ChoiceId "choice" "alice") 0, IChoice (ChoiceId "choice" "bob") 1]) state1 con1

*Lang...V2> con2

When [Case (Choice (ChoiceId "choice" "carol") [Bound 1 1]) Close, Case (Choice (ChoiceId "choice" "carol") [Bound 0 0]) (Pay "alice" (Party "bob") ada (Constant 450) Close)] 100 Close

*Lang...V2> state2

State {accounts = fromList [("alice", ada), 450)], choices = fromList [(ChoiceId "choice" "alice",0),(ChoiceId "choice" "bob",1)], boundValues = fromList [] , minSlot = 0}

Esto muestra que ahora estamos en un contrato en el que la elección depende de Carol, y que todavía existen los 450 Lovelace en la cuenta "alice" .

  • Tercer paso: Carol hace una elección. Si elige 0, se paga a Bob. Si elige 1, se devuelve el dinero a Alice. Hagamos esto ahora:

*Lang...V2> let (TransactionOutput txWarn3 txPay3 state3 con3) = computeTransaction  (TransactionInput (SlotInterval 0 0) [IChoice (ChoiceId "choice" "carol") 1]) state2 con2

*Lang...V2> txPay3

[Payment "alice" ada 450]

*Lang...V2> con3

Close

*Lang...V2> state3

State {accounts = fromList [], choices = fromList [(ChoiceId "choice" "alice",0), (ChoiceId "choice" "bob",1),(ChoiceId "choice" "carol",1)], boundValues = fromList [], minSlot = 0}

Así que ahora el contrato está listo para Close, y así devolver el dinero restante, pero está claro por state3 que no hay cuentas con saldos distintos de cero, por lo que el contrato se termina.

¿Por qué es útil ir paso a paso? Es el equivalente a un debugging, y podemos ver el estado interno del contrato en cada etapa, la continuación del contrato, es decir, lo que queda por ejecutar, y las acciones producidas en cada paso.

 

Ejercicio

Explora otras formas de abordar el contrato: ¿qué ocurre si Bob y Alice deciden devolver el dinero a Alice? - ¿Qué ocurre si Bob y Alice no están de acuerdo, pero Carol se pone del lado de Bob?

© Copyright 2020, IOHK Revision 1b7b1fc1.

 

Encuentra una copia oficial de este documento aquí:

https://alpha.marlowe.iohkdev.io/doc/marlowe/tutorials/using-marlowe.html

https://docs.cardano.org/projects/plutus/en/latest/marlowe/tutorials/using-marlowe.html

 

Más traducciones de Cardano en: Cardano For The World