Utiliser Marlowe depuis la ligne de commande ghci
Ce tutoriel vous montre comment utiliser Marlowe à partir de Haskell, et en particulier comment exercer un contrat en utilisant la sémantique donnée antérieurement.
Marlowe en Haskell
Ce tutoriel fonctionne avec la version 3.0 de Marlowe qui se trouve dans la branche master du dépôt:
Traverser les contrats
Comme nous l'avons vu précédemment, la sémantique d'une transaction unique est définie par la fonction
où les types sont définis comme ça :
et States sont définis comme suit, avec une fonction d'aide pour définir un état initialement vide:
Nous pouvons utiliser les services de ghci pour parcourir un contrat une transaction à la fois, et, ici, nous le ferons avec le contrat d'entiercement intégré contenu dans `EscrowSimmpleV2.hs <https://github.com/input-output-hk/marlowe/blob/master/semantics-3.0/src/Language/Marlowe/Examples/EscrowSimpleV2.hs>`_.
Pour aller à un seul pas a la fois, vous pouvez travailler dans ghci comme ceci, en utilisant la possibilité de faire des liens locaux:
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
En faisant cela, nous avons mis en correspondance la sortie d'une application de computeTransaction, qui prend trois entrées : la deuxième est un état initial (au slot numéro 0) et la troisième est le contrat d'entiercement initial. La première est un TransactionInput qui contient un SlotInterval – ici SlotInterval 0 0 – et un dépôt de 450 Lovelace de "alice" sur son compte "alice" , plus précisément IDeposit "alice" "alice" ada 450.
Note
Si vous voulez essayer ceci par vous-même dans ghci, vous pouvez copier et coller les exemples de code dans le document original (voir le lien en bas de page) : ils sont dans des fenêtres à défilement horizontal.
La sortie est appariée avec TransactionOutput txWarn1 txPay1 state1 con1 afin que nous puissions examiner les différents composants séparément:
*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])
...
Cela montre que la transaction ne génère aucun avertissement ou paiement, mais met à jour l'état pour montrer le solde du compte "alice", et met à jour le contrat, prêt à recevoir un choix d'Alice ou de Bob.
Dans l'état suivant, le contrat est en attente d'entrée, et si Alice et Bob sont d'accord pour effectuer un paiement à Bob en choisissant 0, alors un paiement à Bob est généré. Ceci est vérifié par cette interaction dans 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}
Une autre façon de procéder est d'ajouter ces définitions à un fichier de travail, par ex. Build.hs, où ces définitions seront conservées. En effet, il serait très judicieux d'inclure certaines des définitions utilisées ci-dessus dans un tel fichier.
Routes alternatives à travers le contrat
Les liaisons locales sont perdues chaque fois qu'une commande :load ou :l est exécutée, ce qui nous permet de réutiliser certaines commandes antérieures. Une exécution alternative du contrat est donnée par
- Première étape : Alice dépose de l'argent comme dans l'exemple précédent.
- Deuxième étape : Alice et Bob choisissent des options différentes. Cela peut être fait comme suit:
*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}
Cela montre que nous sommes maintenant dans un contrat où le choix appartient à Carol, et qu'il y a toujours les 450 Lovelace dans le compte "alice" .
- Troisième étape : Carole fait un choix. Si elle choisit 0, le paiement à Bob est effectué. Si elle choisit 1, Alice est remboursée. Faisons cela maintenant:
*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}
Donc maintenant le contrat est prêt à Close, et donc de rembourser l'argent restant, mais il est clair, d'après state3 qu'il n'y a pas de comptes contenant des soldes non nuls, donc le contrat est terminé.
Pourquoi le pas à pas est-il utile ? C'est l'équivalent du débogage, et nous sommes en mesure de voir l'état interne du contrat à chaque étape, la suite du contrat, c'est-à-dire ce qui reste à exécuter, et les actions produites à chaque étape.
Exercice
Explorez d'autres façons d'aborder le contrat - Que se passe-t-il si Bob et Alice choisissent de rembourser l'argent à Alice ? - Que se passe-t-il si Bob et Alice sont en désaccord, mais que Carol se range du côté de Bob ?
© Copyright 2020, IOHK Revision 1b7b1fc1.
Vous trouverez une copie officielle de ce document ici :
https://alpha.marlowe.iohkdev.io/doc/marlowe/tutorials/using-marlowe.html
https://docs.cardano.org/projects/plutus/en/latest/marlowe/tutorials/using-marlowe.html
Plus de traductions de Cardano à: Cardano For The World