{ "cells": [ { "cell_type": "markdown", "id": "68e6f255-3dcd-4651-9510-ef1d417bafc3", "metadata": {}, "source": [ "# Conducting a Raffle Using Marlowe\n", "\n", "\n", "**Executive Summary**\n", "\n", "This example demonstrates conducting a raffle using Marlowe. The contract contains a list of addresses of participants who have entered the raffle, and a random oracle selects and pays one of them. The Blockly diagram below shows a simple raffle with three participants. For large numbers of participants, multiple nested `When` statements are used to hierarchically decompose the search for the winner, so that the Plutus execution budget is not exceeded by the Marlowe contract. Instead of awarding to specific addresses, this example could trivially be modified to award to the holders of a sequence of role tokens.\n", "\n", "![Marlowe contract for a raffle](contract.png)\n", "\n", "A [video demonstration of this example](https://youtu.be/wtUFkElA-u0) is available." ] }, { "cell_type": "markdown", "id": "77972b8b-6ffb-43cf-9146-f34b737c9115", "metadata": {}, "source": [ "## Program for Generating the Contract\n", "\n", "Create a Haskell program that will generate a contract for the given participants..\n", "\n", "The program outputs the file [contract.json](contract.json)." ] }, { "cell_type": "code", "execution_count": 2, "id": "5e86a115-5b6a-4e65-9a36-63b781eb4685", "metadata": { "tags": [] }, "outputs": [], "source": [ "cat << EOI > contract.hs\n", "\n", "{-# LANGUAGE NumericUnderscores #-}\n", "{-# LANGUAGE OverloadedStrings #-}\n", "{-# LANGUAGE Trustworthy #-}\n", "\n", "module Main (\n", "-- * Entry point\n", " main\n", "-- * Contracts\n", ", makeContract\n", ") where\n", "\n", "import Data.Aeson ((.=), encodeFile)\n", "import Data.List.Split (chunksOf)\n", "import Data.Maybe (fromJust)\n", "import Data.String (fromString)\n", "import Data.Text (pack)\n", "import Language.Marlowe.Core.V1.Semantics.Types\n", "import Language.Marlowe.Core.V1.Semantics.Types.Address (deserialiseAddressBech32)\n", "import Plutus.V2.Ledger.Api (POSIXTime(..), TokenName(..))\n", "import System.Environment (getArgs)\n", "\n", "-- | Print the contract.\n", "main :: IO ()\n", "main =\n", " do\n", " size : sponsor : oracle : amount : deposit : select : payout : parties <- getArgs\n", " let\n", " readAddress = uncurry Address . fromJust . deserialiseAddressBech32 . pack\n", " contract =\n", " makeContract\n", " (readAddress sponsor)\n", " (readAddress oracle)\n", " (read amount)\n", " (read size)\n", " (zip [1..] $ readAddress <$> parties)\n", " (fromInteger $ read deposit)\n", " (fromInteger $ read select)\n", " (fromInteger $ read payout)\n", " encodeFile \"contract.json\" contract\n", "\n", "makeContract\n", " :: Party\n", " -> Party\n", " -> Integer\n", " -> Int\n", " -> [(Integer, Party)]\n", " -> POSIXTime\n", " -> POSIXTime\n", " -> POSIXTime\n", " -> Contract\n", "makeContract sponsor oracle amount size parties deposit select payout =\n", " makeDeposit sponsor amount deposit\n", " $ selectWinner oracle (toInteger $ length parties) select\n", " $ payWinner sponsor oracle amount size parties payout\n", " \n", "ada :: Token\n", "ada = Token \"\" \"\"\n", "\n", "makeDeposit\n", " :: Party\n", " -> Integer\n", " -> POSIXTime\n", " -> Contract\n", " -> Contract\n", "makeDeposit sponsor amount deadline contract =\n", " When\n", " [Case (Deposit sponsor sponsor ada (Constant amount)) contract]\n", " deadline\n", " Close\n", " \n", "selectWinner\n", " :: Party\n", " -> Integer\n", " -> POSIXTime\n", " -> Contract\n", " -> Contract\n", "selectWinner oracle count deadline contract =\n", " When\n", " [Case (Choice (ChoiceId \"Random\" oracle) [Bound 1 count]) contract]\n", " deadline\n", " Close\n", "\n", "payWinner\n", " :: Party\n", " -> Party\n", " -> Integer\n", " -> Int\n", " -> [(Integer, Party)]\n", " -> POSIXTime\n", " -> Contract\n", "payWinner sponsor oracle amount size parties deadline\n", " | length parties <= size = When\n", " [\n", " Case (Notify (ValueEQ (ChoiceValue (ChoiceId \"Random\" oracle)) (Constant i)))\n", " $ Pay sponsor (Party party) ada (Constant amount) Close\n", " |\n", " (i, party) <- parties\n", " ]\n", " deadline\n", " Close\n", " | otherwise = When\n", " [\n", " Case (Notify (ValueLE (ChoiceValue (ChoiceId \"Random\" oracle)) (Constant . fst $ last parties')))\n", " $ payWinner sponsor oracle amount size parties' deadline\n", " |\n", " let chunks k xs = chunksOf (div (length xs + k - 1) k) xs\n", " , parties' <- chunks size parties\n", " ]\n", " deadline\n", " Close\n", "\n", "EOI" ] }, { "cell_type": "markdown", "id": "e80d8e2e-574b-4992-a6a9-1e6dd222d848", "metadata": {}, "source": [ "## Constants\n", "\n", "It is convenient to define serveral constants." ] }, { "cell_type": "code", "execution_count": 3, "id": "88f6d4e0-2271-42cc-9cfe-177362edf9e9", "metadata": { "tags": [] }, "outputs": [], "source": [ "ADA=1000000" ] }, { "cell_type": "code", "execution_count": 4, "id": "9f29bd5b-331b-44b3-84c4-613dde94a4d7", "metadata": { "tags": [] }, "outputs": [], "source": [ "SECOND=1000\n", "MINUTE=$((60 * SECOND))\n", "HOUR=$((60 * MINUTE))" ] }, { "cell_type": "markdown", "id": "d3309f9b-05ae-40a2-bcb2-fce50a23bdac", "metadata": {}, "source": [ "## Network\n", "\n", "Use the preproduction network." ] }, { "cell_type": "code", "execution_count": 5, "id": "19bcdb57-0e35-4005-96f0-15f8e33dbad2", "metadata": { "tags": [] }, "outputs": [], "source": [ "export CARDANO_NODE_SOCKET_PATH=/extra/iohk/networks/preprod/node.socket\n", "export CARDANO_TESTNET_MAGIC=1" ] }, { "cell_type": "markdown", "id": "abee7907-41f2-4dfd-95c5-0531ec09ded7", "metadata": {}, "source": [ "## Parties to the contract\n", "\n", "Set the signing keys and addresses for parties to the contract." ] }, { "cell_type": "markdown", "id": "2c00784c-ea35-49d3-ba8f-da4b0efdee03", "metadata": {}, "source": [ "### Sponsor\n", "\n", "The *Sponsor* provides the funds for the raffle." ] }, { "cell_type": "code", "execution_count": 6, "id": "8f8efcc6-3576-4409-a128-6379af0d162c", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "c.marlowe @ addr_test1vrtntkszteptml4e9ce9l3fsmgavwv4ywunvdnhxv6nw5ksq6737a\n" ] } ], "source": [ "SPONSOR_NAME=c.marlowe\n", "SPONSOR_SKEY=../keys/$SPONSOR_NAME.skey\n", "SPONSOR_ADDR=$(cat ../keys/$SPONSOR_NAME.testnet.address)\n", "echo \"$SPONSOR_NAME \"@\" $SPONSOR_ADDR\"" ] }, { "cell_type": "markdown", "id": "6e4f1377-6ccd-465b-b893-24ed4912887a", "metadata": {}, "source": [ "### Oracle\n", "\n", "The *Oracle* provides the random number for the raffle." ] }, { "cell_type": "code", "execution_count": 7, "id": "f680c8e8-16cc-4b1a-8540-514ec91c3215", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "f.beaumont @ addr_test1vqhqudxtwqcpjqesns79hqgqq2q0xx5q0hnzz5es9492yaqpxltpy\n" ] } ], "source": [ "ORACLE_NAME=f.beaumont\n", "ORACLE_SKEY=../keys/$ORACLE_NAME.skey\n", "ORACLE_ADDR=$(cat ../keys/$ORACLE_NAME.testnet.address)\n", "echo \"$ORACLE_NAME\" @ \"$ORACLE_ADDR\"" ] }, { "cell_type": "markdown", "id": "7d298a81-82ce-4712-8ba7-41804ea3c1f0", "metadata": {}, "source": [ "### Participants\n", "\n", "Normally, the list of addresses for the *Participants* would be provided. Here, for convenience, we just derive each participants's address from the same root private key." ] }, { "cell_type": "code", "execution_count": 8, "id": "f9bcd006-a67c-4119-9b98-5598a60b9f28", "metadata": { "tags": [] }, "outputs": [], "source": [ "ROOT_PRV=../keys/william-shakespeare.root.prv" ] }, { "cell_type": "markdown", "id": "20dd6008-fd93-47b6-abcc-ef1206ebb01b", "metadata": {}, "source": [ "Also for convenience, the scholars will share the same stake key." ] }, { "cell_type": "code", "execution_count": 9, "id": "5720224a-df35-45a1-91e3-6a5f41eca9d6", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Stake address = stake_test1urplvp2a7dythh6yxutd0qlzzkncr3gy5ftvxj02d3etafqjugc5h\n" ] } ], "source": [ "cardano-wallet key child 1852H/1815H/0H/2/0 < \"$ROOT_PRV\" \\\n", "| cardano-cli key convert-cardano-address-key --shelley-stake-key --signing-key-file /dev/stdin --out-file /dev/stdout \\\n", "| cardano-cli key verification-key --signing-key-file /dev/stdin --verification-key-file /dev/stdout \\\n", "| cardano-cli key non-extended-key --extended-verification-key-file /dev/stdin --verification-key-file ../keys/william-shakespeare.stake.vkey\n", "STAKE_ADDR=`cardano-cli stake-address build --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --stake-verification-key-file ../keys/william-shakespeare.stake.vkey`\n", "echo \"Stake address = $STAKE_ADDR\"" ] }, { "cell_type": "markdown", "id": "4e8d89bc-f34a-4f67-8719-623fdaf6ad02", "metadata": {}, "source": [ "Set the number of scholars." ] }, { "cell_type": "code", "execution_count": 10, "id": "0db93c47-9b36-4b05-8e40-38128d657eef", "metadata": { "tags": [] }, "outputs": [], "source": [ "NUMBER_OF_PARTICIPANTS=125" ] }, { "cell_type": "markdown", "id": "a77d5fc7-71fc-4a26-a93d-33233428be7d", "metadata": {}, "source": [ "Compute the addresses of the scholars." ] }, { "cell_type": "code", "execution_count": 11, "id": "538ab429-feaa-4a83-a3d4-bedf974913ec", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Participant 1 = 1852H/1815H/0H/0/2 = addr_test1qzenwj7elwatk3mmc368mwnv067fqnuk3x7u4nqw5dezg8wr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqf6k36p\n", "Participant 2 = 1852H/1815H/0H/0/3 = addr_test1qraxynufcduk7ak7nke2jm6pnc32vn7wsmm7ml30cutfgg7r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq77wfgp\n", "Participant 3 = 1852H/1815H/0H/0/4 = addr_test1qzlwepx5u26a8w94kfrkfem6njlam22emyhjscu0lxqrce7r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq5jnrn3\n", "Participant 4 = 1852H/1815H/0H/0/5 = addr_test1qqjrjfslev50d5jn6qdeztxsqvuaaefq6e4hu55n59grjj7r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqwhulyr\n", "Participant 5 = 1852H/1815H/0H/0/6 = addr_test1qqxrzfv0v8l0lahyc5qsgpug66dafp8njl278g0pter7e3xr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqcjuuw0\n", "Participant 6 = 1852H/1815H/0H/0/7 = addr_test1qqqfzyuqkvrr7ajgk887sqac8lgzatc6el9uxke4x5g5dg7r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqkmrpwu\n", "Participant 7 = 1852H/1815H/0H/0/8 = addr_test1qp77epd4gy5hrt8pnh6h73se4durwrrkes3u0vj6tycwsq7r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq7kyfpt\n", "Participant 8 = 1852H/1815H/0H/0/9 = addr_test1qqau5f983jd4p5jxx7uxek4axcuuyqgc3q20d9el33ydg4kr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqvdshe7\n", "Participant 9 = 1852H/1815H/0H/0/10 = addr_test1qry8r8w64h8t6luv4gcvny3snjzmytvrge5euj0ydqchh3wr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq8f955r\n", "Participant 10 = 1852H/1815H/0H/0/11 = addr_test1qzf7zduewu3zjw586mv8r0cxtctwsccsydk7d2hxdcad2s7r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jql02nhc\n", "Participant 11 = 1852H/1815H/0H/0/12 = addr_test1qz5acr3p66e5jzts96jhlgh8nhuurydw5364xs9u2kdwlg7r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqrudtl4\n", "Participant 12 = 1852H/1815H/0H/0/13 = addr_test1qp85hggjkyjzq32m9hk6yfwp8xdz0j6kq7g8j4f2akfl9ckr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq8xh40m\n", "Participant 13 = 1852H/1815H/0H/0/14 = addr_test1qp5uceg0yhxgra7a8emm0d4k8v6qqm4g3tg65ywtqkhcaawr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqyctq4d\n", "Participant 14 = 1852H/1815H/0H/0/15 = addr_test1qqs5whf8xtzdn9myltr7svnug89g5hr48u4zl3lugcrxr67r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqruqfn5\n", "Participant 15 = 1852H/1815H/0H/0/16 = addr_test1qrj49qkfmr72mgmt3lsktde0havnv72yp9qsvsq6365dyp7r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqnpl2rv\n", "Participant 16 = 1852H/1815H/0H/0/17 = addr_test1qqgdvj84rncnlm754fwttn3py73hp85454tzxzll9sk98rkr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqj6jhze\n", "Participant 17 = 1852H/1815H/0H/0/18 = addr_test1qrjk5w2t35r7qpuc0mlxcuazvta0e4d8wsn7mq6wpq4fa2kr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq0zqdga\n", "Participant 18 = 1852H/1815H/0H/0/19 = addr_test1qrnartu48wqykfavssdsgsz6vvgqxgv9s43tgpzrauh6ugwr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqwu7lzs\n", "Participant 19 = 1852H/1815H/0H/0/20 = addr_test1qpftg7deaxswzauukv2hqsegtrr4q680ayd6683k3rg8gkkr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqv7jm9y\n", "Participant 20 = 1852H/1815H/0H/0/21 = addr_test1qzx9gsxhj09ne3vz73jzg25calq9skl3fxwedxdfu6y7gdkr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqvt6lj0\n", "Participant 21 = 1852H/1815H/0H/0/22 = addr_test1qzlv9amdympgu47t6tu4ec5lz6uhu2qnq8ulwk9caasm7f7r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqulv0pl\n", "Participant 22 = 1852H/1815H/0H/0/23 = addr_test1qq6nzgz24yj8u2fy45psnrn4emdwh7scjh29j43z3pv5rckr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq7h6t4e\n", "Participant 23 = 1852H/1815H/0H/0/24 = addr_test1qrhpp4kv5vxpr0kqerx5stkyfqghf8pjltmcucdscuzvg57r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqkeka27\n", "Participant 24 = 1852H/1815H/0H/0/25 = addr_test1qzlweggfq6ara5tytufktkcyjv7j29garuhyufz5ryzxnqwr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq2lh7qe\n", "Participant 25 = 1852H/1815H/0H/0/26 = addr_test1qp0t92r5ep5suj08mpk8mcy7phfuq3607wmksp8z407z6kkr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq2xwugk\n", "Participant 26 = 1852H/1815H/0H/0/27 = addr_test1qzhdl8anw4ssr75uguffuem6227ay9rh3wp855pq6scjc5xr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqe2smw4\n", "Participant 27 = 1852H/1815H/0H/0/28 = addr_test1qzg57krydk30ydzd39ltjvs9wqd3jsf2er5e8asr4faycfxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqmzupaz\n", "Participant 28 = 1852H/1815H/0H/0/29 = addr_test1qpcfw8xjj9vk7889m45mpw4lnmt5ackful200xxp6q3r98wr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqez5l32\n", "Participant 29 = 1852H/1815H/0H/0/30 = addr_test1qzyp0dv2hq77jvhk4kh3y45g63tfx759ufwcsu892ukvegkr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqqun809\n", "Participant 30 = 1852H/1815H/0H/0/31 = addr_test1qp5g75sm5esea8alu07e8c5k63ywns5tq74lvh8ursr48s7r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqjpx5tl\n", "Participant 31 = 1852H/1815H/0H/0/32 = addr_test1qpy8fx7kasu376v3c9pskxckj5stk6ejy2nswnq0requ45kr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqm0r9l6\n", "Participant 32 = 1852H/1815H/0H/0/33 = addr_test1qpazh38gxxnt6yxafz8vf0ryrdc8n8tyc4xlv97c7f8qqfwr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq5zqhdp\n", "Participant 33 = 1852H/1815H/0H/0/34 = addr_test1qpf5pakhjntq8fyxmtc6gv6wf8c5dz8k9dv3nk06dk423awr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq4kdl8u\n", "Participant 34 = 1852H/1815H/0H/0/35 = addr_test1qpfhfug63l0ys2a2vm0wldmxjjlaqgk4u280m4pmk6f8cp7r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqpdfphd\n", "Participant 35 = 1852H/1815H/0H/0/36 = addr_test1qrpjhy8rnc9h50vusd4tsh2nfep9w6n7qutdzs2gpjqfh6xr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqffy4uy\n", "Participant 36 = 1852H/1815H/0H/0/37 = addr_test1qpdsderx7fdh3vx42sx8j4kjcxj3k2d58fgsd5ptya5ulywr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq2ruk85\n", "Participant 37 = 1852H/1815H/0H/0/38 = addr_test1qq4fsl04nuu03njzwh6n89uhgu63x9ypjeg84q4pdzvqttkr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq7ywduq\n", "Participant 38 = 1852H/1815H/0H/0/39 = addr_test1qq5gmdhh65mxm3pje855vwsgfrj90wye43grnq3zzu9ug0wr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jql9ku83\n", "Participant 39 = 1852H/1815H/0H/0/40 = addr_test1qpummduqr4zq3vkxmjxqwvatrfm2wgeefn23p3y5us2rxpkr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqntpetu\n", "Participant 40 = 1852H/1815H/0H/0/41 = addr_test1qzwxx7va22maycmt0wfhzw4q6zy885658swh3yzvxq5860wr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqez9c58\n", "Participant 41 = 1852H/1815H/0H/0/42 = addr_test1qp7sp0w8ljvmau95rsscmg8zegmem4cya6hmyr276hr3c7kr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqpm58rl\n", "Participant 42 = 1852H/1815H/0H/0/43 = addr_test1qzwsqegmud7dcr8prnslmhh97war84dh4z9t7v5xgh8jh2xr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqnq9x0k\n", "Participant 43 = 1852H/1815H/0H/0/44 = addr_test1qz2nmcnwdrxrksk4fvfw9x3myrxndcwhqwkxe5f9lw2azyxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqtxn85r\n", "Participant 44 = 1852H/1815H/0H/0/45 = addr_test1qpek6vrkj00g5vcvzxs74xrzt6clfwc964puu2k32f76hk7r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqv26z8x\n", "Participant 45 = 1852H/1815H/0H/0/46 = addr_test1qq8ses7vgfl9rmj0tjtzvt3r7twpku4cv3c7naxtltlwwqwr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq34fkvd\n", "Participant 46 = 1852H/1815H/0H/0/47 = addr_test1qpggkalsqjuc4t2pj7arzf66he2u7eultqpq3vc7xexunl7r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqw03sf5\n", "Participant 47 = 1852H/1815H/0H/0/48 = addr_test1qzpjuk3pjy47s5pt7danm0d2765e9w8ana9jms38xd0ghfxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqs6uqev\n", "Participant 48 = 1852H/1815H/0H/0/49 = addr_test1qpevx0exxesd4yz5xl0zsuf5rnlg30gkm9l6xtph3ajed2wr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqpd5pd8\n", "Participant 49 = 1852H/1815H/0H/0/50 = addr_test1qqvtgtjgsqcr96wv0xw4cgpjz0qatr7r0g3hfk2tu2xvlhwr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq54hatp\n", "Participant 50 = 1852H/1815H/0H/0/51 = addr_test1qq2hewgkma04wx6udewv6heh3rdvw2agp3gtwa96cz9k4kkr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqa6sxxs\n", "Participant 51 = 1852H/1815H/0H/0/52 = addr_test1qr5zm006w3nd3etsmttwyk298pu65jwwuk4wc8s2zhsv59kr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq9zk0w9\n", "Participant 52 = 1852H/1815H/0H/0/53 = addr_test1qp9p3fh0jh49ypts970970zve2e7lwx3x2wqdgurmumwz5xr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqkrrxts\n", "Participant 53 = 1852H/1815H/0H/0/54 = addr_test1qp4rwv6whephyqm8l4esavujwnfdhenqqnxwdvtdp7zampxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq5q7hz7\n", "Participant 54 = 1852H/1815H/0H/0/55 = addr_test1qze89as8wq67p63gpcj0ycg8rgrs4d5gfykkgq463py404xr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqwy6dex\n", "Participant 55 = 1852H/1815H/0H/0/56 = addr_test1qza96yahn4m8awmzpqwk6d07z6lxfyphqcwvar6e23pj27xr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq6yduup\n", "Participant 56 = 1852H/1815H/0H/0/57 = addr_test1qp37f8ysp9ez3wmfnr5vh3hl4z2670fvs2exln2w0zgs3cxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqv49m2k\n", "Participant 57 = 1852H/1815H/0H/0/58 = addr_test1qrsgyj9wcl9jjqkl0nm8rf28m4gs54grycup9a5krezaqcxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqfjkpp8\n", "Participant 58 = 1852H/1815H/0H/0/59 = addr_test1qzn4wvyj6mvdyaxnj8yhpujxa9m6amp3t5gaevw8etmd9a7r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqw7gjta\n", "Participant 59 = 1852H/1815H/0H/0/60 = addr_test1qz3gznr4hw3jg3t4llp0pezdrwqsjz5ngjx7vsq9pklqwwwr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq3j4820\n", "Participant 60 = 1852H/1815H/0H/0/61 = addr_test1qq588p04pqus2358226a0fjcvcxq22u4zc0edal0fw3m77wr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqp9h4tq\n", "Participant 61 = 1852H/1815H/0H/0/62 = addr_test1qq84w78q9lvfp7jart6nl2qckwzmuww37q2yja8cpqp5607r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq8z60t9\n", "Participant 62 = 1852H/1815H/0H/0/63 = addr_test1qrl98h2rr2ltcrhsnsh5n3z5ywnhnx6gtnp90t5gugqel5xr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqtvxcrm\n", "Participant 63 = 1852H/1815H/0H/0/64 = addr_test1qr0zwzyd6tu9jgzztwcnf3d5s7uupggplxdr8n3h88lzc6xr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqq543s5\n", "Participant 64 = 1852H/1815H/0H/0/65 = addr_test1qrwd8caaqtnjd4xgv3e8j2nhggxh65fq83uwddvky5xvzdkr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqnan585\n", "Participant 65 = 1852H/1815H/0H/0/66 = addr_test1qzeaxy5zazmp0edr007qq86w59t5l4s4pp0w4er2aumx73xr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqn67xqz\n", "Participant 66 = 1852H/1815H/0H/0/67 = addr_test1qq9tsjye0cjs9rjs0xydxjcq5la729ltvzw7t6lqpvj28gxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqjfd45w\n", "Participant 67 = 1852H/1815H/0H/0/68 = addr_test1qq3vmljj6xr6qsng04uq40ltjjank8y2wtqavgkk582fg0xr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq36vy6p\n", "Participant 68 = 1852H/1815H/0H/0/69 = addr_test1qz08fqe3n2pglztx8rhh5xa3slh5xtufy7c5c44u49ar6mxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqgj4hyp\n", "Participant 69 = 1852H/1815H/0H/0/70 = addr_test1qzg75fn3gzefd5x4fj9396d7l898hjsc5de0hfcehy90epxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq7u0w62\n", "Participant 70 = 1852H/1815H/0H/0/71 = addr_test1qr7l63r8dg25mzdrarckv0zh9m855mn6he53ha2jtdjd8swr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqpxcwxy\n", "Participant 71 = 1852H/1815H/0H/0/72 = addr_test1qrvkc8v843ap7svs650v7ykarmy8az6l58j8gyvlyx9ng4wr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqm7cf4s\n", "Participant 72 = 1852H/1815H/0H/0/73 = addr_test1qzu0znj2cn7x3rvt0zaq3cjuz4j39h978s0czw0xajux3jkr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqlw8fme\n", "Participant 73 = 1852H/1815H/0H/0/74 = addr_test1qzh92un69kg06t7rtfu4nfjz4xttc4hunwsz7htpqqpfh9kr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq5egcn6\n", "Participant 74 = 1852H/1815H/0H/0/75 = addr_test1qpym6sp643shhfgdqz2t0krc5vldw5hwlrcj9l6qndn8npkr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqqknlf8\n", "Participant 75 = 1852H/1815H/0H/0/76 = addr_test1qz0sraafpmnzj0ujahuxljjacg36hxeq4lwdxnhfm9uddnxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqwjz4kw\n", "Participant 76 = 1852H/1815H/0H/0/77 = addr_test1qqlvsfdqcl8hxkn065m3m0v24k5kpuc0n26a3h5kdedtly7r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqqz6rz2\n", "Participant 77 = 1852H/1815H/0H/0/78 = addr_test1qrqwjg5jvm7898kem96c3gev2pxytzkcfh5cea0epxhhqtkr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq3r845y\n", "Participant 78 = 1852H/1815H/0H/0/79 = addr_test1qzuqkw9453mm2wqt9x33aduxc2tpjq9czxlq9pxx5tgx8pxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqfkn0j3\n", "Participant 79 = 1852H/1815H/0H/0/80 = addr_test1qruhds8vv5w4nd6nlkjewa7aqu9pzff22m8xj0a4aq8myuxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqxy85qu\n", "Participant 80 = 1852H/1815H/0H/0/81 = addr_test1qrg45zfejwqx9grrzx3aw0nweym5sjyjkgku2cfzs60u7dwr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqv0j247\n", "Participant 81 = 1852H/1815H/0H/0/82 = addr_test1qphc67n5pw0drrr8r7xdjeckk4l4pyusddvvruaqz78296xr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqp2xh7y\n", "Participant 82 = 1852H/1815H/0H/0/83 = addr_test1qp4gr0dhkvv999madce0dhez4x367wkznahkdmtvjv8yz27r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqhl28aq\n", "Participant 83 = 1852H/1815H/0H/0/84 = addr_test1qpqnnaatl3yr3fc3aw66d8026mjfddmpqzdgql99yxgfyvwr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqazk3gh\n", "Participant 84 = 1852H/1815H/0H/0/85 = addr_test1qzqsv0q9js4udx89yrnadnvdd7nuwv750zz2938sg4fa83wr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq2efdee\n", "Participant 85 = 1852H/1815H/0H/0/86 = addr_test1qrcnznq5m5srjasmxrpkdqc7x4mh02vsru0ws8m82v667hxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq8wje78\n", "Participant 86 = 1852H/1815H/0H/0/87 = addr_test1qzamldrpyf6rfneflv2jvh4q03m6gug8amp5hce5ww04l7kr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq8aa8k9\n", "Participant 87 = 1852H/1815H/0H/0/88 = addr_test1qprs6cc7p6xkuyedjrgg3w8g6r82jmvp8hq7zv8lhlshf07r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqkplwl4\n", "Participant 88 = 1852H/1815H/0H/0/89 = addr_test1qprks5kj24y2r2hdvav6rkdwef2m757epr54xnjc2tr398wr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqla8ngy\n", "Participant 89 = 1852H/1815H/0H/0/90 = addr_test1qzz0xx5cz6su3kh6gldu7wzp2mhcffytwv0upg43hdkc0nxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqhw08as\n", "Participant 90 = 1852H/1815H/0H/0/91 = addr_test1qrjwq07mqh4lhwamstx3gy69meqsvn7pylxtmhfadf7ut6kr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqp6e7ud\n", "Participant 91 = 1852H/1815H/0H/0/92 = addr_test1qq6peyeak7ftpdwq7lgahssj4s5sslhcgcfd4wfgxtf52xkr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqwzhdsg\n", "Participant 92 = 1852H/1815H/0H/0/93 = addr_test1qzmwzfavsycupvv35xjchq7w4q6yqxz67r5plrwglqsnve7r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqkktlxy\n", "Participant 93 = 1852H/1815H/0H/0/94 = addr_test1qzd3z04g5wlkgztjchdqkgg9j6hysmgk6xsgxf3m37glfl7r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqnaeh54\n", "Participant 94 = 1852H/1815H/0H/0/95 = addr_test1qqg3rrcvdvz2lrvayeakmt2ahlgv84y29ggjyhya7p80a67r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jquj2zsf\n", "Participant 95 = 1852H/1815H/0H/0/96 = addr_test1qq3k3mxh25zclz5hg95rzskf2k5m2z5qwr2ejcyant43evwr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqqpmnnz\n", "Participant 96 = 1852H/1815H/0H/0/97 = addr_test1qzeexmvhgklvm0sm5a93has8la8xzkalnghulxq07zs84q7r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqadklvz\n", "Participant 97 = 1852H/1815H/0H/0/98 = addr_test1qz0djqvxvfg7xmpzr98jgmlzv870jg80qctaemrzhx7rx6kr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqdqcucz\n", "Participant 98 = 1852H/1815H/0H/0/99 = addr_test1qpjsldudrtytstlgkfmy7z6dymu4yra9uperq2chmu9xaukr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq00l0a0\n", "Participant 99 = 1852H/1815H/0H/0/100 = addr_test1qzs2warxngdak4jdtmg0q7j2n3yc6gtrmhqwvq4gaq602lxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqjxlpdl\n", "Participant 100 = 1852H/1815H/0H/0/101 = addr_test1qqtdfkwpjq7amgjvka4czt7cqvxa4zhe3jmaa8jaqpjxfhkr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq6hmtxv\n", "Participant 101 = 1852H/1815H/0H/0/102 = addr_test1qpuqse785jwx6cyrkr83g6q2a528kqruwzrdcwquum7qz6kr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqnh22p9\n", "Participant 102 = 1852H/1815H/0H/0/103 = addr_test1qqztp3j2j43acu3scu7hwscsgsq2xx90dfdxcf50tl08l47r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqfvns3t\n", "Participant 103 = 1852H/1815H/0H/0/104 = addr_test1qpt72nadqr805aqvfry3u2s38v0hdtjtr74r0023fsr4zvxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqhf8n46\n", "Participant 104 = 1852H/1815H/0H/0/105 = addr_test1qruevfw9n99qk2q6ernw2n65qcagq88yk265mretfcu4g2wr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqj8twmy\n", "Participant 105 = 1852H/1815H/0H/0/106 = addr_test1qrs3rg737vy3gnsu4mp8qxuytzqjhyt8g6jxfr5a06lac0xr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqfsnj0u\n", "Participant 106 = 1852H/1815H/0H/0/107 = addr_test1qq8t9rd2fsky50j0yspjdqptunnwjh275jl03uhx8r7hsw7r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqa29ek7\n", "Participant 107 = 1852H/1815H/0H/0/108 = addr_test1qqsaemxqnw6h3m3vxudk9utms4p7jzmw2g0m53mnqy75chkr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq2sl26u\n", "Participant 108 = 1852H/1815H/0H/0/109 = addr_test1qraukfjgvvfyctgv904l3umuxergjpqxsnwcwpcx5gvww0kr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqajqgjt\n", "Participant 109 = 1852H/1815H/0H/0/110 = addr_test1qzjj5cr97f8pagqad0fgh24qpvmmagnmuzzt228x3rfc5zkr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqx8mm60\n", "Participant 110 = 1852H/1815H/0H/0/111 = addr_test1qrq0p9xvedjjpknruvq9p3staswefl92rll8spzq3lch0hxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqulk76y\n", "Participant 111 = 1852H/1815H/0H/0/112 = addr_test1qzhwep7fau3w2y9cru072aamwakclwkaeqr3gd4ee2x7g2xr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqleafk3\n", "Participant 112 = 1852H/1815H/0H/0/113 = addr_test1qzjlfngyh2q9vvcm3kn2wmysw24yrp46ywyxupec24xnc4kr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqwnmz5x\n", "Participant 113 = 1852H/1815H/0H/0/114 = addr_test1qrqxwcuyg2pzy8kawmk76ry2y3c4taggnks3yjyf8gfamxkr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqdqs9h6\n", "Participant 114 = 1852H/1815H/0H/0/115 = addr_test1qp500fm2wxw7szkmnz9a0e5azcxg7dpzkdp09tqvez2en2xr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jquptalx\n", "Participant 115 = 1852H/1815H/0H/0/116 = addr_test1qzjmk05yd5g3anhaj6t5t4gtzz834x0ahpy25f90ud4nefxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq4y68e5\n", "Participant 116 = 1852H/1815H/0H/0/117 = addr_test1qrve4lfj4x7umy85u8s7xcx6dc9sr60hk3epnsjkd2hxd9xr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqtzmx35\n", "Participant 117 = 1852H/1815H/0H/0/118 = addr_test1qq2espt3r5qvdqd4jfzlwsfdy6xedtcy4u7snvj59wxfajxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqn90dx2\n", "Participant 118 = 1852H/1815H/0H/0/119 = addr_test1qrkwcf35ezgnt9tnzaacgrmjakkwjk8gnjcvd3lke7vk7vxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq6juq9g\n", "Participant 119 = 1852H/1815H/0H/0/120 = addr_test1qrflw25khkgf5suz65na39ytaqpdxycchlk482d8vvmv827r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqdz8yn0\n", "Participant 120 = 1852H/1815H/0H/0/121 = addr_test1qp7jwjqlhe4pc5cg8qv0zxea63l9eaq9dwaqz94cjlp2hzkr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq2w50u6\n", "Participant 121 = 1852H/1815H/0H/0/122 = addr_test1qpfpzhdkxsgf7x0nv49qp7rpexaf0zuf92quzzm0qxfh2nxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq8lhqey\n", "Participant 122 = 1852H/1815H/0H/0/123 = addr_test1qpu5pmlsr8qttzl6f3xt3zr92fu040g5qdq45w0240gdgv7r7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqscjqmc\n", "Participant 123 = 1852H/1815H/0H/0/124 = addr_test1qzpnj7gyz88txgnde68hcxcxvvx5wjvgpafk75ppx737eekr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqu6jyu0\n", "Participant 124 = 1852H/1815H/0H/0/125 = addr_test1qzl8mgpv46z02a5pnvltgg4j6zvwsr640ets9etmmlpsh3kr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqzkfnsp\n", "Participant 125 = 1852H/1815H/0H/0/126 = addr_test1qrh7j6xzdt2e88grpcrslshk9slaq2pr6rh73dn8djun8xxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq6l4eps\n" ] } ], "source": [ "for j in `seq 1 $NUMBER_OF_PARTICIPANTS`\n", "do\n", " PARTICIPANT_SKEY[$j]=../keys/scholar-$j.skey\n", " PARTICIPANT_ADDR[$j]=$(\n", " cardano-wallet key child 1852H/1815H/0H/0/$j < \"$ROOT_PRV\" \\\n", " | cardano-cli key convert-cardano-address-key --shelley-payment-key --signing-key-file /dev/stdin --out-file \"${PARTICIPANT_SKEY[$j]}\"\n", " cardano-cli key verification-key --signing-key-file \"${PARTICIPANT_SKEY[$j]}\" --verification-key-file /dev/stdout \\\n", " | cardano-cli address build --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --payment-verification-key-file /dev/stdin --stake-verification-key-file ../keys/william-shakespeare.stake.vkey \\\n", " )\n", " echo \"Participant $j\" = 1852H/1815H/0H/0/\"$((1 + j))\" = \"${PARTICIPANT_ADDR[$j]}\"\n", "done" ] }, { "cell_type": "markdown", "id": "f05ab3d1-b857-41d3-a594-8564e277ef7d", "metadata": {}, "source": [ "## Contract Parameters" ] }, { "cell_type": "markdown", "id": "14e74097-7901-4a6a-95b2-11c354dde306", "metadata": {}, "source": [ "### Deadlines\n", "\n", "Start the contract at the current time." ] }, { "cell_type": "code", "execution_count": 12, "id": "932d174a-1092-4c5f-9da1-4dd84bd6eb81", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "NOW = 1683600635000 = Mon May 8 08:50:35 PM MDT 2023\n" ] } ], "source": [ "NOW=$((`date -u +%s` * 1000))\n", "echo \"NOW = $NOW\" = \"`date -d @$((NOW / 1000))`\"" ] }, { "cell_type": "code", "execution_count": 13, "id": "d66c6b93-a559-4778-8409-9f628897e809", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "FUNDING_DEADLINE = 1683604238000 = Mon May 8 09:50:38 PM MDT 2023\n" ] } ], "source": [ "FUNDING_DEADLINE=$((`date -u +%s` * SECOND + 1 * HOUR))\n", "echo \"FUNDING_DEADLINE = $FUNDING_DEADLINE\" = \"`date -d @$((FUNDING_DEADLINE / 1000))`\"" ] }, { "cell_type": "code", "execution_count": 14, "id": "b0ce5169-1439-443d-8d4f-e86dea5f0ae5", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "SELECTION_DEADLINE = 1683607840000 = Mon May 8 10:50:40 PM MDT 2023\n" ] } ], "source": [ "SELECTION_DEADLINE=$((`date -u +%s` * SECOND + 2 * HOUR))\n", "echo \"SELECTION_DEADLINE = $SELECTION_DEADLINE\" = \"`date -d @$((SELECTION_DEADLINE / 1000))`\"" ] }, { "cell_type": "code", "execution_count": 15, "id": "ff4ff9cd-e6bc-45fa-8990-4770a1ca4f60", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "AWARD_DEADLINE = 1683611444000 = Mon May 8 11:50:44 PM MDT 2023\n" ] } ], "source": [ "AWARD_DEADLINE=$((`date -u +%s` * SECOND + 3 * HOUR))\n", "echo \"AWARD_DEADLINE = $AWARD_DEADLINE\" = \"`date -d @$((AWARD_DEADLINE / 1000))`\"" ] }, { "cell_type": "markdown", "id": "754729f9-9889-42fc-b259-14c9ff3cadbe", "metadata": {}, "source": [ "### Award" ] }, { "cell_type": "code", "execution_count": 16, "id": "107e363c-312a-4b81-86cd-cb654f6e9849", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "AWARD_AMOUNT = 100000000 lovelace\n" ] } ], "source": [ "AWARD_AMOUNT=$((100 * ADA))\n", "echo \"AWARD_AMOUNT = $AWARD_AMOUNT lovelace\"" ] }, { "cell_type": "markdown", "id": "488f7010-f6d3-4d70-a6c2-a25cee2c19ec", "metadata": {}, "source": [ "## Contract\n", "\n", "Now run the Haskell program to generate the contract. We'll use a fivefold split to hierarchically search for the winner, so that the Plutus execution budget is not exceeded." ] }, { "cell_type": "code", "execution_count": 17, "id": "b55e2e6a-f8e3-400d-81a9-2ef0cd05324f", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "SIZE = 5\n" ] } ], "source": [ "SIZE=5\n", "echo \"SIZE = $SIZE\"" ] }, { "cell_type": "code", "execution_count": 18, "id": "b3d09d40-afdc-4671-b583-fa755713940b", "metadata": {}, "outputs": [], "source": [ "runhaskell contract.hs \\\n", " \"$SIZE\" \\\n", " \"$SPONSOR_ADDR\" \\\n", " \"$ORACLE_ADDR\" \\\n", " \"$AWARD_AMOUNT\" \\\n", " \"$FUNDING_DEADLINE\" \\\n", " \"$SELECTION_DEADLINE\" \\\n", " \"$AWARD_DEADLINE\" \\\n", " ${PARTICIPANT_ADDR[@]}" ] }, { "cell_type": "markdown", "id": "f6d3544f-2087-4cde-8750-ec37e8d53c72", "metadata": {}, "source": [ "## Initial State\n", "\n", "We put 2 ada in the initial contract when it is created, in order to satisfy the ledger's minimum-UTxO rule." ] }, { "cell_type": "code", "execution_count": 19, "id": "0caf44eb-40f7-43f7-af07-16197e30ca11", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\"accounts\":[[[{\"address\":\"addr_test1vrtntkszteptml4e9ce9l3fsmgavwv4ywunvdnhxv6nw5ksq6737a\"},{\"currency_symbol\":\"\",\"token_name\":\"\"}],2000000]],\"boundValues\":[],\"choices\":[],\"minTime\":1}\n" ] } ], "source": [ "MIN_LOVELACE=$((2 * ADA))\n", "\n", "yaml2json << EOI > state.json\n", "accounts:\n", "- - - address: $SPONSOR_ADDR\n", " - currency_symbol: ''\n", " token_name: ''\n", " - $MIN_LOVELACE\n", "boundValues: []\n", "choices: []\n", "minTime: 1\n", "EOI\n", "\n", "cat state.json" ] }, { "cell_type": "markdown", "id": "d18d022a-1c4e-4c19-a0ba-ea28cde001be", "metadata": {}, "source": [ "## Creation transaction\n", "\n", "Merkleize the contract when we initialize it." ] }, { "cell_type": "code", "execution_count": 20, "id": "b13363fc-58a2-4e53-886d-36f24aacf1cf", "metadata": { "tags": [] }, "outputs": [], "source": [ "marlowe-cli run initialize \\\n", " --contract-file contract.json \\\n", " --state-file state.json \\\n", " --out-file marlowe-1.json \\\n", " --merkleize \\\n", " --permanently-without-staking" ] }, { "cell_type": "markdown", "id": "3fd25d53-893d-4528-9f6d-03f621a96662", "metadata": {}, "source": [ "The sponsor submits the creation transaction." ] }, { "cell_type": "code", "execution_count": 21, "id": "e4a1942b-9e93-4d04-9ef8-b26ea7443b69", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Fee: Lovelace 196081\n", "Size: 579 / 16384 = 3%\n", "Execution units:\n", " Memory: 0 / 14000000 = 0%\n", " Steps: 0 / 10000000000 = 0%\n", "TX[1] = c5f1307a4f2d12b419b1ed381a8ccefcf4c2a019c9e2f663da24cb3a91258206\n", "https://preprod.cardanoscan.io/transaction/c5f1307a4f2d12b419b1ed381a8ccefcf4c2a019c9e2f663da24cb3a91258206?tab=utxo\n" ] } ], "source": [ "TX[1]=$(\n", "/extra/iohk/bin/marlowe-cli run auto-execute \\\n", " --marlowe-out-file marlowe-1.json \\\n", " --change-address \"$SPONSOR_ADDR\" \\\n", " --required-signer \"$SPONSOR_SKEY\" \\\n", " --out-file /dev/null \\\n", " --submit 600 \\\n", " --print-stats \\\n", "| sed -e 's/^TxId \"\\(.*\\)\"$/\\1/' \\\n", ")\n", "echo \"TX[1] = ${TX[1]}\"\n", "echo 'https://preprod.cardanoscan.io/transaction/'\"${TX[1]}\"'?tab=utxo'" ] }, { "cell_type": "markdown", "id": "82083aac-fe83-42c7-8b8b-35fc04046d6c", "metadata": {}, "source": [ "## Transaction to deposit the funds.\n", "\n", "The sponsor prepares the transaction to deposit the funds." ] }, { "cell_type": "code", "execution_count": 22, "id": "e77cb6a1-8b06-4eb0-8475-d8b356d063dd", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "TransactionInput {txInterval = (POSIXTime {getPOSIXTime = 1683600666000},POSIXTime {getPOSIXTime = 1683601026999}), txInputs = [NormalInput (IDeposit \"\\\"addr_test1vrtntkszteptml4e9ce9l3fsmgavwv4ywunvdnhxv6nw5ksq6737a\\\"\" \"\\\"addr_test1vrtntkszteptml4e9ce9l3fsmgavwv4ywunvdnhxv6nw5ksq6737a\\\"\" (Token \"\" \"\") 100000000)]}\n" ] } ], "source": [ "marlowe-cli run prepare \\\n", " --deposit-account \"$SPONSOR_ADDR\" \\\n", " --deposit-party \"$SPONSOR_ADDR\" \\\n", " --deposit-amount \"$AWARD_AMOUNT\" \\\n", " --invalid-before \"$((($(date -u +%s) - 1 * 60) * 1000))\" \\\n", " --invalid-hereafter \"$((($(date -u +%s) + 5 * 60) * 1000))\" \\\n", " --marlowe-file marlowe-1.json \\\n", " --out-file marlowe-2.json \\\n", " 2> /dev/null" ] }, { "cell_type": "markdown", "id": "e5229357-dfae-4d79-8221-d2f13b1ff8e7", "metadata": {}, "source": [ "Submit the transaction and await its confirmation." ] }, { "cell_type": "code", "execution_count": 23, "id": "353e21b3-d2bd-40cf-a975-8a8c82454094", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Fee: Lovelace 625267\n", "Size: 1250 / 16384 = 7%\n", "Execution units:\n", " Memory: 5168716 / 14000000 = 36%\n", " Steps: 1405524214 / 10000000000 = 14%\n", "TX[2] = 3c832480473eedcbb911855be6e9f434d31ccb91daa087ee162c6a5c9d8b28c3\n", "https://preprod.cardanoscan.io/transaction/3c832480473eedcbb911855be6e9f434d31ccb91daa087ee162c6a5c9d8b28c3?tab=utxo\n" ] } ], "source": [ "TX[2]=$(\n", "/extra/iohk/bin/marlowe-cli run auto-execute \\\n", " --tx-in-marlowe \"${TX[1]}#1\" \\\n", " --marlowe-in-file marlowe-1.json \\\n", " --marlowe-out-file marlowe-2.json \\\n", " --change-address \"$SPONSOR_ADDR\" \\\n", " --required-signer \"$SPONSOR_SKEY\" \\\n", " --out-file /dev/null \\\n", " --submit 600 \\\n", " --print-stats \\\n", "| sed -e 's/^TxId \"\\(.*\\)\"$/\\1/' \\\n", ")\n", "echo \"TX[2] = ${TX[2]}\"\n", "echo 'https://preprod.cardanoscan.io/transaction/'\"${TX[2]}\"'?tab=utxo'" ] }, { "cell_type": "markdown", "id": "732f8168-3c65-4c05-b638-23b03d4e56c8", "metadata": {}, "source": [ "## Transaction to randomly select a winner.\n", "\n", "The oracle fetches a truly random integer from [RANDOM.ORG](https://random.org/)." ] }, { "cell_type": "code", "execution_count": 25, "id": "0205041c-0690-4b99-8873-8b8a1a1e4bef", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "SELECTION = 85\n" ] } ], "source": [ "SELECTION=$(curl -sS \"https://www.random.org/integers/?num=1&min=1&max=\"$NUMBER_OF_PARTICIPANTS\"&col=1&base=10&format=plain&rnd=new\")\n", "echo \"SELECTION = $SELECTION\"" ] }, { "cell_type": "markdown", "id": "9eb98f1c-48f4-4f01-ade0-3ffd101e579d", "metadata": {}, "source": [ "The oracle prepares the transaction with this random choice." ] }, { "cell_type": "code", "execution_count": 26, "id": "357a98b9-f068-42a5-a5b4-09e4b2d38e1c", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "TransactionInput {txInterval = (POSIXTime {getPOSIXTime = 1683600721000},POSIXTime {getPOSIXTime = 1683601081999}), txInputs = [NormalInput (IChoice (ChoiceId \"Random\" \"\\\"addr_test1vqhqudxtwqcpjqesns79hqgqq2q0xx5q0hnzz5es9492yaqpxltpy\\\"\") 85)]}\n" ] } ], "source": [ "marlowe-cli run prepare \\\n", " --choice-name Random \\\n", " --choice-party \"$ORACLE_ADDR\" \\\n", " --choice-number \"$SELECTION\" \\\n", " --invalid-before \"$((($(date -u +%s) - 1 * 60) * 1000))\" \\\n", " --invalid-hereafter \"$((($(date -u +%s) + 5 * 60) * 1000))\" \\\n", " --marlowe-file marlowe-2.json \\\n", " --out-file marlowe-3.json \\\n", " 2> /dev/null" ] }, { "cell_type": "markdown", "id": "c983458d-eca4-4046-be53-ced955b0df7c", "metadata": {}, "source": [ "The oracle submits the transaction and awaits confirmation." ] }, { "cell_type": "code", "execution_count": 27, "id": "768995c9-e315-4edf-aa62-79f00f3cd179", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Fee: Lovelace 833385\n", "Size: 2172 / 16384 = 13%\n", "Execution units:\n", " Memory: 7171896 / 14000000 = 51%\n", " Steps: 2123841881 / 10000000000 = 21%\n", "TX[3] = 4d0f2f250203ca39074859ced409f1e4d8b6a2ef81f780c1f21b6920a4d156e4\n", "https://preprod.cardanoscan.io/transaction/4d0f2f250203ca39074859ced409f1e4d8b6a2ef81f780c1f21b6920a4d156e4?tab=utxo\n" ] } ], "source": [ "TX[3]=$(\n", "/extra/iohk/bin/marlowe-cli run auto-execute \\\n", " --tx-in-marlowe \"${TX[2]}#1\" \\\n", " --marlowe-in-file marlowe-2.json \\\n", " --marlowe-out-file marlowe-3.json \\\n", " --change-address \"$ORACLE_ADDR\" \\\n", " --required-signer \"$ORACLE_SKEY\" \\\n", " --out-file /dev/null \\\n", " --submit 600 \\\n", " --print-stats \\\n", "| sed -e 's/^TxId \"\\(.*\\)\"$/\\1/' \\\n", ")\n", "echo \"TX[3] = ${TX[3]}\"\n", "echo 'https://preprod.cardanoscan.io/transaction/'\"${TX[3]}\"'?tab=utxo'" ] }, { "cell_type": "markdown", "id": "f0dc2e75-8654-429e-a969-81e6977f4bc6", "metadata": {}, "source": [ "## Transactions to award the winner\n", "\n", "Because the search for the winner has been hierarchically split, we'll need several `INotify` actions to walk the hierarchy to the winner. The number of notifications is the logarithm of the number of participants, rounded upwards to the nearest whole number." ] }, { "cell_type": "code", "execution_count": 28, "id": "25769ce1-8a67-4c9b-8aec-7d4b46fe2917", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "DEPTH = 3\n" ] } ], "source": [ "DEPTH=$(printf \"%.0f\" `echo l\"($NUMBER_OF_PARTICIPANTS)\" / \"l($SIZE)\" | ~/.nix-profile/bin/bc -l`)\n", "echo \"DEPTH = $DEPTH\"" ] }, { "cell_type": "markdown", "id": "cf2d0978-eafa-4264-833a-c37e7f07484a", "metadata": {}, "source": [ "Anyone can prepare and submit the notifications, but for convenience the sponsor does so here." ] }, { "cell_type": "code", "execution_count": 29, "id": "9033ab54-e32b-446e-a8bf-08d59fc1dd8c", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "----- Notify 1 -----\n", "\n", "TransactionInput {txInterval = (POSIXTime {getPOSIXTime = 1683600792000},POSIXTime {getPOSIXTime = 1683601152999}), txInputs = [NormalInput INotify]}\n", "\n", "Fee: Lovelace 913392\n", "Size: 2654 / 16384 = 16%\n", "Execution units:\n", " Memory: 7896032 / 14000000 = 56%\n", " Steps: 2362301577 / 10000000000 = 23%\n", "TX[4] = 39981f87fabe70091285af176b8a97b234cc16c6ffde4b948fa39282070af861\n", "https://preprod.cardanoscan.io/transaction/39981f87fabe70091285af176b8a97b234cc16c6ffde4b948fa39282070af861?tab=utxo\n", "\n", "----- Notify 2 -----\n", "\n", "TransactionInput {txInterval = (POSIXTime {getPOSIXTime = 1683600803000},POSIXTime {getPOSIXTime = 1683601163999}), txInputs = [NormalInput INotify]}\n", "\n", "Fee: Lovelace 896647\n", "Size: 2654 / 16384 = 16%\n", "Execution units:\n", " Memory: 7679900 / 14000000 = 54%\n", " Steps: 2303018611 / 10000000000 = 23%\n", "TX[5] = 39ee58ea4d271c29f7c529e0730c8b22acd69fba58f2bd819b1c3ae310b1e4fc\n", "https://preprod.cardanoscan.io/transaction/39ee58ea4d271c29f7c529e0730c8b22acd69fba58f2bd819b1c3ae310b1e4fc?tab=utxo\n", "\n", "----- Notify 3 -----\n", "\n", "TransactionInput {txInterval = (POSIXTime {getPOSIXTime = 1683600839000},POSIXTime {getPOSIXTime = 1683601199999}), txInputs = [NormalInput INotify]}\n", "Payment 1\n", " Acccount: \"\\\"addr_test1vrtntkszteptml4e9ce9l3fsmgavwv4ywunvdnhxv6nw5ksq6737a\\\"\"\n", " Payee: Party \"\\\"addr_test1qrcnznq5m5srjasmxrpkdqc7x4mh02vsru0ws8m82v667hxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq8wje78\\\"\"\n", " Ada: Lovelace {getLovelace = 100000000}\n", "Payment 2\n", " Acccount: \"\\\"addr_test1vrtntkszteptml4e9ce9l3fsmgavwv4ywunvdnhxv6nw5ksq6737a\\\"\"\n", " Payee: Party \"\\\"addr_test1vrtntkszteptml4e9ce9l3fsmgavwv4ywunvdnhxv6nw5ksq6737a\\\"\"\n", " Ada: Lovelace {getLovelace = 2000000}\n", "\n", "Fee: Lovelace 712216\n", "Size: 1490 / 16384 = 9%\n", "Execution units:\n", " Memory: 6153780 / 14000000 = 43%\n", " Steps: 1676694305 / 10000000000 = 16%\n", "TX[6] = 296d39e690bf0e8d6bf65075b8fe4ce0efd7b1acc2471edd1c32b3b906d5f824\n", "https://preprod.cardanoscan.io/transaction/296d39e690bf0e8d6bf65075b8fe4ce0efd7b1acc2471edd1c32b3b906d5f824?tab=utxo\n" ] } ], "source": [ "for i in `seq 1 $DEPTH`\n", "do\n", "\n", "n=$((i+3))\n", "\n", "echo\n", "echo \"----- Notify $i -----\"\n", "echo\n", "\n", "marlowe-cli run prepare \\\n", " --notify \\\n", " --invalid-before \"$((($(date -u +%s) - 1 * 60) * 1000))\" \\\n", " --invalid-hereafter \"$((($(date -u +%s) + 5 * 60) * 1000))\" \\\n", " --marlowe-file marlowe-$((n-1)).json \\\n", " --out-file marlowe-$n.json \\\n", " 2> /dev/null\n", "\n", "TX[$n]=$(\n", "/extra/iohk/bin/marlowe-cli run auto-execute \\\n", " --tx-in-marlowe \"${TX[$((n-1))]}#1\" \\\n", " --marlowe-in-file marlowe-$((n-1)).json \\\n", " --marlowe-out-file marlowe-$n.json \\\n", " --change-address \"$SPONSOR_ADDR\" \\\n", " --required-signer \"$SPONSOR_SKEY\" \\\n", " --out-file /dev/null \\\n", " --submit 600 \\\n", " --print-stats \\\n", "| sed -e 's/^TxId \"\\(.*\\)\"$/\\1/' \\\n", ")\n", "echo \"TX[$n] = ${TX[$n]}\"\n", "echo 'https://preprod.cardanoscan.io/transaction/'\"${TX[$n]}\"'?tab=utxo' \n", "\n", "done" ] }, { "cell_type": "markdown", "id": "7b53db54-67a6-4a08-afb7-33d898058b98", "metadata": {}, "source": [ "The last notification triggered the payment to the winner and a reimbursement of the sponsor's minimum-UTxO value from creating the contract." ] }, { "cell_type": "code", "execution_count": 30, "id": "73eb7860-7f15-48ef-a4fb-f0edba1b34c7", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Winner = addr_test1qrcnznq5m5srjasmxrpkdqc7x4mh02vsru0ws8m82v667hxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jq8wje78\n" ] } ], "source": [ "echo \"Winner = ${PARTICIPANT_ADDR[$SELECTION]}\"" ] }, { "cell_type": "markdown", "id": "27dd3e63-7bb2-4e11-8449-15ff7c989dc8", "metadata": {}, "source": [ "Here is the UTxO with the winnings." ] }, { "cell_type": "code", "execution_count": 31, "id": "3df83773-2c07-45d5-8a3a-b74cefa4a73f", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " TxHash TxIx Amount\n", "--------------------------------------------------------------------------------------\n", "296d39e690bf0e8d6bf65075b8fe4ce0efd7b1acc2471edd1c32b3b906d5f824 2 100000000 lovelace + TxOutDatumNone\n" ] } ], "source": [ "cardano-cli query utxo --testnet-magic \"$CARDANO_TESTNET_MAGIC\" --address \"${PARTICIPANT_ADDR[$SELECTION]}\"" ] } ], "metadata": { "kernelspec": { "display_name": "Bash with Marlowe Tools", "language": "bash", "name": "bash-minimal" }, "language_info": { "codemirror_mode": "shell", "file_extension": ".sh", "mimetype": "text/x-sh", "name": "bash" } }, "nbformat": 4, "nbformat_minor": 5 }