From de922395d1393cea2c00cb83c9fe68c4b84f525d Mon Sep 17 00:00:00 2001 From: Konstantinos Lambrou-Latreille Date: Mon, 17 Jan 2022 15:04:54 -0500 Subject: [PATCH] SCP-3196: Added a new Game contract (simplified version of GameStateMachine) * Parameterized the GameStateMachine contract * Added Game contract which is compatible with remote wallets by using `yieldUnbalancedTx`. * Added the contract in the plutus-pab-executables builtin contract --- doc/plutus-doc.cabal | 1 + doc/plutus/tutorials/GameModel.hs | 73 +- doc/plutus/tutorials/contract-testing.rst | 25 +- .../.plan.nix/plutus-doc.nix | 1 + .../.plan.nix/plutus-use-cases.nix | 3 + .../.plan.nix/plutus-doc.nix | 1 + .../.plan.nix/plutus-use-cases.nix | 3 + .../.plan.nix/plutus-doc.nix | 1 + .../.plan.nix/plutus-use-cases.nix | 3 + .../examples/ContractExample.hs | 6 + plutus-use-cases/plutus-use-cases.cabal | 3 + plutus-use-cases/scripts/Main.hs | 6 +- plutus-use-cases/src/Plutus/Contracts/Game.hs | 192 + .../src/Plutus/Contracts/GameStateMachine.hs | 118 +- plutus-use-cases/test/Spec.hs | 2 + plutus-use-cases/test/Spec/Game.hs | 98 + .../test/Spec/GameStateMachine.hs | 104 +- plutus-use-cases/test/Spec/game.pir | 317 ++ .../test/Spec/gameStateMachine.pir | 4936 +++++++++-------- plutus-use-cases/test/Spec/renderGuess.txt | 114 +- 20 files changed, 3393 insertions(+), 2614 deletions(-) create mode 100644 plutus-use-cases/src/Plutus/Contracts/Game.hs create mode 100644 plutus-use-cases/test/Spec/Game.hs create mode 100644 plutus-use-cases/test/Spec/game.pir diff --git a/doc/plutus-doc.cabal b/doc/plutus-doc.cabal index f92122ff45..1ef2bc68a9 100644 --- a/doc/plutus-doc.cabal +++ b/doc/plutus-doc.cabal @@ -61,6 +61,7 @@ executable doc-doctests template-haskell >=2.13.0.0, bytestring -any, cardano-api -any, + data-default -any, flat -any, plutus-core -any, plutus-chain-index-core -any, diff --git a/doc/plutus/tutorials/GameModel.hs b/doc/plutus/tutorials/GameModel.hs index c1066937a9..1d984a7861 100644 --- a/doc/plutus/tutorials/GameModel.hs +++ b/doc/plutus/tutorials/GameModel.hs @@ -57,6 +57,18 @@ import Plutus.Trace.Emulator as Trace import Plutus.Contract.Secrets -- END import Contract.Security +-- START import TimeSlot +import Ledger.TimeSlot qualified as TimeSlot +-- END import TimeSlot + +-- START import Data.Default +import Data.Default (Default (def)) +-- END import Data.Default + +-- START gameParam +gameParam :: G.GameParam +gameParam = G.GameParam (mockWalletPaymentPubKeyHash w1) (TimeSlot.scSlotZeroTime def) +-- END gameParam -- * QuickCheck model @@ -103,18 +115,21 @@ instance ContractModel GameModel where perform handle s cmd = case cmd of Lock w new val -> do callEndpoint @"lock" (handle $ WalletKey w) - LockArgs{ lockArgsSecret = secretArg new - , lockArgsValue = Ada.lovelaceValueOf val } + LockArgs { lockArgsGameParam = gameParam + , lockArgsSecret = secretArg new + , lockArgsValue = Ada.lovelaceValueOf val + } delay 2 Guess w old new val -> do callEndpoint @"guess" (handle $ WalletKey w) - GuessArgs{ guessArgsOldSecret = old + GuessArgs{ guessArgsGameParam = gameParam + , guessArgsOldSecret = old , guessArgsNewSecret = secretArg new , guessArgsValueTakenOut = Ada.lovelaceValueOf val } delay 1 GiveToken w' -> do let w = fromJust (s ^. contractState . hasToken) - payToWallet w w' gameTokenVal + payToWallet w w' guessTokenVal delay 1 -- END perform @@ -125,8 +140,8 @@ instance ContractModel GameModel where hasToken $= Just w currentSecret $= secret gameValue $= val - mint gameTokenVal - deposit w gameTokenVal + mint guessTokenVal + deposit w guessTokenVal withdraw w $ Ada.lovelaceValueOf val wait 2 @@ -144,7 +159,7 @@ instance ContractModel GameModel where nextState (GiveToken w) = do w0 <- fromJust <$> viewContractState hasToken - transfer w0 w gameTokenVal + transfer w0 w guessTokenVal hasToken $= Just w wait 1 @@ -163,9 +178,9 @@ instance ContractModel GameModel where -- START precondition precondition s cmd = case cmd of - Lock _ _ v -> tok == Nothing + Lock _ _ v -> isNothing tok Guess w _ _ v -> tok == Just w && v <= val - GiveToken w -> tok /= Nothing + GiveToken w -> isJust tok where tok = s ^. contractState . hasToken val = s ^. contractState . gameValue @@ -296,12 +311,12 @@ wallets :: [Wallet] wallets = [w1, w2, w3] -- END wallets --- START gameTokenVal -gameTokenVal :: Value -gameTokenVal = - let sym = Scripts.forwardingMintingPolicyHash G.typedValidator +-- START guessTokenVal +guessTokenVal :: Value +guessTokenVal = + let sym = Scripts.forwardingMintingPolicyHash $ G.typedValidator gameParam in G.token sym "guess" --- END gameTokenVal +-- END guessTokenVal -- START testLock v1 testLock :: Property @@ -353,8 +368,8 @@ v1_model = () hasToken $= Just w currentSecret $= secret gameValue $= val - mint gameTokenVal - deposit w gameTokenVal + mint guessTokenVal + deposit w guessTokenVal withdraw w $ Ada.lovelaceValueOf val -- END nextState Lock v1 -- START nextState Guess v1 @@ -370,13 +385,13 @@ v1_model = () -- START nextState GiveToken v1 nextState (GiveToken w) = do w0 <- fromJust <$> viewContractState hasToken - transfer w0 w gameTokenVal + transfer w0 w guessTokenVal hasToken $= Just w -- END nextState GiveToken v1 precondition :: ModelState GameModel -> Action GameModel -> Bool -- START precondition v1 - precondition s (GiveToken _) = tok /= Nothing + precondition s (GiveToken _) = isJust tok where tok = s ^. contractState . hasToken precondition s _ = True @@ -387,16 +402,18 @@ v1_model = () perform handle s cmd = case cmd of Lock w new val -> do callEndpoint @"lock" (handle $ WalletKey w) - LockArgs{ lockArgsSecret = secretArg new + LockArgs{ lockArgsGameParam = gameParam + , lockArgsSecret = secretArg new , lockArgsValue = Ada.lovelaceValueOf val} Guess w old new val -> do callEndpoint @"guess" (handle $ WalletKey w) - GuessArgs{ guessArgsOldSecret = old + GuessArgs{ guessArgsGameParam = gameParam + , guessArgsOldSecret = old , guessArgsNewSecret = secretArg new , guessArgsValueTakenOut = Ada.lovelaceValueOf val} GiveToken w' -> do let w = fromJust (s ^. contractState . hasToken) - payToWallet w w' gameTokenVal + payToWallet w w' guessTokenVal return () -- END perform v1 @@ -409,8 +426,8 @@ v2_model = () hasToken $= Just w currentSecret $= secret gameValue $= val - mint gameTokenVal - deposit w gameTokenVal + mint guessTokenVal + deposit w guessTokenVal withdraw w $ Ada.lovelaceValueOf val wait 2 -- END nextState Lock v2 @@ -425,9 +442,9 @@ v2_model = () precondition :: ModelState GameModel -> Action GameModel -> Bool -- START precondition v2 precondition s cmd = case cmd of - Lock _ _ _ -> tok == Nothing - Guess _ _ _ _ -> True - GiveToken _ -> tok /= Nothing + Lock {} -> isNothing tok + Guess {} -> True + GiveToken _ -> isJust tok where tok = s ^. contractState . hasToken -- END precondition v2 @@ -450,9 +467,9 @@ v3_model = () precondition :: ModelState GameModel -> Action GameModel -> Bool -- START precondition v3 precondition s cmd = case cmd of - Lock _ _ _ -> tok == Nothing + Lock {} -> isNothing tok Guess w _ _ _ -> tok == Just w - GiveToken _ -> tok /= Nothing + GiveToken _ -> isJust tok where tok = s ^. contractState . hasToken -- END precondition v3 diff --git a/doc/plutus/tutorials/contract-testing.rst b/doc/plutus/tutorials/contract-testing.rst index cc4be16832..278e1698cd 100644 --- a/doc/plutus/tutorials/contract-testing.rst +++ b/doc/plutus/tutorials/contract-testing.rst @@ -92,23 +92,33 @@ we can define it as follows, applying a minting policy defined in the code under .. literalinclude:: GameModel.hs :start-after: START import Game :end-before: END import Game +.. literalinclude:: GameModel.hs + :start-after: START import TimeSlot + :end-before: END import TimeSlot +.. literalinclude:: GameModel.hs + :start-after: START import Data.Default + :end-before: END import Data.Default + +.. literalinclude:: GameModel.hs + :start-after: START gameParam + :end-before: END gameParam .. literalinclude:: GameModel.hs - :start-after: START gameTokenVal - :end-before: END gameTokenVal + :start-after: START guessTokenVal + :end-before: END guessTokenVal The value of the :term:`token` is (with long hash values abbreviated): .. code-block:: text - > gameTokenVal + > guessTokenVal Value (Map [(f687...,Map [(guess,1)])]) We can even construct a ``Value`` containing an Ada and a game :term:`token`: .. code-block:: text - > Ada.lovelaceValueOf 1 <> gameTokenVal + > Ada.lovelaceValueOf 1 <> guessTokenVal Value (Map [(,Map [(,1)]),(f687...,Map [(guess,1)])]) If you inspect the output closely, you will see that a ``Value`` @@ -511,6 +521,9 @@ contract end-points, using the API defined in the code under test, and transfer the game :term:`token` from one wallet to another as specified by ``GiveToken`` actions. +.. literalinclude:: GameModel.hs + :start-after: START gameParam + :end-before: END gameParam .. literalinclude:: GameModel.hs :start-after: START perform v1 :end-before: END perform v1 @@ -680,6 +693,10 @@ We can cause the emulator to delay a number of slots like this: We add a call to ``delay`` in each branch of :hsobj:`Plutus.Contract.Test.ContractModel.perform`: +.. literalinclude:: GameModel.hs + :start-after: START gameParam + :end-before: END gameParam + .. literalinclude:: GameModel.hs :start-after: START perform :end-before: END perform diff --git a/nix/pkgs/haskell/materialized-darwin/.plan.nix/plutus-doc.nix b/nix/pkgs/haskell/materialized-darwin/.plan.nix/plutus-doc.nix index 7cd2f584e0..2ebce6357d 100644 --- a/nix/pkgs/haskell/materialized-darwin/.plan.nix/plutus-doc.nix +++ b/nix/pkgs/haskell/materialized-darwin/.plan.nix/plutus-doc.nix @@ -38,6 +38,7 @@ (hsPkgs."template-haskell" or (errorHandler.buildDepError "template-haskell")) (hsPkgs."bytestring" or (errorHandler.buildDepError "bytestring")) (hsPkgs."cardano-api" or (errorHandler.buildDepError "cardano-api")) + (hsPkgs."data-default" or (errorHandler.buildDepError "data-default")) (hsPkgs."flat" or (errorHandler.buildDepError "flat")) (hsPkgs."plutus-core" or (errorHandler.buildDepError "plutus-core")) (hsPkgs."plutus-chain-index-core" or (errorHandler.buildDepError "plutus-chain-index-core")) diff --git a/nix/pkgs/haskell/materialized-darwin/.plan.nix/plutus-use-cases.nix b/nix/pkgs/haskell/materialized-darwin/.plan.nix/plutus-use-cases.nix index b3d57dc83a..0e6768b9ca 100644 --- a/nix/pkgs/haskell/materialized-darwin/.plan.nix/plutus-use-cases.nix +++ b/nix/pkgs/haskell/materialized-darwin/.plan.nix/plutus-use-cases.nix @@ -67,6 +67,7 @@ "Plutus/Contracts/Escrow" "Plutus/Contracts/SimpleEscrow" "Plutus/Contracts/Future" + "Plutus/Contracts/Game" "Plutus/Contracts/GameStateMachine" "Plutus/Contracts/Governance" "Plutus/Contracts/MultiSig" @@ -143,6 +144,7 @@ "Spec/Escrow" "Spec/SimpleEscrow" "Spec/Future" + "Spec/Game" "Spec/GameStateMachine" "Spec/Governance" "Spec/MultiSig" @@ -199,6 +201,7 @@ "Spec/Escrow" "Spec/SimpleEscrow" "Spec/Future" + "Spec/Game" "Spec/GameStateMachine" "Spec/Governance" "Spec/MultiSig" diff --git a/nix/pkgs/haskell/materialized-linux/.plan.nix/plutus-doc.nix b/nix/pkgs/haskell/materialized-linux/.plan.nix/plutus-doc.nix index 7cd2f584e0..2ebce6357d 100644 --- a/nix/pkgs/haskell/materialized-linux/.plan.nix/plutus-doc.nix +++ b/nix/pkgs/haskell/materialized-linux/.plan.nix/plutus-doc.nix @@ -38,6 +38,7 @@ (hsPkgs."template-haskell" or (errorHandler.buildDepError "template-haskell")) (hsPkgs."bytestring" or (errorHandler.buildDepError "bytestring")) (hsPkgs."cardano-api" or (errorHandler.buildDepError "cardano-api")) + (hsPkgs."data-default" or (errorHandler.buildDepError "data-default")) (hsPkgs."flat" or (errorHandler.buildDepError "flat")) (hsPkgs."plutus-core" or (errorHandler.buildDepError "plutus-core")) (hsPkgs."plutus-chain-index-core" or (errorHandler.buildDepError "plutus-chain-index-core")) diff --git a/nix/pkgs/haskell/materialized-linux/.plan.nix/plutus-use-cases.nix b/nix/pkgs/haskell/materialized-linux/.plan.nix/plutus-use-cases.nix index b3d57dc83a..0e6768b9ca 100644 --- a/nix/pkgs/haskell/materialized-linux/.plan.nix/plutus-use-cases.nix +++ b/nix/pkgs/haskell/materialized-linux/.plan.nix/plutus-use-cases.nix @@ -67,6 +67,7 @@ "Plutus/Contracts/Escrow" "Plutus/Contracts/SimpleEscrow" "Plutus/Contracts/Future" + "Plutus/Contracts/Game" "Plutus/Contracts/GameStateMachine" "Plutus/Contracts/Governance" "Plutus/Contracts/MultiSig" @@ -143,6 +144,7 @@ "Spec/Escrow" "Spec/SimpleEscrow" "Spec/Future" + "Spec/Game" "Spec/GameStateMachine" "Spec/Governance" "Spec/MultiSig" @@ -199,6 +201,7 @@ "Spec/Escrow" "Spec/SimpleEscrow" "Spec/Future" + "Spec/Game" "Spec/GameStateMachine" "Spec/Governance" "Spec/MultiSig" diff --git a/nix/pkgs/haskell/materialized-windows/.plan.nix/plutus-doc.nix b/nix/pkgs/haskell/materialized-windows/.plan.nix/plutus-doc.nix index 7cd2f584e0..2ebce6357d 100644 --- a/nix/pkgs/haskell/materialized-windows/.plan.nix/plutus-doc.nix +++ b/nix/pkgs/haskell/materialized-windows/.plan.nix/plutus-doc.nix @@ -38,6 +38,7 @@ (hsPkgs."template-haskell" or (errorHandler.buildDepError "template-haskell")) (hsPkgs."bytestring" or (errorHandler.buildDepError "bytestring")) (hsPkgs."cardano-api" or (errorHandler.buildDepError "cardano-api")) + (hsPkgs."data-default" or (errorHandler.buildDepError "data-default")) (hsPkgs."flat" or (errorHandler.buildDepError "flat")) (hsPkgs."plutus-core" or (errorHandler.buildDepError "plutus-core")) (hsPkgs."plutus-chain-index-core" or (errorHandler.buildDepError "plutus-chain-index-core")) diff --git a/nix/pkgs/haskell/materialized-windows/.plan.nix/plutus-use-cases.nix b/nix/pkgs/haskell/materialized-windows/.plan.nix/plutus-use-cases.nix index b3d57dc83a..0e6768b9ca 100644 --- a/nix/pkgs/haskell/materialized-windows/.plan.nix/plutus-use-cases.nix +++ b/nix/pkgs/haskell/materialized-windows/.plan.nix/plutus-use-cases.nix @@ -67,6 +67,7 @@ "Plutus/Contracts/Escrow" "Plutus/Contracts/SimpleEscrow" "Plutus/Contracts/Future" + "Plutus/Contracts/Game" "Plutus/Contracts/GameStateMachine" "Plutus/Contracts/Governance" "Plutus/Contracts/MultiSig" @@ -143,6 +144,7 @@ "Spec/Escrow" "Spec/SimpleEscrow" "Spec/Future" + "Spec/Game" "Spec/GameStateMachine" "Spec/Governance" "Spec/MultiSig" @@ -199,6 +201,7 @@ "Spec/Escrow" "Spec/SimpleEscrow" "Spec/Future" + "Spec/Game" "Spec/GameStateMachine" "Spec/Governance" "Spec/MultiSig" diff --git a/plutus-pab-executables/examples/ContractExample.hs b/plutus-pab-executables/examples/ContractExample.hs index 225fae075c..d714ccd002 100644 --- a/plutus-pab-executables/examples/ContractExample.hs +++ b/plutus-pab-executables/examples/ContractExample.hs @@ -18,6 +18,7 @@ module ContractExample( import Control.Monad.Freer import Data.Aeson (FromJSON, ToJSON) import Data.Default (Default (def)) +import Data.Text (Text) import GHC.Generics (Generic) import Prettyprinter @@ -32,6 +33,7 @@ import Language.PureScript.Bridge.TypeParameters (A) import Ledger (TxId) import Playground.Types (FunctionSchema) import Plutus.Contracts.Currency qualified as Contracts.Currency +import Plutus.Contracts.Game qualified as Contracts.Game import Plutus.Contracts.GameStateMachine qualified as Contracts.GameStateMachine import Plutus.Contracts.PingPong qualified as Contracts.PingPong import Plutus.Contracts.Prism.Mirror qualified as Contracts.Prism @@ -49,6 +51,7 @@ import Schema (FormSchema) data ContractExample = UniswapInit | UniswapOwner | UniswapUser Contracts.Uniswap.Uniswap + | Game | GameStateMachine | PayToWallet | AtomicSwap @@ -78,6 +81,7 @@ instance HasPSTypes ContractExample where instance HasDefinitions ContractExample where getDefinitions = [ UniswapInit , UniswapOwner + , Game , GameStateMachine , PayToWallet , AtomicSwap @@ -97,6 +101,7 @@ getContractExampleSchema = \case UniswapInit -> Builtin.endpointsToSchemas @Empty UniswapUser _ -> Builtin.endpointsToSchemas @Contracts.Uniswap.UniswapUserSchema UniswapOwner -> Builtin.endpointsToSchemas @Contracts.Uniswap.UniswapOwnerSchema + Game -> Builtin.endpointsToSchemas @Contracts.Game.GameSchema GameStateMachine -> Builtin.endpointsToSchemas @Contracts.GameStateMachine.GameStateMachineSchema PayToWallet -> Builtin.endpointsToSchemas @Contracts.PayToWallet.PayToWalletSchema AtomicSwap -> Builtin.endpointsToSchemas @Contracts.AtomicSwap.AtomicSwapSchema @@ -114,6 +119,7 @@ getContractExample = \case UniswapInit -> SomeBuiltin Contracts.Uniswap.setupTokens UniswapUser us -> SomeBuiltin $ Contracts.Uniswap.userEndpoints us UniswapOwner -> SomeBuiltin Contracts.Uniswap.ownerEndpoint + Game -> SomeBuiltin (Contracts.Game.contract @Text) GameStateMachine -> SomeBuiltin Contracts.GameStateMachine.contract PayToWallet -> SomeBuiltin Contracts.PayToWallet.payToWallet AtomicSwap -> SomeBuiltin Contracts.AtomicSwap.atomicSwap diff --git a/plutus-use-cases/plutus-use-cases.cabal b/plutus-use-cases/plutus-use-cases.cabal index d1e6ca8b21..d0c27c488c 100644 --- a/plutus-use-cases/plutus-use-cases.cabal +++ b/plutus-use-cases/plutus-use-cases.cabal @@ -35,6 +35,7 @@ library Plutus.Contracts.Escrow Plutus.Contracts.SimpleEscrow Plutus.Contracts.Future + Plutus.Contracts.Game Plutus.Contracts.GameStateMachine Plutus.Contracts.Governance Plutus.Contracts.MultiSig @@ -109,6 +110,7 @@ test-suite plutus-use-cases-test Spec.Escrow Spec.SimpleEscrow Spec.Future + Spec.Game Spec.GameStateMachine Spec.Governance Spec.MultiSig @@ -175,6 +177,7 @@ executable plutus-use-cases-scripts Spec.Escrow Spec.SimpleEscrow Spec.Future + Spec.Game Spec.GameStateMachine Spec.Governance Spec.MultiSig diff --git a/plutus-use-cases/scripts/Main.hs b/plutus-use-cases/scripts/Main.hs index b56c986c92..93285ebe00 100644 --- a/plutus-use-cases/scripts/Main.hs +++ b/plutus-use-cases/scripts/Main.hs @@ -1,10 +1,6 @@ -{-# LANGUAGE DeriveAnyClass #-} -{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeFamilies #-} module Main(main, ExportTx(..)) where @@ -21,6 +17,7 @@ import Plutus.Trace (Command (..), ScriptsConfig (..), showStats, writeScriptsTo import Spec.Currency qualified as Currency import Spec.Escrow qualified as Escrow import Spec.Future qualified as Future +import Spec.Game qualified as Game import Spec.GameStateMachine qualified as GameStateMachine import Spec.MultiSig qualified as MultiSig import Spec.MultiSigStateMachine qualified as MultiSigStateMachine @@ -102,6 +99,7 @@ writeScripts config = do , ("future-increase-margin", Future.increaseMarginTrace, def) , ("future-settle-early", Future.settleEarlyTrace, def) , ("future-pay-out", Future.payOutTrace, def) + , ("game-success", Game.successTrace, def) , ("game-sm-success_1", GameStateMachine.successTrace, def) , ("game-sm-success_2", GameStateMachine.successTrace2, def) , ("multisig-success", MultiSig.succeedingTrace, def) diff --git a/plutus-use-cases/src/Plutus/Contracts/Game.hs b/plutus-use-cases/src/Plutus/Contracts/Game.hs new file mode 100644 index 0000000000..644d507792 --- /dev/null +++ b/plutus-use-cases/src/Plutus/Contracts/Game.hs @@ -0,0 +1,192 @@ +{-# LANGUAGE AllowAmbiguousTypes #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE PartialTypeSignatures #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE ViewPatterns #-} + +-- | A guessing game. A simplified version of 'Plutus.Contract.GameStateMachine' +-- not using 'Plutus.Contract.StateMachine' and using `yieldUnbalancedTx' for +-- balancing, signing and submitting transactions. +-- +-- Currently, remote wallets (anything other than WBE) can only handles +-- `yieldUnbalancedTx` requests, and not `balanceTx`, `signTx` and `submitTx` +-- requests. +module Plutus.Contracts.Game + ( contract + , GameParam(..) + , GameSchema + , LockArgs(..) + , GuessArgs(..) + -- * Scripts + , gameInstance + , mkValidator + -- * Address + , gameAddress + , covIdx + ) where + +import Data.Aeson (FromJSON, ToJSON) +import Data.ByteString.Char8 qualified as C +import Data.Map (Map) +import Data.Map qualified as Map +import Data.Maybe (catMaybes) +import GHC.Generics (Generic) +import Ledger (Address, Datum (Datum), POSIXTime, PaymentPubKeyHash, ScriptContext, TxOutRef, Validator, Value) +import Ledger qualified +import Ledger.Ada qualified as Ada +import Ledger.Constraints qualified as Constraints +import Ledger.Tx (ChainIndexTxOut (..)) +import Ledger.Typed.Scripts qualified as Scripts +import Playground.Contract (ToSchema) +import Plutus.Contract (AsContractError, Contract, Endpoint, Promise, collectFromScript, endpoint, fundsAtAddressGeq, + logInfo, mkTxConstraints, selectList, type (.\/), yieldUnbalancedTx) +import PlutusTx qualified +import PlutusTx.Code (getCovIdx) +import PlutusTx.Coverage (CoverageIndex) +import PlutusTx.Prelude hiding (pure, (<$>)) +import Prelude qualified as Haskell + +-- | Datatype for creating a parameterized validator. +data GameParam = GameParam + { gameParamPayeePkh :: PaymentPubKeyHash + -- ^ Payment public key hash of the wallet locking some funds + , gameParamStartTime :: POSIXTime + -- ^ Starting time of the game + } deriving (Haskell.Show, Generic) + deriving anyclass (ToJSON, FromJSON, ToSchema) + +PlutusTx.makeLift ''GameParam + +newtype HashedString = HashedString BuiltinByteString + deriving newtype (PlutusTx.ToData, PlutusTx.FromData, PlutusTx.UnsafeFromData) + +PlutusTx.makeLift ''HashedString + +newtype ClearString = ClearString BuiltinByteString + deriving newtype (PlutusTx.ToData, PlutusTx.FromData, PlutusTx.UnsafeFromData) + +PlutusTx.makeLift ''ClearString + +type GameSchema = + Endpoint "lock" LockArgs + .\/ Endpoint "guess" GuessArgs + +data Game +instance Scripts.ValidatorTypes Game where + type instance RedeemerType Game = ClearString + type instance DatumType Game = HashedString + +-- | The address of the game (the hash of its validator script) +gameAddress :: GameParam -> Address +gameAddress = Ledger.scriptAddress . gameValidator + +-- | The validator script of the game. +gameValidator :: GameParam -> Validator +gameValidator = Scripts.validatorScript . gameInstance + +gameInstance :: GameParam -> Scripts.TypedValidator Game +gameInstance = Scripts.mkTypedValidatorParam @Game + $$(PlutusTx.compile [|| mkValidator ||]) + $$(PlutusTx.compile [|| wrap ||]) where + wrap = Scripts.wrapValidator @HashedString @ClearString + +-- | The validation function (Datum -> Redeemer -> ScriptContext -> Bool) +{-# INLINABLE mkValidator #-} +mkValidator :: GameParam -> HashedString -> ClearString -> ScriptContext -> Bool +mkValidator _ hs cs _ = isGoodGuess hs cs + +{-# INLINABLE isGoodGuess #-} +isGoodGuess :: HashedString -> ClearString -> Bool +isGoodGuess (HashedString actual) (ClearString guess') = actual == sha2_256 guess' + +-- TODO: Ideas welcome for how to make this interface suck less. +-- Doing it this way actually generates coverage locations that we don't care about(!) +covIdx :: GameParam -> CoverageIndex +covIdx gameParam = + getCovIdx ($$(PlutusTx.compile [|| mkValidator ||]) `PlutusTx.applyCode` PlutusTx.liftCode gameParam) + +-- create a data script for the guessing game by hashing the string +-- and lifting the hash to its on-chain representation +hashString :: Haskell.String -> HashedString +hashString = HashedString . sha2_256 . toBuiltin . C.pack + +-- create a redeemer script for the guessing game by lifting the +-- string to its on-chain representation +clearString :: Haskell.String -> ClearString +clearString = ClearString . toBuiltin . C.pack + +-- | Arguments for the @"lock"@ endpoint +data LockArgs = + LockArgs + { lockArgsGameParam :: GameParam + -- ^ The parameters for parameterizing the validator. + , lockArgsSecret :: Haskell.String -- SecretArgument Haskell.String + -- ^ The secret + , lockArgsValue :: Value + -- ^ Value that is locked by the contract initially + } deriving stock (Haskell.Show, Generic) + deriving anyclass (ToJSON, FromJSON, ToSchema) + +-- | Arguments for the @"guess"@ endpoint +data GuessArgs = + GuessArgs + { guessArgsGameParam :: GameParam + -- ^ The parameters for parameterizing the validator. + , guessArgsSecret :: Haskell.String + -- ^ The guess + } deriving stock (Haskell.Show, Generic) + deriving anyclass (ToJSON, FromJSON, ToSchema) + +-- | The "lock" contract endpoint. See note [Contract endpoints] +lock :: AsContractError e => Promise () GameSchema e () +lock = endpoint @"lock" $ \LockArgs { lockArgsGameParam, lockArgsSecret, lockArgsValue } -> do + logInfo @Haskell.String $ "Pay " <> Haskell.show lockArgsValue <> " to the script" + let lookups = Constraints.typedValidatorLookups (gameInstance lockArgsGameParam) + tx = Constraints.mustPayToTheScript (hashString lockArgsSecret) lockArgsValue + unbalancedTx <- mkTxConstraints lookups tx + yieldUnbalancedTx $ Constraints.adjustUnbalancedTx unbalancedTx + +-- | The "guess" contract endpoint. See note [Contract endpoints] +guess :: AsContractError e => Promise () GameSchema e () +guess = endpoint @"guess" $ \GuessArgs { guessArgsGameParam, guessArgsSecret } -> do + -- Wait for script to have a UTxO of a least 1 lovelace + logInfo @Haskell.String "Waiting for script to have a UTxO of at least 1 lovelace" + utxos <- fundsAtAddressGeq (gameAddress guessArgsGameParam) (Ada.lovelaceValueOf 1) + + let lookups = Constraints.typedValidatorLookups (gameInstance guessArgsGameParam) + Haskell.<> Constraints.unspentOutputs utxos + redeemer = clearString guessArgsSecret + tx = collectFromScript utxos redeemer + + unbalancedTx <- mkTxConstraints lookups tx + yieldUnbalancedTx unbalancedTx + +-- | Find the secret word in the Datum of the UTxOs +findSecretWordValue :: Map TxOutRef ChainIndexTxOut -> Maybe HashedString +findSecretWordValue = + listToMaybe . catMaybes . Map.elems . Map.map secretWordValue + +-- | Extract the secret word in the Datum of a given transaction output is possible +secretWordValue :: ChainIndexTxOut -> Maybe HashedString +secretWordValue o = do + Datum d <- either (const Nothing) Just (_ciTxOutDatum o) + PlutusTx.fromBuiltinData d + +contract :: AsContractError e => Contract () GameSchema e () +contract = do + logInfo @Haskell.String "Waiting for lock or guess endpoint..." + selectList [lock, guess] >> contract diff --git a/plutus-use-cases/src/Plutus/Contracts/GameStateMachine.hs b/plutus-use-cases/src/Plutus/Contracts/GameStateMachine.hs index 7f23af0031..eb828359c1 100644 --- a/plutus-use-cases/src/Plutus/Contracts/GameStateMachine.hs +++ b/plutus-use-cases/src/Plutus/Contracts/GameStateMachine.hs @@ -25,12 +25,14 @@ module Plutus.Contracts.GameStateMachine( contract , typedValidator - , GameToken + , GameParam(..) + , GuessToken , mkValidator , mintingPolicy , LockArgs(..) , GuessArgs(..) - , GameStateMachineSchema, GameError + , GameStateMachineSchema + , GameError , token , covIdx ) where @@ -38,29 +40,38 @@ module Plutus.Contracts.GameStateMachine( import Control.Lens (makeClassyPrisms) import Control.Monad (void) import Data.Aeson (FromJSON, ToJSON) +import Data.ByteString.Char8 qualified as C import GHC.Generics (Generic) -import Ledger hiding (to) +import Ledger (MintingPolicyHash, POSIXTime, PaymentPubKeyHash, TokenName, Value) import Ledger.Ada qualified as Ada import Ledger.Constraints (TxConstraints) import Ledger.Constraints qualified as Constraints import Ledger.Typed.Scripts qualified as Scripts import Ledger.Value qualified as V -import PlutusTx qualified -import PlutusTx.Code -import PlutusTx.Coverage -import PlutusTx.Prelude hiding (Applicative (..), check) -import Schema (ToArgument, ToSchema) - -import Data.ByteString.Char8 qualified as C - -import Plutus.Contract.StateMachine (State (..), Void) +import Plutus.Contract (AsContractError (_ContractError), Contract, ContractError, Endpoint, Promise, endpoint, + selectList, type (.\/)) +import Plutus.Contract.Secrets (SecretArgument, escape_sha2_256, extractSecret) +import Plutus.Contract.StateMachine (State (State, stateData, stateValue), Void) import Plutus.Contract.StateMachine qualified as SM - -import Plutus.Contract -import Plutus.Contract.Secrets +import PlutusTx qualified +import PlutusTx.Code (getCovIdx) +import PlutusTx.Coverage (CoverageIndex) +import PlutusTx.Prelude (Bool (False, True), BuiltinByteString, Eq, Maybe (Just, Nothing), sha2_256, toBuiltin, + traceIfFalse, ($), (&&), (-), (.), (<$>), (<>), (==), (>>)) +import Schema (ToSchema) import Prelude qualified as Haskell +-- | Datatype for creating a parameterized validator. +data GameParam = GameParam + { gameParamPayeePkh :: PaymentPubKeyHash + -- ^ Payment public key hash of the wallet locking some funds + , gameParamStartTime :: POSIXTime + -- ^ Starting time of the game + } deriving (Haskell.Show, Generic) + deriving anyclass (ToJSON, FromJSON, ToSchema) + +PlutusTx.makeLift ''GameParam newtype HashedString = HashedString BuiltinByteString deriving newtype (Eq, PlutusTx.ToData, PlutusTx.FromData, PlutusTx.UnsafeFromData) @@ -79,24 +90,28 @@ PlutusTx.makeLift ''ClearString -- | Arguments for the @"lock"@ endpoint data LockArgs = LockArgs - { lockArgsSecret :: SecretArgument Haskell.String + { lockArgsGameParam :: GameParam + -- ^ The parameters for parameterizing the validator. + , lockArgsSecret :: SecretArgument Haskell.String -- ^ The secret - , lockArgsValue :: Value + , lockArgsValue :: Value -- ^ Value that is locked by the contract initially } deriving stock (Haskell.Show, Generic) - deriving anyclass (ToJSON, FromJSON, ToSchema, ToArgument) + deriving anyclass (ToJSON, FromJSON, ToSchema) -- | Arguments for the @"guess"@ endpoint data GuessArgs = GuessArgs - { guessArgsOldSecret :: Haskell.String + { guessArgsGameParam :: GameParam + -- ^ The parameters for parameterizing the validator. + , guessArgsOldSecret :: Haskell.String -- ^ The guess , guessArgsNewSecret :: SecretArgument Haskell.String -- ^ The new secret , guessArgsValueTakenOut :: Value -- ^ How much to extract from the contract } deriving stock (Haskell.Show, Generic) - deriving anyclass (ToJSON, FromJSON, ToSchema, ToArgument) + deriving anyclass (ToJSON, FromJSON, ToSchema) -- | The schema of the contract. It consists of the two endpoints @"lock"@ -- and @"guess"@ with their respective argument types. @@ -123,7 +138,7 @@ contract :: Contract () GameStateMachineSchema GameError () contract = selectList [lock, guess] >> contract -- | The token that represents the right to make a guess -newtype GameToken = GameToken { unGameToken :: Value } +newtype GuessToken = GuessToken { unGuessToken :: Value } deriving newtype (Eq, Haskell.Show) token :: MintingPolicyHash -> TokenName -> Value @@ -145,6 +160,7 @@ instance Eq GameState where {-# INLINABLE (==) #-} (Initialised sym tn s) == (Initialised sym' tn' s') = sym == sym' && s == s' && tn == tn' (Locked sym tn s) == (Locked sym' tn' s') = sym == sym' && s == s' && tn == tn' + Finished == Finished = True _ == _ = traceIfFalse "states not equal" False -- | Check whether a 'ClearString' is the preimage of a @@ -163,8 +179,12 @@ data GameInput = deriving anyclass (ToJSON, FromJSON) {-# INLINABLE transition #-} -transition :: State GameState -> GameInput -> Maybe (TxConstraints Void Void, State GameState) -transition State{stateData=oldData, stateValue=oldValue} input = case (oldData, input) of +transition + :: GameParam + -> State GameState + -> GameInput + -> Maybe (TxConstraints Void Void, State GameState) +transition _ State{stateData=oldData, stateValue=oldValue} input = case (oldData, input) of (Initialised mph tn s, MintToken) -> let constraints = Constraints.mustMintCurrency mph tn 1 in Just ( constraints @@ -175,7 +195,8 @@ transition State{stateData=oldData, stateValue=oldValue} input = case (oldData, ) (Locked mph tn currentSecret, Guess theGuess nextSecret takenOut) | checkGuess currentSecret theGuess -> - let constraints = Constraints.mustSpendAtLeast (token mph tn) <> Constraints.mustMintCurrency mph tn 0 + let constraints = Constraints.mustSpendAtLeast (token mph tn) + <> Constraints.mustMintCurrency mph tn 0 newValue = oldValue - takenOut in Just ( constraints , State @@ -190,54 +211,55 @@ transition State{stateData=oldData, stateValue=oldValue} input = case (oldData, type GameStateMachine = SM.StateMachine GameState GameInput {-# INLINABLE machine #-} -machine :: GameStateMachine -machine = SM.mkStateMachine Nothing transition isFinal where +machine :: GameParam -> GameStateMachine +machine gameParam = SM.mkStateMachine Nothing (transition gameParam) isFinal where isFinal Finished = True isFinal _ = False {-# INLINABLE mkValidator #-} -mkValidator :: Scripts.ValidatorType GameStateMachine -mkValidator = SM.mkValidator machine +mkValidator :: GameParam -> Scripts.ValidatorType GameStateMachine +mkValidator gameParam = SM.mkValidator (machine gameParam) -typedValidator :: Scripts.TypedValidator GameStateMachine -typedValidator = Scripts.mkTypedValidator @GameStateMachine - $$(PlutusTx.compile [|| mkValidator ||]) +typedValidator :: GameParam -> Scripts.TypedValidator GameStateMachine +typedValidator gp = Scripts.mkTypedValidator @GameStateMachine + ($$(PlutusTx.compile [|| mkValidator ||]) `PlutusTx.applyCode` PlutusTx.liftCode gp) $$(PlutusTx.compile [|| wrap ||]) where wrap = Scripts.wrapValidator -- TODO: Ideas welcome for how to make this interface suck less. -- Doing it this way actually generates coverage locations that we don't care about(!) -covIdx :: CoverageIndex -covIdx = getCovIdx $$(PlutusTx.compile [|| mkValidator ||]) +covIdx :: GameParam -> CoverageIndex +covIdx gp = getCovIdx ($$(PlutusTx.compile [|| mkValidator ||]) `PlutusTx.applyCode` PlutusTx.liftCode gp) + +mintingPolicy :: GameParam -> Scripts.MintingPolicy +mintingPolicy gp = Scripts.forwardingMintingPolicy $ typedValidator gp -mintingPolicy :: Scripts.MintingPolicy -mintingPolicy = Scripts.forwardingMintingPolicy typedValidator +client :: GameParam -> SM.StateMachineClient GameState GameInput +client gp = SM.mkStateMachineClient $ SM.StateMachineInstance (machine gp) $ typedValidator gp -client :: SM.StateMachineClient GameState GameInput -client = SM.mkStateMachineClient $ SM.StateMachineInstance machine typedValidator +-- | The @"lock"@ endpoint. +lock :: Promise () GameStateMachineSchema GameError () +lock = endpoint @"lock" $ \LockArgs{lockArgsGameParam, lockArgsSecret, lockArgsValue} -> do + let secret = HashedString (escape_sha2_256 (toBuiltin . C.pack <$> extractSecret lockArgsSecret)) + sym = Scripts.forwardingMintingPolicyHash $ typedValidator lockArgsGameParam + _ <- SM.runInitialise (client lockArgsGameParam) (Initialised sym "guess" secret) lockArgsValue + void $ SM.runStep (client lockArgsGameParam) MintToken -- | The @"guess"@ endpoint. guess :: Promise () GameStateMachineSchema GameError () -guess = endpoint @"guess" $ \GuessArgs{guessArgsOldSecret,guessArgsNewSecret, guessArgsValueTakenOut} -> do +guess = endpoint @"guess" $ \GuessArgs{guessArgsGameParam, guessArgsOldSecret, guessArgsNewSecret, guessArgsValueTakenOut} -> do let guessedSecret = ClearString (toBuiltin (C.pack guessArgsOldSecret)) newSecret = HashedString (escape_sha2_256 (toBuiltin . C.pack <$> extractSecret guessArgsNewSecret)) void - $ SM.runStep client + $ SM.runStep (client guessArgsGameParam) (Guess guessedSecret newSecret guessArgsValueTakenOut) -lock :: Promise () GameStateMachineSchema GameError () -lock = endpoint @"lock" $ \LockArgs{lockArgsSecret, lockArgsValue} -> do - let secret = HashedString (escape_sha2_256 (toBuiltin . C.pack <$> extractSecret lockArgsSecret)) - sym = Scripts.forwardingMintingPolicyHash typedValidator - _ <- SM.runInitialise client (Initialised sym "guess" secret) lockArgsValue - void $ SM.runStep client MintToken - PlutusTx.unstableMakeIsData ''GameState PlutusTx.makeLift ''GameState PlutusTx.unstableMakeIsData ''GameInput PlutusTx.makeLift ''GameInput -PlutusTx.makeLift ''GameToken -PlutusTx.unstableMakeIsData ''GameToken +PlutusTx.makeLift ''GuessToken +PlutusTx.unstableMakeIsData ''GuessToken diff --git a/plutus-use-cases/test/Spec.hs b/plutus-use-cases/test/Spec.hs index c29303c27b..291675f497 100644 --- a/plutus-use-cases/test/Spec.hs +++ b/plutus-use-cases/test/Spec.hs @@ -7,6 +7,7 @@ import Spec.Currency qualified import Spec.ErrorHandling qualified import Spec.Escrow qualified import Spec.Future qualified +import Spec.Game qualified import Spec.GameStateMachine qualified import Spec.Governance qualified import Spec.SealedBidAuction qualified @@ -48,6 +49,7 @@ tests = localOption limit $ testGroup "use cases" [ Spec.PubKey.tests, Spec.Escrow.tests, Spec.SimpleEscrow.tests, + Spec.Game.tests, Spec.GameStateMachine.tests, Spec.Rollup.tests, Spec.TokenAccount.tests, diff --git a/plutus-use-cases/test/Spec/Game.hs b/plutus-use-cases/test/Spec/Game.hs new file mode 100644 index 0000000000..a485b02386 --- /dev/null +++ b/plutus-use-cases/test/Spec/Game.hs @@ -0,0 +1,98 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DeriveFunctor #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE MultiWayIf #-} +{-# LANGUAGE NumericUnderscores #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE StandaloneDeriving #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE UndecidableInstances #-} +module Spec.Game + ( tests, successTrace, failTrace + ) where + +import Control.Monad (void) +import Data.Default (Default (def)) +import Data.Text (Text) +import Test.Tasty (TestTree, testGroup) +import Test.Tasty.HUnit qualified as HUnit + +import Ledger.Ada qualified as Ada +import Ledger.TimeSlot qualified as TimeSlot +import Ledger.Typed.Scripts qualified as Scripts +import Ledger.Value (Value) +import Plutus.Contract.Test (checkPredicate, goldenPir, mockWalletPaymentPubKeyHash, reasonable', valueAtAddress, w1, + w2, walletFundsChange, (.&&.)) +import Plutus.Contracts.Game (GuessArgs (GuessArgs, guessArgsGameParam, guessArgsSecret), + LockArgs (LockArgs, lockArgsGameParam, lockArgsSecret, lockArgsValue)) +import Plutus.Contracts.Game qualified as G +import Plutus.Trace.Emulator (EmulatorTrace) +import Plutus.Trace.Emulator qualified as Trace +import PlutusTx qualified + +gameParam :: G.GameParam +gameParam = G.GameParam (mockWalletPaymentPubKeyHash w1) (TimeSlot.scSlotZeroTime def) + +-- * Unit tests + +tests :: TestTree +tests = + testGroup "game state machine with secret arguments tests" + [ checkPredicate "run a successful game trace" + (walletFundsChange w2 (Ada.adaValueOf 8) + .&&. valueAtAddress (Scripts.validatorAddress $ G.gameInstance gameParam) (Ada.adaValueOf 0 ==) + .&&. walletFundsChange w1 (Ada.adaValueOf (-8))) + successTrace + + , checkPredicate "run a failed trace" + (walletFundsChange w2 mempty + .&&. valueAtAddress (Scripts.validatorAddress $ G.gameInstance gameParam) (Ada.adaValueOf 8 ==) + .&&. walletFundsChange w1 (Ada.adaValueOf (-8))) + failTrace + + , goldenPir "test/Spec/game.pir" $$(PlutusTx.compile [|| G.mkValidator ||]) + + , HUnit.testCaseSteps "script size is reasonable" $ \step -> + reasonable' step (Scripts.validatorScript $ G.gameInstance gameParam) 49000 + ] + +initialVal :: Value +initialVal = Ada.adaValueOf 10 + +-- | Wallet 1 locks some funds, and w2 then makes a correct guess. +successTrace :: EmulatorTrace () +successTrace = do + hdl <- Trace.activateContractWallet w1 $ G.contract @Text + Trace.callEndpoint @"lock" hdl LockArgs { lockArgsGameParam = gameParam + , lockArgsSecret = "hello" + , lockArgsValue = Ada.adaValueOf 8 + } + -- One slot for sending the Ada to the script. + _ <- Trace.waitNSlots 1 + hdl2 <- Trace.activateContractWallet w2 $ G.contract @Text + Trace.callEndpoint @"guess" hdl2 GuessArgs { guessArgsGameParam = gameParam + , guessArgsSecret = "hello" + } + void $ Trace.waitNSlots 1 + +-- | Wallet 1 locks some funds, and Wallet 2 makes a wrong guess. +failTrace :: EmulatorTrace () +failTrace = do + hdl <- Trace.activateContractWallet w1 $ G.contract @Text + Trace.callEndpoint @"lock" hdl LockArgs { lockArgsGameParam = gameParam + , lockArgsSecret = "hello" + , lockArgsValue = Ada.adaValueOf 8 + } + _ <- Trace.waitNSlots 1 + hdl2 <- Trace.activateContractWallet w2 $ G.contract @Text + _ <- Trace.callEndpoint @"guess" hdl2 GuessArgs { guessArgsGameParam = gameParam + , guessArgsSecret = "hola" + } + void $ Trace.waitNSlots 1 diff --git a/plutus-use-cases/test/Spec/GameStateMachine.hs b/plutus-use-cases/test/Spec/GameStateMachine.hs index 374324c5ed..227b577601 100644 --- a/plutus-use-cases/test/Spec/GameStateMachine.hs +++ b/plutus-use-cases/test/Spec/GameStateMachine.hs @@ -33,8 +33,10 @@ import Test.Tasty hiding (after) import Test.Tasty.HUnit qualified as HUnit import Test.Tasty.QuickCheck (testProperty) +import Data.Default (Default (def)) import Ledger qualified import Ledger.Ada qualified as Ada +import Ledger.TimeSlot qualified as TimeSlot import Ledger.Typed.Scripts qualified as Scripts import Ledger.Value (Value, isZero) import Plutus.Contract.Secrets @@ -45,13 +47,18 @@ import Plutus.Contracts.GameStateMachine as G import Plutus.Trace.Emulator as Trace import PlutusTx qualified import PlutusTx.Coverage + +gameParam :: G.GameParam +gameParam = G.GameParam (mockWalletPaymentPubKeyHash w1) (TimeSlot.scSlotZeroTime def) + -- -- * QuickCheck model data GameModel = GameModel { _gameValue :: Integer , _hasToken :: Maybe Wallet - , _currentSecret :: String } + , _currentSecret :: String + } deriving (Show) makeLenses 'GameModel @@ -84,17 +91,22 @@ instance ContractModel GameModel where perform handle s cmd = case cmd of Lock w new val -> do Trace.callEndpoint @"lock" (handle $ WalletKey w) - LockArgs{lockArgsSecret = secretArg new, lockArgsValue = Ada.lovelaceValueOf val} + LockArgs { lockArgsGameParam = gameParam + , lockArgsSecret = secretArg new + , lockArgsValue = Ada.lovelaceValueOf val + } delay 2 Guess w old new val -> do Trace.callEndpoint @"guess" (handle $ WalletKey w) - GuessArgs{ guessArgsOldSecret = old - , guessArgsNewSecret = secretArg new - , guessArgsValueTakenOut = Ada.lovelaceValueOf val} + GuessArgs { guessArgsGameParam = gameParam + , guessArgsOldSecret = old + , guessArgsNewSecret = secretArg new + , guessArgsValueTakenOut = Ada.lovelaceValueOf val + } delay 1 GiveToken w' -> do let w = fromJust (s ^. contractState . hasToken) - _ <- Trace.payToWallet w w' gameTokenVal + _ <- Trace.payToWallet w w' guessTokenVal delay 1 -- 'nextState' descibes how each command affects the state of the model @@ -103,8 +115,8 @@ instance ContractModel GameModel where hasToken $= Just w currentSecret $= secret gameValue $= val - mint gameTokenVal - deposit w gameTokenVal + mint guessTokenVal + deposit w guessTokenVal withdraw w $ Ada.lovelaceValueOf val wait 2 @@ -120,7 +132,7 @@ instance ContractModel GameModel where w0 <- fromJust <$> viewContractState hasToken withdraw w0 $ Ada.toValue Ledger.minAdaTxOut deposit w $ Ada.toValue Ledger.minAdaTxOut - transfer w0 w gameTokenVal + transfer w0 w guessTokenVal hasToken $= Just w wait 1 @@ -187,7 +199,7 @@ prop_SanityCheckModel = propSanityCheckModel @GameModel check_prop_Game_with_coverage :: IO CoverageReport check_prop_Game_with_coverage = - quickCheckWithCoverage (set coverageIndex covIdx $ defaultCoverageOptions) $ \covopts -> + quickCheckWithCoverage (set coverageIndex (covIdx gameParam) defaultCoverageOptions) $ \covopts -> propRunActionsWithOptions @GameModel defaultCheckOptions covopts (const (pure True)) @@ -287,39 +299,38 @@ tests :: TestTree tests = testGroup "game state machine with secret arguments tests" [ checkPredicate "run a successful game trace" - (walletFundsChange w2 (Ada.toValue Ledger.minAdaTxOut <> Ada.adaValueOf 3 <> gameTokenVal) - .&&. valueAtAddress (Scripts.validatorAddress G.typedValidator) (Ada.adaValueOf 5 ==) + (walletFundsChange w2 (Ada.toValue Ledger.minAdaTxOut <> Ada.adaValueOf 3 <> guessTokenVal) + .&&. valueAtAddress (Scripts.validatorAddress $ G.typedValidator gameParam) (Ada.adaValueOf 5 ==) .&&. walletFundsChange w1 (Ada.toValue (-Ledger.minAdaTxOut) <> Ada.adaValueOf (-8))) successTrace , checkPredicate "run a 2nd successful game trace" (walletFundsChange w2 (Ada.adaValueOf 3) - .&&. valueAtAddress (Scripts.validatorAddress G.typedValidator) (Ada.adaValueOf 0 ==) + .&&. valueAtAddress (Scripts.validatorAddress $ G.typedValidator gameParam) (Ada.adaValueOf 0 ==) .&&. walletFundsChange w1 (Ada.toValue (-Ledger.minAdaTxOut) <> Ada.adaValueOf (-8)) - .&&. walletFundsChange w3 (Ada.toValue Ledger.minAdaTxOut <> Ada.adaValueOf 5 <> gameTokenVal)) + .&&. walletFundsChange w3 (Ada.toValue Ledger.minAdaTxOut <> Ada.adaValueOf 5 <> guessTokenVal)) successTrace2 , checkPredicate "run a successful game trace where we try to leave 1 Ada in the script address" - (walletFundsChange w1 (Ada.toValue (-Ledger.minAdaTxOut) <> gameTokenVal) - .&&. valueAtAddress (Scripts.validatorAddress G.typedValidator) (Ada.toValue Ledger.minAdaTxOut ==)) + (walletFundsChange w1 (Ada.toValue (-Ledger.minAdaTxOut) <> guessTokenVal) + .&&. valueAtAddress (Scripts.validatorAddress $ G.typedValidator gameParam) (Ada.toValue Ledger.minAdaTxOut ==)) traceLeaveOneAdaInScript , checkPredicate "run a failed trace" - (walletFundsChange w2 (Ada.toValue Ledger.minAdaTxOut <> gameTokenVal) - .&&. valueAtAddress (Scripts.validatorAddress G.typedValidator) (Ada.adaValueOf 8 ==) + (walletFundsChange w2 (Ada.toValue Ledger.minAdaTxOut <> guessTokenVal) + .&&. valueAtAddress (Scripts.validatorAddress $ G.typedValidator gameParam) (Ada.adaValueOf 8 ==) .&&. walletFundsChange w1 (Ada.toValue (-Ledger.minAdaTxOut) <> Ada.adaValueOf (-8))) failTrace , goldenPir "test/Spec/gameStateMachine.pir" $$(PlutusTx.compile [|| mkValidator ||]) , HUnit.testCaseSteps "script size is reasonable" $ \step -> - reasonable' step (Scripts.validatorScript G.typedValidator) 49000 + reasonable' step (Scripts.validatorScript $ G.typedValidator gameParam) 49000 , testProperty "can always get the funds out" $ withMaxSuccess 10 prop_NoLockedFunds - , testProperty "sanity check the contract model" $ - prop_SanityCheckModel + , testProperty "sanity check the contract model" prop_SanityCheckModel ] initialVal :: Value @@ -331,14 +342,21 @@ initialVal = Ada.adaValueOf 10 successTrace :: EmulatorTrace () successTrace = do hdl <- Trace.activateContractWallet w1 G.contract - Trace.callEndpoint @"lock" hdl LockArgs{lockArgsSecret=secretArg "hello", lockArgsValue= Ada.adaValueOf 8} + Trace.callEndpoint @"lock" hdl LockArgs { lockArgsGameParam = gameParam + , lockArgsSecret = secretArg "hello" + , lockArgsValue = Ada.adaValueOf 8 + } -- One slot for sending the Ada to the script and one slot for minting the -- guess token _ <- Trace.waitNSlots 2 - _ <- Trace.payToWallet w1 w2 gameTokenVal + _ <- Trace.payToWallet w1 w2 guessTokenVal _ <- Trace.waitNSlots 1 hdl2 <- Trace.activateContractWallet w2 G.contract - Trace.callEndpoint @"guess" hdl2 GuessArgs{guessArgsOldSecret="hello", guessArgsNewSecret=secretArg "new secret", guessArgsValueTakenOut=Ada.adaValueOf 3} + Trace.callEndpoint @"guess" hdl2 GuessArgs { guessArgsGameParam = gameParam + , guessArgsOldSecret = "hello" + , guessArgsNewSecret = secretArg "new secret" + , guessArgsValueTakenOut = Ada.adaValueOf 3 + } void $ Trace.waitNSlots 1 -- | Run 'successTrace', then wallet 2 transfers the token to wallet 3, which @@ -346,10 +364,14 @@ successTrace = do successTrace2 :: EmulatorTrace () successTrace2 = do successTrace - _ <- Trace.payToWallet w2 w3 gameTokenVal + _ <- Trace.payToWallet w2 w3 guessTokenVal _ <- Trace.waitNSlots 1 hdl3 <- Trace.activateContractWallet w3 G.contract - Trace.callEndpoint @"guess" hdl3 GuessArgs{guessArgsOldSecret="new secret", guessArgsNewSecret=secretArg "hello", guessArgsValueTakenOut=Ada.adaValueOf 5} + Trace.callEndpoint @"guess" hdl3 GuessArgs { guessArgsGameParam = gameParam + , guessArgsOldSecret = "new secret" + , guessArgsNewSecret = secretArg "hello" + , guessArgsValueTakenOut = Ada.adaValueOf 5 + } void $ Trace.waitNSlots 1 -- | Tests whether the contract correctly handles the case where we leave less @@ -357,9 +379,16 @@ successTrace2 = do traceLeaveOneAdaInScript :: EmulatorTrace () traceLeaveOneAdaInScript = do hdl <- Trace.activateContractWallet w1 G.contract - Trace.callEndpoint @"lock" hdl LockArgs{lockArgsSecret=secretArg "hello", lockArgsValue= Ada.adaValueOf 8} + Trace.callEndpoint @"lock" hdl LockArgs { lockArgsGameParam = gameParam + , lockArgsSecret = secretArg "hello" + , lockArgsValue = Ada.adaValueOf 8 + } _ <- Trace.waitNSlots 2 - _ <- Trace.callEndpoint @"guess" hdl GuessArgs{guessArgsOldSecret="hello", guessArgsNewSecret=secretArg "new secret", guessArgsValueTakenOut=Ada.adaValueOf 7} + _ <- Trace.callEndpoint @"guess" hdl GuessArgs { guessArgsGameParam = gameParam + , guessArgsOldSecret = "hello" + , guessArgsNewSecret = secretArg "new secret" + , guessArgsValueTakenOut = Ada.adaValueOf 7 + } void $ Trace.waitNSlots 1 -- | Wallet 1 locks some funds, transfers the token to wallet 2 @@ -367,15 +396,22 @@ traceLeaveOneAdaInScript = do failTrace :: EmulatorTrace () failTrace = do hdl <- Trace.activateContractWallet w1 G.contract - Trace.callEndpoint @"lock" hdl LockArgs{lockArgsSecret=secretArg "hello", lockArgsValue= Ada.adaValueOf 8} + Trace.callEndpoint @"lock" hdl LockArgs { lockArgsGameParam = gameParam + , lockArgsSecret = secretArg "hello" + , lockArgsValue = Ada.adaValueOf 8 + } _ <- Trace.waitNSlots 2 - _ <- Trace.payToWallet w1 w2 gameTokenVal + _ <- Trace.payToWallet w1 w2 guessTokenVal _ <- Trace.waitNSlots 1 hdl2 <- Trace.activateContractWallet w2 G.contract - _ <- Trace.callEndpoint @"guess" hdl2 GuessArgs{guessArgsOldSecret="hola", guessArgsNewSecret=secretArg "new secret", guessArgsValueTakenOut=Ada.adaValueOf 3} + _ <- Trace.callEndpoint @"guess" hdl2 GuessArgs { guessArgsGameParam = gameParam + , guessArgsOldSecret = "hola" + , guessArgsNewSecret = secretArg "new secret" + , guessArgsValueTakenOut = Ada.adaValueOf 3 + } void $ Trace.waitNSlots 1 -gameTokenVal :: Value -gameTokenVal = - let sym = Scripts.forwardingMintingPolicyHash G.typedValidator +guessTokenVal :: Value +guessTokenVal = + let sym = Scripts.forwardingMintingPolicyHash $ G.typedValidator gameParam in G.token sym "guess" diff --git a/plutus-use-cases/test/Spec/game.pir b/plutus-use-cases/test/Spec/game.pir new file mode 100644 index 0000000000..32a1af3c19 --- /dev/null +++ b/plutus-use-cases/test/Spec/game.pir @@ -0,0 +1,317 @@ +(program + (let + (nonrec) + (datatypebind + (datatype + (tyvardecl GameParam (type)) + + GameParam_match + (vardecl GameParam (fun (con bytestring) (fun (con integer) GameParam))) + ) + ) + (datatypebind + (datatype + (tyvardecl Credential (type)) + + Credential_match + (vardecl PubKeyCredential (fun (con bytestring) Credential)) + (vardecl ScriptCredential (fun (con bytestring) Credential)) + ) + ) + (datatypebind + (datatype + (tyvardecl StakingCredential (type)) + + StakingCredential_match + (vardecl StakingHash (fun Credential StakingCredential)) + (vardecl + StakingPtr + (fun + (con integer) + (fun (con integer) (fun (con integer) StakingCredential)) + ) + ) + ) + ) + (datatypebind + (datatype + (tyvardecl DCert (type)) + + DCert_match + (vardecl DCertDelegDeRegKey (fun StakingCredential DCert)) + (vardecl + DCertDelegDelegate + (fun StakingCredential (fun (con bytestring) DCert)) + ) + (vardecl DCertDelegRegKey (fun StakingCredential DCert)) + (vardecl DCertGenesis DCert) + (vardecl DCertMir DCert) + (vardecl + DCertPoolRegister (fun (con bytestring) (fun (con bytestring) DCert)) + ) + (vardecl + DCertPoolRetire (fun (con bytestring) (fun (con integer) DCert)) + ) + ) + ) + (datatypebind + (datatype + (tyvardecl TxOutRef (type)) + + TxOutRef_match + (vardecl TxOutRef (fun (con bytestring) (fun (con integer) TxOutRef))) + ) + ) + (datatypebind + (datatype + (tyvardecl ScriptPurpose (type)) + + ScriptPurpose_match + (vardecl Certifying (fun DCert ScriptPurpose)) + (vardecl Minting (fun (con bytestring) ScriptPurpose)) + (vardecl Rewarding (fun StakingCredential ScriptPurpose)) + (vardecl Spending (fun TxOutRef ScriptPurpose)) + ) + ) + (datatypebind + (datatype + (tyvardecl Extended (fun (type) (type))) + (tyvardecl a (type)) + Extended_match + (vardecl Finite (fun a [ Extended a ])) + (vardecl NegInf [ Extended a ]) + (vardecl PosInf [ Extended a ]) + ) + ) + (datatypebind + (datatype + (tyvardecl Bool (type)) + + Bool_match + (vardecl True Bool) (vardecl False Bool) + ) + ) + (datatypebind + (datatype + (tyvardecl LowerBound (fun (type) (type))) + (tyvardecl a (type)) + LowerBound_match + (vardecl LowerBound (fun [ Extended a ] (fun Bool [ LowerBound a ]))) + ) + ) + (datatypebind + (datatype + (tyvardecl UpperBound (fun (type) (type))) + (tyvardecl a (type)) + UpperBound_match + (vardecl UpperBound (fun [ Extended a ] (fun Bool [ UpperBound a ]))) + ) + ) + (datatypebind + (datatype + (tyvardecl Interval (fun (type) (type))) + (tyvardecl a (type)) + Interval_match + (vardecl + Interval (fun [ LowerBound a ] (fun [ UpperBound a ] [ Interval a ])) + ) + ) + ) + (datatypebind + (datatype + (tyvardecl Maybe (fun (type) (type))) + (tyvardecl a (type)) + Maybe_match + (vardecl Just (fun a [ Maybe a ])) (vardecl Nothing [ Maybe a ]) + ) + ) + (datatypebind + (datatype + (tyvardecl Address (type)) + + Address_match + (vardecl + Address (fun Credential (fun [ Maybe StakingCredential ] Address)) + ) + ) + ) + (datatypebind + (datatype + (tyvardecl Tuple2 (fun (type) (fun (type) (type)))) + (tyvardecl a (type)) (tyvardecl b (type)) + Tuple2_match + (vardecl Tuple2 (fun a (fun b [ [ Tuple2 a ] b ]))) + ) + ) + (let + (rec) + (datatypebind + (datatype + (tyvardecl List (fun (type) (type))) + (tyvardecl a (type)) + Nil_match + (vardecl Nil [ List a ]) + (vardecl Cons (fun a (fun [ List a ] [ List a ]))) + ) + ) + (let + (nonrec) + (datatypebind + (datatype + (tyvardecl TxOut (type)) + + TxOut_match + (vardecl + TxOut + (fun + Address + (fun + [ + [ + (lam k (type) (lam v (type) [ List [ [ Tuple2 k ] v ] ])) + (con bytestring) + ] + [ + [ + (lam + k (type) (lam v (type) [ List [ [ Tuple2 k ] v ] ]) + ) + (con bytestring) + ] + (con integer) + ] + ] + (fun [ Maybe (con bytestring) ] TxOut) + ) + ) + ) + ) + ) + (datatypebind + (datatype + (tyvardecl TxInInfo (type)) + + TxInInfo_match + (vardecl TxInInfo (fun TxOutRef (fun TxOut TxInInfo))) + ) + ) + (datatypebind + (datatype + (tyvardecl TxInfo (type)) + + TxInfo_match + (vardecl + TxInfo + (fun + [ List TxInInfo ] + (fun + [ List TxOut ] + (fun + [ + [ + (lam + k (type) (lam v (type) [ List [ [ Tuple2 k ] v ] ]) + ) + (con bytestring) + ] + [ + [ + (lam + k (type) (lam v (type) [ List [ [ Tuple2 k ] v ] ]) + ) + (con bytestring) + ] + (con integer) + ] + ] + (fun + [ + [ + (lam + k (type) (lam v (type) [ List [ [ Tuple2 k ] v ] ]) + ) + (con bytestring) + ] + [ + [ + (lam + k + (type) + (lam v (type) [ List [ [ Tuple2 k ] v ] ]) + ) + (con bytestring) + ] + (con integer) + ] + ] + (fun + [ List DCert ] + (fun + [ + List [ [ Tuple2 StakingCredential ] (con integer) ] + ] + (fun + [ Interval (con integer) ] + (fun + [ List (con bytestring) ] + (fun + [ + List + [ [ Tuple2 (con bytestring) ] (con data) ] + ] + (fun (con bytestring) TxInfo) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (datatypebind + (datatype + (tyvardecl ScriptContext (type)) + + ScriptContext_match + (vardecl + ScriptContext (fun TxInfo (fun ScriptPurpose ScriptContext)) + ) + ) + ) + (lam + ds + GameParam + (lam + hs + (con bytestring) + (lam + cs + (con bytestring) + (lam + ds + ScriptContext + [ + [ + [ + { (builtin ifThenElse) Bool } + [ + [ (builtin equalsByteString) hs ] + [ (builtin sha2_256) cs ] + ] + ] + True + ] + False + ] + ) + ) + ) + ) + ) + ) + ) +) \ No newline at end of file diff --git a/plutus-use-cases/test/Spec/gameStateMachine.pir b/plutus-use-cases/test/Spec/gameStateMachine.pir index 04ac4721ab..c264962da4 100644 --- a/plutus-use-cases/test/Spec/gameStateMachine.pir +++ b/plutus-use-cases/test/Spec/gameStateMachine.pir @@ -16274,6 +16274,19 @@ (vardecl MintToken GameInput) ) ) + (datatypebind + (datatype + (tyvardecl GameParam (type)) + + GameParam_match + (vardecl + GameParam + (fun + (con bytestring) (fun (con integer) GameParam) + ) + ) + ) + ) (datatypebind (datatype (tyvardecl GameState (type)) @@ -16310,523 +16323,505 @@ [ (builtin mkNilData) (con unit ()) ] ] ) - (termbind - (strict) - (vardecl w [ [ StateMachine GameState ] GameInput ]) - [ - [ + (lam + gameParam + GameParam + (let + (nonrec) + (termbind + (strict) + (vardecl + w [ [ StateMachine GameState ] GameInput ] + ) [ [ - { { StateMachine GameState } GameInput } - (lam - w - [ State GameState ] - (lam - w - GameInput - [ - { - [ { State_match GameState } w ] + [ + [ + { { StateMachine GameState } GameInput } + (lam + w + [ State GameState ] + (lam + w + GameInput [ - Maybe - [ + { + [ { State_match GameState } w ] [ - Tuple2 + Maybe [ - [ TxConstraints Void ] Void - ] - ] - [ State GameState ] - ] - ] - } - (lam - ww - GameState - (lam - ww - [ - [ - (lam - k - (type) - (lam - v - (type) + [ + Tuple2 [ - List [ [ Tuple2 k ] v ] + [ TxConstraints Void ] + Void ] - ) - ) - (con bytestring) + ] + [ State GameState ] + ] ] - [ + } + (lam + ww + GameState + (lam + ww [ - (lam - k - (type) + [ (lam - v + k (type) - [ - List - [ [ Tuple2 k ] v ] - ] + (lam + v + (type) + [ + List + [ [ Tuple2 k ] v ] + ] + ) ) - ) - (con bytestring) - ] - (con integer) - ] - ] - { - [ - [ + (con bytestring) + ] [ - { - [ GameState_match ww ] - (all - dead + [ + (lam + k (type) - [ - Maybe + (lam + v + (type) [ - [ - Tuple2 - [ - [ - TxConstraints - Void - ] - Void - ] - ] - [ - State GameState - ] + List + [ [ Tuple2 k ] v ] ] - ] + ) ) - } - (abs - dead - (type) - { - Nothing - [ + (con bytestring) + ] + (con integer) + ] + ] + { + [ + [ + [ + { [ - Tuple2 + GameState_match ww + ] + (all + dead + (type) [ + Maybe [ - TxConstraints - Void + [ + Tuple2 + [ + [ + TxConstraints + Void + ] + Void + ] + ] + [ + State + GameState + ] ] - Void ] - ] - [ State GameState ] - ] - } - ) - ] - (lam - mph - (con bytestring) - (lam - tn - (con bytestring) - (lam - s - (con bytestring) + ) + } (abs dead (type) { + Nothing [ [ - { + Tuple2 + [ [ - GameInput_match - w + TxConstraints + Void ] - (all - dead - (type) - [ - Maybe + Void + ] + ] + [ + State + GameState + ] + ] + } + ) + ] + (lam + mph + (con bytestring) + (lam + tn + (con bytestring) + (lam + s + (con bytestring) + (abs + dead + (type) + { + [ + [ + { [ + GameInput_match + w + ] + (all + dead + (type) [ - Tuple2 + Maybe [ [ - TxConstraints - Void + Tuple2 + [ + [ + TxConstraints + Void + ] + Void + ] + ] + [ + State + GameState ] - Void ] ] - [ - State - GameState - ] - ] - ] - ) - } - (lam - ipv - (con - bytestring - ) - (lam - ipv - (con - bytestring - ) + ) + } (lam ipv - [ - [ - (lam - k - (type) - (lam - v - (type) - [ - List - [ + (con + bytestring + ) + (lam + ipv + (con + bytestring + ) + (lam + ipv + [ + [ + (lam + k + (type) + (lam + v + (type) [ - Tuple2 - k + List + [ + [ + Tuple2 + k + ] + v + ] ] - v - ] + ) + ) + (con + bytestring + ) + ] + [ + [ + (lam + k + (type) + (lam + v + (type) + [ + List + [ + [ + Tuple2 + k + ] + v + ] + ] + ) + ) + (con + bytestring + ) ] - ) - ) - (con - bytestring - ) - ] - [ - [ - (lam - k - (type) - (lam - v - (type) + (con + integer + ) + ] + ] + (abs + dead + (type) + { + Nothing + [ [ - List + Tuple2 [ [ - Tuple2 - k + TxConstraints + Void ] - v + Void ] ] - ) - ) - (con - bytestring - ) - ] - (con - integer - ) - ] - ] - (abs - dead - (type) - { - Nothing - [ - [ - Tuple2 - [ [ - TxConstraints - Void + State + GameState ] - Void ] - ] - [ - State - GameState - ] - ] - } + } + ) + ) ) ) - ) - ) - ] - (abs - dead - (type) - [ - { - Just - [ - [ - Tuple2 - [ - [ - TxConstraints - Void - ] - Void - ] - ] - [ - State - GameState - ] - ] - } - [ + ] + (abs + dead + (type) [ { - { - Tuple2 + Just + [ [ + Tuple2 [ - TxConstraints + [ + TxConstraints + Void + ] Void ] - Void ] - } - [ - State - GameState + [ + State + GameState + ] ] } [ [ - [ + { { - { - TxConstraints + Tuple2 + [ + [ + TxConstraints + Void + ] Void - } - Void + ] } [ - { - build - TxConstraint - } - (abs - a - (type) - (lam - c - (fun + State + GameState + ] + } + [ + [ + [ + { + { + TxConstraints + Void + } + Void + } + [ + { + build TxConstraint - (fun - a - a - ) - ) - (lam - n + } + (abs a - [ - [ - c + (type) + (lam + c + (fun + TxConstraint + (fun + a + a + ) + ) + (lam + n + a [ [ + c [ [ - MustMintValue - mph + [ + [ + MustMintValue + mph + ] + unitDatum + ] + tn ] - unitDatum + (con + integer + 1 + ) ] - tn ] - (con - integer - 1 - ) + n ] - ] - n - ] + ) + ) ) - ) - ) + ] + ] + { + Nil + [ + InputConstraint + Void + ] + } ] + { + Nil + [ + OutputConstraint + Void + ] + } ] - { - Nil - [ - InputConstraint - Void - ] - } ] - { - Nil - [ - OutputConstraint - Void - ] - } - ] - ] - [ - [ - { - State - GameState - } [ [ + { + State + GameState + } [ - Locked - mph + [ + [ + Locked + mph + ] + tn + ] + s ] - tn ] - s + ww ] ] - ww ] - ] + ) ] - ) - ] - (all - dead (type) dead + (all + dead + (type) + dead + ) + } ) - } + ) ) ) - ) - ) - ] - (lam - mph - (con bytestring) - (lam - tn - (con bytestring) + ] (lam - currentSecret + mph (con bytestring) - (abs - dead - (type) - { - [ - [ - { + (lam + tn + (con bytestring) + (lam + currentSecret + (con bytestring) + (abs + dead + (type) + { + [ [ - GameInput_match - w - ] - (all - dead - (type) - [ - Maybe + { [ + GameInput_match + w + ] + (all + dead + (type) [ - Tuple2 + Maybe [ [ - TxConstraints - Void - ] - Void - ] - ] - [ - State - GameState - ] - ] - ] - ) - } - (lam - theGuess - (con - bytestring - ) - (lam - nextSecret - (con - bytestring - ) - (lam - takenOut - [ - [ - (lam - k - (type) - (lam - v - (type) + Tuple2 [ - List [ - [ - Tuple2 - k - ] - v + TxConstraints + Void ] + Void ] - ) - ) - (con - bytestring - ) + ] + [ + State + GameState + ] + ] ] - [ + ) + } + (lam + theGuess + (con + bytestring + ) + (lam + nextSecret + (con + bytestring + ) + (lam + takenOut [ - (lam - k - (type) + [ (lam - v + k (type) - [ - List + (lam + v + (type) [ + List [ - Tuple2 - k + [ + Tuple2 + k + ] + v ] - v ] - ] + ) ) - ) - (con - bytestring - ) - ] - (con - integer - ) - ] - ] - (let - (nonrec) - (termbind - (nonstrict) - (vardecl - newValue + (con + bytestring + ) + ] [ [ (lam @@ -16851,382 +16846,458 @@ bytestring ) ] - [ + (con + integer + ) + ] + ] + (let + (nonrec) + (termbind + (nonstrict) + (vardecl + newValue [ - (lam - k - (type) + [ (lam - v + k (type) - [ - List + (lam + v + (type) [ + List [ - Tuple2 - k + [ + Tuple2 + k + ] + v ] - v ] - ] + ) ) - ) - (con - bytestring - ) - ] - (con - integer - ) - ] - ] - ) - [ - [ - [ - unionWith - addInteger - ] - ww - ] - [ - [ - fAdditiveGroupValue_cscale - (con - integer - -1 - ) - ] - takenOut - ] - ] - ) - (abs - dead - (type) - { - [ - [ - { + (con + bytestring + ) + ] [ - Bool_match [ - [ - [ - { - (builtin - ifThenElse - ) - Bool - } + (lam + k + (type) + (lam + v + (type) [ + List [ - (builtin - equalsByteString - ) - currentSecret - ] - [ - (builtin - sha2_256 - ) - theGuess + [ + Tuple2 + k + ] + v ] ] - ] - True - ] - False + ) + ) + (con + bytestring + ) ] + (con + integer + ) ] - (all - dead - (type) - [ - Maybe + ] + ) + [ + [ + [ + unionWith + addInteger + ] + ww + ] + [ + [ + fAdditiveGroupValue_cscale + (con + integer + -1 + ) + ] + takenOut + ] + ] + ) + (abs + dead + (type) + { + [ + [ + { [ + Bool_match [ - Tuple2 [ [ - TxConstraints - Void + { + (builtin + ifThenElse + ) + Bool + } + [ + [ + (builtin + equalsByteString + ) + currentSecret + ] + [ + (builtin + sha2_256 + ) + theGuess + ] + ] ] - Void + True ] - ] - [ - State - GameState + False ] ] - ] - ) - } - (abs - dead - (type) - [ - { - Just - [ + (all + dead + (type) [ - Tuple2 + Maybe [ [ - TxConstraints - Void + Tuple2 + [ + [ + TxConstraints + Void + ] + Void + ] + ] + [ + State + GameState ] - Void ] ] - [ - State - GameState - ] - ] + ) } - [ + (abs + dead + (type) [ { - { - Tuple2 + Just + [ [ + Tuple2 [ - TxConstraints + [ + TxConstraints + Void + ] Void ] - Void ] - } - [ - State - GameState + [ + State + GameState + ] ] } [ [ - [ + { { - { - TxConstraints + Tuple2 + [ + [ + TxConstraints + Void + ] Void - } - Void + ] } + [ + State + GameState + ] + } + [ [ [ - [ - { - { - foldr - TxConstraint - } - [ - List - TxConstraint - ] - } + { { - Cons - TxConstraint + TxConstraints + Void } - ] + Void + } [ - { - build - TxConstraint - } - (abs - a - (type) - (lam - c - (fun + [ + [ + { + { + foldr + TxConstraint + } + [ + List + TxConstraint + ] + } + { + Cons TxConstraint - (fun - a - a - ) - ) - (lam - n + } + ] + [ + { + build + TxConstraint + } + (abs a - [ - [ - c + (type) + (lam + c + (fun + TxConstraint + (fun + a + a + ) + ) + (lam + n + a [ [ + c [ [ - MustMintValue - mph + [ + [ + MustMintValue + mph + ] + unitDatum + ] + tn ] - unitDatum + (con + integer + 0 + ) ] - tn ] - (con - integer - 0 - ) + n ] - ] - n - ] + ) + ) ) - ) - ) - ] - ] - [ - { - build - TxConstraint - } - (abs - a - (type) - (lam - c - (fun + ] + ] + [ + { + build TxConstraint - (fun - a - a - ) - ) - (lam - n + } + (abs a - [ - [ - c + (type) + (lam + c + (fun + TxConstraint + (fun + a + a + ) + ) + (lam + n + a [ - MustSpendAtLeast [ + c [ - { - Cons - [ - [ - Tuple2 - (con - bytestring - ) - ] - [ - [ - (lam - k - (type) - (lam - v - (type) - [ - List - [ - [ - Tuple2 - k - ] - v - ] - ] - ) - ) - (con - bytestring - ) - ] - (con - integer - ) - ] - ] - } + MustSpendAtLeast [ [ { - { - Tuple2 - (con - bytestring - ) - } + Cons [ [ - (lam - k - (type) + Tuple2 + (con + bytestring + ) + ] + [ + [ (lam - v + k (type) - [ - List + (lam + v + (type) [ + List [ - Tuple2 - k + [ + Tuple2 + k + ] + v ] - v ] - ] + ) ) - ) + (con + bytestring + ) + ] (con - bytestring + integer ) ] - (con - integer - ) ] } - mph - ] - [ [ - { - Cons - [ - [ + [ + { + { Tuple2 (con bytestring ) + } + [ + [ + (lam + k + (type) + (lam + v + (type) + [ + List + [ + [ + Tuple2 + k + ] + v + ] + ] + ) + ) + (con + bytestring + ) + ] + (con + integer + ) ] - (con - integer - ) - ] - } + } + mph + ] [ [ { - { + Cons + [ + [ + Tuple2 + (con + bytestring + ) + ] + (con + integer + ) + ] + } + [ + [ + { + { + Tuple2 + (con + bytestring + ) + } + (con + integer + ) + } + tn + ] + (con + integer + 1 + ) + ] + ] + { + Nil + [ + [ Tuple2 (con bytestring ) - } + ] (con integer ) - } - tn - ] + ] + } + ] + ] + ] + { + Nil + [ + [ + Tuple2 (con - integer - 1 + bytestring ) ] - ] - { - Nil [ [ - Tuple2 + (lam + k + (type) + (lam + v + (type) + [ + List + [ + [ + Tuple2 + k + ] + v + ] + ] + ) + ) (con bytestring ) @@ -17235,213 +17306,284 @@ integer ) ] - } - ] - ] - ] - { - Nil - [ - [ - Tuple2 - (con - bytestring - ) - ] - [ - [ - (lam - k - (type) - (lam - v - (type) - [ - List - [ - [ - Tuple2 - k - ] - v - ] - ] - ) - ) - (con - bytestring - ) ] - (con - integer - ) - ] + } ] - } + ] ] + n ] - ] - n - ] + ) + ) ) - ) - ) + ] + ] ] - ] - ] - [ - [ [ - { + [ + [ + { + { + foldr + [ + InputConstraint + Void + ] + } + [ + List + [ + InputConstraint + Void + ] + ] + } + { + Cons + [ + InputConstraint + Void + ] + } + ] { - foldr + Nil [ InputConstraint Void ] } - [ - List - [ - InputConstraint - Void - ] - ] - } + ] { - Cons + Nil [ InputConstraint Void ] } ] - { - Nil - [ - InputConstraint - Void - ] - } ] - { - Nil - [ - InputConstraint - Void - ] - } - ] - ] - [ - [ [ - { - { - foldr - [ - OutputConstraint - Void - ] - } + [ [ - List + { + { + foldr + [ + OutputConstraint + Void + ] + } + [ + List + [ + OutputConstraint + Void + ] + ] + } + { + Cons + [ + OutputConstraint + Void + ] + } + ] + { + Nil [ OutputConstraint Void ] - ] - } + } + ] { - Cons + Nil [ OutputConstraint Void ] } ] - { - Nil - [ - OutputConstraint - Void - ] - } ] - { - Nil - [ - OutputConstraint - Void - ] - } ] - ] - ] - [ - [ - { - State - GameState - } - { + [ [ - [ - { + { + State + GameState + } + { + [ [ - Bool_match - [ - isZero + { [ + Bool_match [ - { - Cons + isZero + [ [ - [ - Tuple2 - (con - bytestring - ) - ] + { + Cons + [ + [ + Tuple2 + (con + bytestring + ) + ] + [ + [ + (lam + k + (type) + (lam + v + (type) + [ + List + [ + [ + Tuple2 + k + ] + v + ] + ] + ) + ) + (con + bytestring + ) + ] + (con + integer + ) + ] + ] + } [ [ - (lam - k - (type) - (lam - v - (type) + { + { + Tuple2 + (con + bytestring + ) + } + [ + [ + (lam + k + (type) + (lam + v + (type) + [ + List + [ + [ + Tuple2 + k + ] + v + ] + ] + ) + ) + (con + bytestring + ) + ] + (con + integer + ) + ] + } + (con + bytestring + # + ) + ] + [ + [ + { + Cons [ - List [ - [ + Tuple2 + (con + bytestring + ) + ] + (con + integer + ) + ] + } + [ + [ + { + { Tuple2 - k + (con + bytestring + ) + } + (con + integer + ) + } + (con + bytestring + # + ) + ] + [ + [ + [ + valueOf + newValue ] - v + (con + bytestring + # + ) ] + (con + bytestring + # + ) ] - ) - ) - (con - bytestring - ) + ] + ] + { + Nil + [ + [ + Tuple2 + (con + bytestring + ) + ] + (con + integer + ) + ] + } ] - (con - integer - ) ] ] - } - [ - [ - { - { + { + Nil + [ + [ Tuple2 (con bytestring ) - } + ] [ [ (lam @@ -17470,444 +17612,259 @@ integer ) ] - } - (con - bytestring - # - ) - ] - [ - [ - { - Cons - [ - [ - Tuple2 - (con - bytestring - ) - ] - (con - integer - ) - ] - } - [ - [ - { - { - Tuple2 - (con - bytestring - ) - } - (con - integer - ) - } - (con - bytestring - # - ) - ] - [ - [ - [ - valueOf - newValue - ] - (con - bytestring - # - ) - ] - (con - bytestring - # - ) - ] - ] ] - { - Nil - [ - [ - Tuple2 - (con - bytestring - ) - ] - (con - integer - ) - ] - } - ] + } ] ] - { - Nil - [ - [ - Tuple2 - (con - bytestring - ) - ] - [ - [ - (lam - k - (type) - (lam - v - (type) - [ - List - [ - [ - Tuple2 - k - ] - v - ] - ] - ) - ) - (con - bytestring - ) - ] - (con - integer - ) - ] - ] - } ] - ] + (all + dead + (type) + GameState + ) + } + (abs + dead + (type) + Finished + ) ] - (all + (abs dead (type) - GameState + [ + [ + [ + Locked + mph + ] + tn + ] + nextSecret + ] ) - } - (abs + ] + (all dead (type) - Finished + dead ) - ] - (abs - dead - (type) - [ - [ - [ - Locked - mph - ] - tn - ] - nextSecret - ] - ) + } ] - (all - dead - (type) - dead - ) - } + newValue + ] ] - newValue ] - ] + ) ] - ) - ] - (abs - dead - (type) - { - Nothing - [ - [ - Tuple2 + (abs + dead + (type) + { + Nothing [ [ - TxConstraints - Void + Tuple2 + [ + [ + TxConstraints + Void + ] + Void + ] + ] + [ + State + GameState ] - Void ] - ] - [ - State - GameState - ] - ] - } - ) - ] - (all - dead - (type) - dead + } + ) + ] + (all + dead + (type) + dead + ) + } ) - } + ) ) ) ) - ) - ) - ] - (abs - dead - (type) - { - Nothing - [ - [ - Tuple2 + ] + (abs + dead + (type) + { + Nothing [ [ - TxConstraints - Void + Tuple2 + [ + [ + TxConstraints + Void + ] + Void + ] + ] + [ + State + GameState ] - Void ] - ] - [ - State - GameState - ] - ] - } - ) - ] - (all - dead (type) dead + } + ) + ] + (all + dead + (type) + dead + ) + } ) - } + ) ) ) - ) - ) - ] - (all dead (type) dead) - } - ) + ] + (all dead (type) dead) + } + ) + ) + ] ) - ] - ) - ) - ] - (lam - ds - GameState - { - [ - [ + ) + ] + (lam + ds + GameState + { [ - { - [ GameState_match ds ] - (all dead (type) Bool) - } - (abs dead (type) True) - ] - (lam - default_arg0 - (con bytestring) - (lam - default_arg1 - (con bytestring) + [ + [ + { + [ GameState_match ds ] + (all dead (type) Bool) + } + (abs dead (type) True) + ] (lam - default_arg2 + default_arg0 (con bytestring) - (abs dead (type) False) + (lam + default_arg1 + (con bytestring) + (lam + default_arg2 + (con bytestring) + (abs dead (type) False) + ) + ) ) - ) - ) - ] - (lam - default_arg0 - (con bytestring) - (lam - default_arg1 - (con bytestring) + ] (lam - default_arg2 + default_arg0 (con bytestring) - (abs dead (type) False) + (lam + default_arg1 + (con bytestring) + (lam + default_arg2 + (con bytestring) + (abs dead (type) False) + ) + ) ) - ) - ) - ] - (all dead (type) dead) - } - ) + ] + (all dead (type) dead) + } + ) + ] + (lam + ds + GameState + (lam + ds GameInput (lam ds ScriptContext True) + ) + ) + ] + { Nothing ThreadToken } ] - (lam - ds - GameState - (lam ds GameInput (lam ds ScriptContext True)) - ) - ] - { Nothing ThreadToken } - ] - ) - (lam - w - GameState - (lam - w - GameInput + ) (lam w - ScriptContext - [ - { + GameState + (lam + w + GameInput + (lam + w + ScriptContext [ { - { StateMachine_match GameState } - GameInput - } - w - ] - Bool - } - (lam - ww - (fun - [ State GameState ] - (fun - GameInput [ - Maybe - [ + { + { StateMachine_match GameState } + GameInput + } + w + ] + Bool + } + (lam + ww + (fun + [ State GameState ] + (fun + GameInput [ - Tuple2 - [ [ TxConstraints Void ] Void ] + Maybe + [ + [ + Tuple2 + [ + [ TxConstraints Void ] Void + ] + ] + [ State GameState ] + ] ] - [ State GameState ] - ] - ] - ) - ) - (lam - ww - (fun GameState Bool) - (lam - ww - (fun - GameState - (fun - GameInput (fun ScriptContext Bool) ) ) (lam ww - [ Maybe ThreadToken ] - [ - [ + (fun GameState Bool) + (lam + ww + (fun + GameState + (fun + GameInput + (fun ScriptContext Bool) + ) + ) + (lam + ww + [ Maybe ThreadToken ] [ - (lam - w - GameState - (lam - w - GameInput + [ + [ (lam w - ScriptContext - (let - (nonrec) - (termbind - (nonstrict) - (vardecl - vl - [ - [ - (lam - k - (type) - (lam - v - (type) - [ - List - [ - [ - Tuple2 - k - ] - v - ] - ] - ) - ) - (con bytestring) - ] - [ - [ - (lam - k - (type) - (lam - v - (type) - [ - List - [ - [ - Tuple2 - k - ] - v - ] - ] - ) - ) - (con - bytestring - ) - ] - (con integer) - ] - ] - ) - [ - { - [ - ScriptContext_match - w - ] - [ - [ - (lam - k - (type) - (lam - v - (type) - [ - List - [ - [ - Tuple2 - k - ] - v - ] - ] - ) - ) - (con - bytestring - ) - ] + GameState + (lam + w + GameInput + (lam + w + ScriptContext + (let + (nonrec) + (termbind + (nonstrict) + (vardecl + vl [ [ (lam @@ -17932,21 +17889,65 @@ bytestring ) ] - (con integer) + [ + [ + (lam + k + (type) + (lam + v + (type) + [ + List + [ + [ + Tuple2 + k + ] + v + ] + ] + ) + ) + (con + bytestring + ) + ] + (con + integer + ) + ] ] - ] - } - (lam - ww - TxInfo - (lam - ww - ScriptPurpose - [ - { + ) + [ + { + [ + ScriptContext_match + w + ] + [ [ - TxInfo_match - ww + (lam + k + (type) + (lam + v + (type) + [ + List + [ + [ + Tuple2 + k + ] + v + ] + ] + ) + ) + (con + bytestring + ) ] [ [ @@ -17972,50 +17973,24 @@ bytestring ) ] - [ - [ - (lam - k - (type) - (lam - v - (type) - [ - List - [ - [ - Tuple2 - k - ] - v - ] - ] - ) - ) - (con - bytestring - ) - ] - (con - integer - ) - ] + (con + integer + ) ] - } + ] + } + (lam + ww + TxInfo (lam ww + ScriptPurpose [ - List - TxInInfo - ] - (lam - ww - [ - List - TxOut - ] - (lam - ww + { + [ + TxInfo_match + ww + ] [ [ (lam @@ -18069,32 +18044,21 @@ ) ] ] + } + (lam + ww + [ + List + TxInInfo + ] (lam ww - [ - [ - (lam - k - (type) - (lam - v - (type) - [ - List - [ - [ - Tuple2 - k - ] - v - ] - ] - ) - ) - (con - bytestring - ) - ] + [ + List + TxOut + ] + (lam + ww [ [ (lam @@ -18119,25 +18083,84 @@ bytestring ) ] - (con - integer - ) - ] - ] - (lam - ww - [ - List - DCert + [ + [ + (lam + k + (type) + (lam + v + (type) + [ + List + [ + [ + Tuple2 + k + ] + v + ] + ] + ) + ) + (con + bytestring + ) + ] + (con + integer + ) + ] ] (lam ww [ - List + [ + (lam + k + (type) + (lam + v + (type) + [ + List + [ + [ + Tuple2 + k + ] + v + ] + ] + ) + ) + (con + bytestring + ) + ] [ [ - Tuple2 - StakingCredential + (lam + k + (type) + (lam + v + (type) + [ + List + [ + [ + Tuple2 + k + ] + v + ] + ] + ) + ) + (con + bytestring + ) ] (con integer @@ -18147,127 +18170,80 @@ (lam ww [ - Interval - (con - integer - ) + List + DCert ] (lam ww [ List - (con - bytestring - ) + [ + [ + Tuple2 + StakingCredential + ] + (con + integer + ) + ] ] (lam ww [ - List + Interval + (con + integer + ) + ] + (lam + ww [ - [ - Tuple2 - (con - bytestring - ) - ] + List (con - data + bytestring ) ] - ] - (lam - ww - (con - bytestring - ) - { + (lam + ww [ + List [ - { + [ + Tuple2 + (con + bytestring + ) + ] + (con + data + ) + ] + ] + (lam + ww + (con + bytestring + ) + { + [ [ { - Maybe_match - TxInInfo - } - [ - [ - wfindOwnInput - ww - ] - ww - ] - ] - (all - dead - (type) - [ - [ - (lam - k - (type) - (lam - v - (type) - [ - List - [ - [ - Tuple2 - k - ] - v - ] - ] - ) - ) - (con - bytestring - ) - ] [ + { + Maybe_match + TxInInfo + } [ - (lam - k - (type) - (lam - v - (type) - [ - List - [ - [ - Tuple2 - k - ] - v - ] - ] - ) - ) - (con - bytestring - ) + [ + wfindOwnInput + ww + ] + ww ] - (con - integer - ) ] - ] - ) - } - (lam - a - TxInInfo - (abs - dead - (type) - [ - { - [ - TxInInfo_match - a - ] + (all + dead + (type) [ [ (lam @@ -18321,18 +18297,43 @@ ) ] ] - } - (lam - ds - TxOutRef - (lam - ds - TxOut - [ - { + ) + } + (lam + a + TxInInfo + (abs + dead + (type) + [ + { + [ + TxInInfo_match + a + ] + [ [ - TxOut_match - ds + (lam + k + (type) + (lam + v + (type) + [ + List + [ + [ + Tuple2 + k + ] + v + ] + ] + ) + ) + (con + bytestring + ) ] [ [ @@ -18358,64 +18359,23 @@ bytestring ) ] - [ - [ - (lam - k - (type) - (lam - v - (type) - [ - List - [ - [ - Tuple2 - k - ] - v - ] - ] - ) - ) - (con - bytestring - ) - ] - (con - integer - ) - ] + (con + integer + ) ] - } + ] + } + (lam + ds + TxOutRef (lam ds - Address - (lam - ds - [ + TxOut + [ + { [ - (lam - k - (type) - (lam - v - (type) - [ - List - [ - [ - Tuple2 - k - ] - v - ] - ] - ) - ) - (con - bytestring - ) + TxOut_match + ds ] [ [ @@ -18441,128 +18401,213 @@ bytestring ) ] - (con - integer - ) + [ + [ + (lam + k + (type) + (lam + v + (type) + [ + List + [ + [ + Tuple2 + k + ] + v + ] + ] + ) + ) + (con + bytestring + ) + ] + (con + integer + ) + ] ] - ] + } (lam ds - [ - Maybe - (con - bytestring + Address + (lam + ds + [ + [ + (lam + k + (type) + (lam + v + (type) + [ + List + [ + [ + Tuple2 + k + ] + v + ] + ] + ) + ) + (con + bytestring + ) + ] + [ + [ + (lam + k + (type) + (lam + v + (type) + [ + List + [ + [ + Tuple2 + k + ] + v + ] + ] + ) + ) + (con + bytestring + ) + ] + (con + integer + ) + ] + ] + (lam + ds + [ + Maybe + (con + bytestring + ) + ] + ds ) - ] - ds + ) ) - ) + ] ) - ] - ) + ) + ] ) - ] - ) - ) - ] - (abs - dead - (type) - [ - { - error + ) + ] + (abs + dead + (type) [ - [ - (lam - k - (type) - (lam - v - (type) - [ - List - [ + { + error + [ + [ + (lam + k + (type) + (lam + v + (type) [ - Tuple2 - k + List + [ + [ + Tuple2 + k + ] + v + ] ] - v - ] + ) + ) + (con + bytestring + ) + ] + [ + [ + (lam + k + (type) + (lam + v + (type) + [ + List + [ + [ + Tuple2 + k + ] + v + ] + ] + ) + ) + (con + bytestring + ) ] - ) - ) - (con - bytestring - ) - ] + (con + integer + ) + ] + ] + } [ - [ - (lam - k - (type) - (lam - v - (type) + { + [ + Unit_match + [ [ - List - [ - [ - Tuple2 - k - ] - v - ] + { + (builtin + trace + ) + Unit + } + (con + string + "S0" + ) ] - ) - ) + Unit + ] + ] (con - bytestring + unit ) - ] + } (con - integer + unit + () ) ] ] - } - [ - { - [ - Unit_match - [ - [ - { - (builtin - trace - ) - Unit - } - (con - string - "S0" - ) - ] - Unit - ] - ] - (con - unit - ) - } - (con - unit - () - ) - ] + ) ] - ) - ] - (all - dead - (type) - dead + (all + dead + (type) + dead + ) + } ) - } + ) ) ) ) @@ -18571,569 +18616,527 @@ ) ) ) - ) + ] ) - ] - ) + ) + ] ) - ] - ) - (termbind - (nonstrict) - (vardecl j Bool) - { - [ - [ - { + (termbind + (nonstrict) + (vardecl j Bool) + { + [ [ { - Maybe_match [ - [ - Tuple2 + { + Maybe_match [ [ - TxConstraints - Void + Tuple2 + [ + [ + TxConstraints + Void + ] + Void + ] ] - Void - ] - ] - [ - State - GameState - ] - ] - } - [ - [ - ww - [ - [ - { + [ State GameState - } - w + ] ] + } + [ [ + ww [ [ - unionWith - addInteger - ] - vl - ] - [ - [ - fAdditiveGroupValue_cscale - (con - integer - -1 - ) + { + State + GameState + } + w ] [ [ - threadTokenValueInner - ww + [ + unionWith + addInteger + ] + vl ] [ - ownHash - w + [ + fAdditiveGroupValue_cscale + (con + integer + -1 + ) + ] + [ + [ + threadTokenValueInner + ww + ] + [ + ownHash + w + ] + ] ] ] ] ] + w ] ] - w - ] - ] - (all - dead - (type) - Bool - ) - } - (lam - ds - [ - [ - Tuple2 + (all + dead + (type) + Bool + ) + } + (lam + ds [ [ - TxConstraints - Void - ] - Void - ] - ] - [ - State - GameState - ] - ] - (abs - dead - (type) - [ - { - [ - { - { - Tuple2_match - [ - [ - TxConstraints - Void - ] - Void - ] - } + Tuple2 + [ [ - State - GameState + TxConstraints + Void ] - } - ds - ] - Bool - } - (lam - newConstraints - [ - [ - TxConstraints Void ] - Void ] - (let - (nonrec) - (termbind - (nonstrict) - (vardecl - j - Bool - ) + [ + State + GameState + ] + ] + (abs + dead + (type) + [ + { [ { - [ - { - { - TxConstraints_match + { + Tuple2_match + [ + [ + TxConstraints Void - } + ] Void - } - newConstraints + ] + } + [ + State + GameState ] - Bool } - (lam - ww + ds + ] + Bool + } + (lam + newConstraints + [ + [ + TxConstraints + Void + ] + Void + ] + (let + (nonrec) + (termbind + (nonstrict) + (vardecl + j + Bool + ) [ - List - TxConstraint - ] - (lam - ww - [ - List + { [ - InputConstraint - Void + { + { + TxConstraints_match + Void + } + Void + } + newConstraints ] - ] + Bool + } (lam ww [ List - [ - OutputConstraint - Void - ] + TxConstraint ] - { + (lam + ww [ + List [ - { + InputConstraint + Void + ] + ] + (lam + ww + [ + List + [ + OutputConstraint + Void + ] + ] + { + [ [ - Bool_match - [ + { [ + Bool_match [ [ [ - { - { - wcheckScriptContext - Void - } - Void - } - (lam - a - Void - { - [ - Void_match + [ + [ + { + { + wcheckScriptContext + Void + } + Void + } + (lam a - ] - (con - data + Void + { + [ + Void_match + a + ] + (con + data + ) + } ) - } - ) + ] + ww + ] + ww ] ww ] - ww + w ] - ww ] - w - ] + (all + dead + (type) + Bool + ) + } + (abs + dead + (type) + True + ) ] - (all + (abs dead (type) - Bool + [ + [ + { + (builtin + trace + ) + Bool + } + (con + string + "S4" + ) + ] + False + ] ) - } - (abs + ] + (all dead (type) - True + dead ) - ] - (abs - dead - (type) - [ - [ - { - (builtin - trace - ) - Bool - } - (con - string - "S4" - ) - ] - False - ] - ) - ] - (all - dead - (type) - dead + } ) - } + ) ) - ) - ) - ] - ) - (lam - ds - [ - State - GameState - ] - [ - { - [ - { - State_match - GameState - } - ds ] - Bool - } + ) (lam ds - GameState - (lam - ds - [ + [ + State + GameState + ] + [ + { [ - (lam - k - (type) - (lam - v - (type) - [ - List - [ - [ - Tuple2 - k - ] - v - ] - ] - ) - ) - (con - bytestring - ) + { + State_match + GameState + } + ds ] - [ + Bool + } + (lam + ds + GameState + (lam + ds [ - (lam - k - (type) + [ (lam - v + k (type) - [ - List + (lam + v + (type) [ + List [ - Tuple2 - k + [ + Tuple2 + k + ] + v ] - v - ] - ] - ) - ) - (con - bytestring - ) - ] - (con - integer - ) - ] - ] - { - [ - [ - { - [ - Bool_match - [ - ww - ds - ] - ] - (all - dead - (type) - Bool - ) - } - (abs - dead - (type) - { - [ - [ - { + ] + ) + ) + (con + bytestring + ) + ] + [ + [ + (lam + k + (type) + (lam + v + (type) + [ + List [ - Bool_match [ - isZero - ds + Tuple2 + k ] + v ] - (all - dead - (type) - Bool - ) - } - (abs - dead - (type) - j - ) + ] + ) + ) + (con + bytestring + ) + ] + (con + integer + ) + ] + ] + { + [ + [ + { + [ + Bool_match + [ + ww + ds + ] ] - (abs + (all dead (type) - { + Bool + ) + } + (abs + dead + (type) + { + [ [ - [ - { + { + [ + Bool_match [ - Bool_match - [ - [ - { - (builtin - trace - ) - Bool - } - (con - string - "S3" - ) - ] - False - ] + isZero + ds ] - (all - dead - (type) - Bool - ) - } - (abs + ] + (all dead (type) - j + Bool ) - ] + } (abs dead (type) - False + j ) ] - (all + (abs dead (type) - dead + { + [ + [ + { + [ + Bool_match + [ + [ + { + (builtin + trace + ) + Bool + } + (con + string + "S3" + ) + ] + False + ] + ] + (all + dead + (type) + Bool + ) + } + (abs + dead + (type) + j + ) + ] + (abs + dead + (type) + False + ) + ] + (all + dead + (type) + dead + ) + } ) - } - ) - ] - (all - dead - (type) - dead + ] + (all + dead + (type) + dead + ) + } ) - } - ) - ] - (abs - dead - (type) - [ - { + ] + (abs + dead + (type) [ { - { - TxConstraints_match - Void - } - Void - } - newConstraints - ] - Bool - } - (lam - ds - [ - List - TxConstraint - ] - (lam - ds - [ - List [ - InputConstraint - Void + { + { + TxConstraints_match + Void + } + Void + } + newConstraints ] - ] + Bool + } (lam ds [ List - [ - OutputConstraint - Void - ] + TxConstraint ] - { + (lam + ds [ + List [ - { + InputConstraint + Void + ] + ] + (lam + ds + [ + List + [ + OutputConstraint + Void + ] + ] + { + [ [ - Bool_match - [ + { [ + Bool_match [ [ [ - { - { - wcheckScriptContext - Void - } - GameState - } - (lam - ds - GameState - { - [ - [ + [ + [ + { + { + wcheckScriptContext + Void + } + GameState + } + (lam + ds + GameState + { [ - { - [ - GameState_match - ds - ] - (all - dead - (type) - (con - data - ) - ) - } - (abs - dead - (type) + [ [ - [ - (builtin - constrData - ) - (con - integer - 2 - ) - ] - [ - (builtin - mkNilData - ) - (con - unit - () + { + [ + GameState_match + ds + ] + (all + dead + (type) + (con + data + ) ) - ] - ] - ) - ] - (lam - arg - (con - bytestring - ) - (lam - arg - (con - bytestring - ) - (lam - arg - (con - bytestring - ) + } (abs dead (type) @@ -19144,42 +19147,48 @@ ) (con integer - 0 + 2 ) ] [ + (builtin + mkNilData + ) + (con + unit + () + ) + ] + ] + ) + ] + (lam + arg + (con + bytestring + ) + (lam + arg + (con + bytestring + ) + (lam + arg + (con + bytestring + ) + (abs + dead + (type) [ - { + [ (builtin - mkCons + constrData ) (con - data - ) - } - [ - (builtin - bData + integer + 0 ) - arg - ] - ] - [ - [ - { - (builtin - mkCons - ) - (con - data - ) - } - [ - (builtin - bData - ) - arg - ] ] [ [ @@ -19199,84 +19208,84 @@ ] ] [ - (builtin - mkNilData - ) - (con - unit - () - ) + [ + { + (builtin + mkCons + ) + (con + data + ) + } + [ + (builtin + bData + ) + arg + ] + ] + [ + [ + { + (builtin + mkCons + ) + (con + data + ) + } + [ + (builtin + bData + ) + arg + ] + ] + [ + (builtin + mkNilData + ) + (con + unit + () + ) + ] + ] ] ] ] - ] - ] + ) + ) ) ) - ) - ) - ] - (lam - arg - (con - bytestring - ) - (lam - arg - (con - bytestring - ) + ] (lam arg (con bytestring ) - (abs - dead - (type) - [ - [ - (builtin - constrData - ) - (con - integer - 1 - ) - ] - [ + (lam + arg + (con + bytestring + ) + (lam + arg + (con + bytestring + ) + (abs + dead + (type) [ - { + [ (builtin - mkCons + constrData ) (con - data - ) - } - [ - (builtin - bData + integer + 1 ) - arg - ] - ] - [ - [ - { - (builtin - mkCons - ) - (con - data - ) - } - [ - (builtin - bData - ) - arg - ] ] [ [ @@ -19296,452 +19305,501 @@ ] ] [ - (builtin - mkNilData - ) - (con - unit - () - ) + [ + { + (builtin + mkCons + ) + (con + data + ) + } + [ + (builtin + bData + ) + arg + ] + ] + [ + [ + { + (builtin + mkCons + ) + (con + data + ) + } + [ + (builtin + bData + ) + arg + ] + ] + [ + (builtin + mkNilData + ) + (con + unit + () + ) + ] + ] ] ] ] - ] - ] + ) + ) ) ) + ] + (all + dead + (type) + dead ) - ) - ] - (all - dead - (type) - dead + } ) - } - ) + ] + ds + ] + ds ] - ds - ] - ds - ] - [ - { - build [ - OutputConstraint - GameState - ] - } - (abs - a - (type) - (lam - c - (fun + { + build [ OutputConstraint GameState ] - (fun - a - a - ) - ) - (lam - n + } + (abs a - [ - [ - c + (type) + (lam + c + (fun + [ + OutputConstraint + GameState + ] + (fun + a + a + ) + ) + (lam + n + a [ [ - { - OutputConstraint - GameState - } - ds - ] - [ - [ - [ - unionWith - addInteger - ] - ds - ] + c [ [ - threadTokenValueInner - ww + { + OutputConstraint + GameState + } + ds ] [ - ownHash - w + [ + [ + unionWith + addInteger + ] + ds + ] + [ + [ + threadTokenValueInner + ww + ] + [ + ownHash + w + ] + ] ] ] ] + n ] - ] - n - ] + ) + ) ) - ) - ) + ] + ] + w ] ] - w - ] + (all + dead + (type) + Bool + ) + } + (abs + dead + (type) + True + ) ] - (all + (abs dead (type) - Bool + [ + [ + { + (builtin + trace + ) + Bool + } + (con + string + "S5" + ) + ] + False + ] ) - } - (abs + ] + (all dead (type) - True + dead ) - ] - (abs - dead - (type) - [ - [ - { - (builtin - trace - ) - Bool - } - (con - string - "S5" - ) - ] - False - ] - ) - ] - (all - dead - (type) - dead + } ) - } + ) ) - ) + ] ) ] - ) - ] - (all - dead - (type) - dead + (all + dead + (type) + dead + ) + } ) - } - ) + ) + ] ) - ] + ) ) - ) + ] ) + ) + ] + (abs + dead + (type) + [ + [ + { + (builtin + trace + ) + Bool + } + (con + string + "S6" + ) + ] + False ] ) + ] + (all + dead + (type) + dead ) - ] - (abs - dead - (type) + } + ) + (termbind + (nonstrict) + (vardecl j Bool) + { [ [ { - (builtin - trace + [ + { + Maybe_match + ThreadToken + } + ww + ] + (all + dead + (type) + Bool ) - Bool - } - (con - string - "S6" - ) - ] - False - ] - ) - ] - (all - dead (type) dead - ) - } - ) - (termbind - (nonstrict) - (vardecl j Bool) - { - [ - [ - { - [ - { - Maybe_match - ThreadToken } - ww - ] - (all - dead - (type) - Bool - ) - } - (lam - threadToken - ThreadToken - (abs - dead - (type) - { - [ - [ - { - [ - Bool_match - [ - [ - [ - { - (builtin - ifThenElse - ) - Bool - } - [ - [ - (builtin - equalsInteger - ) - [ - [ - [ - valueOf - vl - ] - [ - { - [ - ThreadToken_match - threadToken - ] - (con - bytestring - ) - } - (lam - ds - TxOutRef - (lam - ds - (con - bytestring - ) - ds - ) - ) - ] - ] - [ - ownHash - w - ] - ] - ] - (con - integer - 1 - ) - ] - ] - True - ] - False - ] - ] - (all - dead - (type) - Bool - ) - } - (abs - dead - (type) - j - ) - ] - (abs - dead - (type) - { + (lam + threadToken + ThreadToken + (abs + dead + (type) + { + [ [ - [ - { + { + [ + Bool_match [ - Bool_match [ [ { (builtin - trace + ifThenElse ) Bool } - (con - string - "S2" - ) + [ + [ + (builtin + equalsInteger + ) + [ + [ + [ + valueOf + vl + ] + [ + { + [ + ThreadToken_match + threadToken + ] + (con + bytestring + ) + } + (lam + ds + TxOutRef + (lam + ds + (con + bytestring + ) + ds + ) + ) + ] + ] + [ + ownHash + w + ] + ] + ] + (con + integer + 1 + ) + ] ] - False + True ] + False ] - (all - dead - (type) - Bool - ) - } - (abs + ] + (all dead (type) - j + Bool ) - ] + } (abs dead (type) - False + j ) ] - (all + (abs dead (type) - dead + { + [ + [ + { + [ + Bool_match + [ + [ + { + (builtin + trace + ) + Bool + } + (con + string + "S2" + ) + ] + False + ] + ] + (all + dead + (type) + Bool + ) + } + (abs + dead + (type) + j + ) + ] + (abs + dead + (type) + False + ) + ] + (all + dead + (type) + dead + ) + } ) - } - ) - ] - (all - dead - (type) - dead + ] + (all + dead + (type) + dead + ) + } ) - } - ) - ) - ] - (abs - dead (type) j - ) - ] - (all - dead (type) dead - ) - } - ) - { - [ - [ - { - [ - Bool_match - [ - [ - [ ww w ] w - ] - w + ) ] + (abs + dead + (type) + j + ) ] (all dead (type) - Bool + dead ) } - (abs - dead (type) j - ) - ] - (abs - dead - (type) - { + ) + { + [ [ - [ - { + { + [ + Bool_match [ - Bool_match [ [ - { - (builtin - trace - ) - Bool - } - (con - string - "S1" - ) + ww w ] - False + w ] + w ] - (all - dead - (type) - Bool - ) - } - (abs + ] + (all dead (type) - j + Bool ) - ] + } (abs dead (type) - False + j ) ] - (all + (abs dead (type) - dead + { + [ + [ + { + [ + Bool_match + [ + [ + { + (builtin + trace + ) + Bool + } + (con + string + "S1" + ) + ] + False + ] + ] + (all + dead + (type) + Bool + ) + } + (abs + dead + (type) + j + ) + ] + (abs + dead + (type) + False + ) + ] + (all + dead + (type) + dead + ) + } ) - } - ) - ] - (all dead (type) dead) - } + ] + (all + dead (type) dead + ) + } + ) + ) ) ) - ) - ) + w + ] + w + ] w ] - w - ] - w - ] + ) + ) ) ) - ) + ] ) - ] + ) ) ) ) diff --git a/plutus-use-cases/test/Spec/renderGuess.txt b/plutus-use-cases/test/Spec/renderGuess.txt index 67547c50dc..e5c7e32b85 100644 --- a/plutus-use-cases/test/Spec/renderGuess.txt +++ b/plutus-use-cases/test/Spec/renderGuess.txt @@ -101,11 +101,11 @@ Balances Carried Forward: Ada: Lovelace: 100000000 ==== Slot #1, Tx #0 ==== -TxId: 6b753350696782a1b24dfe7ec0549bf1e8d86cd08e5ad4d343ceca646f49f457 +TxId: 5d8ce06e40bb3358a57448bc596baba92d74015c17f1f1962073be7b3577ca90 Fee: Ada: Lovelace: 10 Mint: - Signatures PubKey: 8d9de88fbf445b7f6c3875a14daba94caee2ffcb... - Signature: 5840b6ec0478f7e38365d4c5f842760b7b440b05... + Signature: 5840e3d3e7e18681d4de6714e1dddbcb185fb158... Inputs: ---- Input 0 ---- Destination: PaymentPubKeyHash: a2c20c77887ace1cd986193e4e75babd8993cfd5... (Wallet 872cb83b5ee40eb23bfdab1772660c822a48d491) @@ -124,7 +124,7 @@ Outputs: Ada: Lovelace: 91999990 ---- Output 1 ---- - Destination: Script: 21927cbad33338d4eae6141407bf783b198aa7e55dd9089dc73c8d1d + Destination: Script: e39b4969cde4623e3bbc488dcee1e1820c00c2b69df67248769aff40 Value: Ada: Lovelace: 8000000 @@ -170,51 +170,51 @@ Balances Carried Forward: Value: Ada: Lovelace: 100000000 - Script: 21927cbad33338d4eae6141407bf783b198aa7e55dd9089dc73c8d1d + Script: e39b4969cde4623e3bbc488dcee1e1820c00c2b69df67248769aff40 Value: Ada: Lovelace: 8000000 ==== Slot #2, Tx #0 ==== -TxId: f02f6bdb4e032c86578adc0c8441b15ccb1033c9cc43cc71d17d689e5d107fd3 -Fee: Ada: Lovelace: 14170 -Mint: 9b2c45472487bc82ae575fc57a338b1fa4f6a47e536bdd57f864c46c: guess: 1 +TxId: a0e68431d8b133d45a5e2e1ab2a8b12d1bf3ab6c03d7bab6a1f4f0a24502e299 +Fee: Ada: Lovelace: 14227 +Mint: a00668ced9003f5b42834072802daeec9a7dd1eb777662a161f2ab06: guess: 1 Signatures PubKey: 8d9de88fbf445b7f6c3875a14daba94caee2ffcb... - Signature: 584010f5e66630e0125bf97d894eb6b84fd0ad11... + Signature: 58406bc25ab56d4c5f82c3062827c2610124c621... Inputs: ---- Input 0 ---- Destination: PaymentPubKeyHash: a2c20c77887ace1cd986193e4e75babd8993cfd5... (Wallet 872cb83b5ee40eb23bfdab1772660c822a48d491) Value: Ada: Lovelace: 91999990 Source: - Tx: 6b753350696782a1b24dfe7ec0549bf1e8d86cd08e5ad4d343ceca646f49f457 + Tx: 5d8ce06e40bb3358a57448bc596baba92d74015c17f1f1962073be7b3577ca90 Output #0 ---- Input 1 ---- - Destination: Script: 21927cbad33338d4eae6141407bf783b198aa7e55dd9089dc73c8d1d + Destination: Script: e39b4969cde4623e3bbc488dcee1e1820c00c2b69df67248769aff40 Value: Ada: Lovelace: 8000000 Source: - Tx: 6b753350696782a1b24dfe7ec0549bf1e8d86cd08e5ad4d343ceca646f49f457 + Tx: 5d8ce06e40bb3358a57448bc596baba92d74015c17f1f1962073be7b3577ca90 Output #1 - Script: 59dba60100003323232332233322233322233332... + Script: 59dd450100003323232332233322233322233332... Outputs: ---- Output 0 ---- Destination: PaymentPubKeyHash: a2c20c77887ace1cd986193e4e75babd8993cfd5... (Wallet 872cb83b5ee40eb23bfdab1772660c822a48d491) Value: - Ada: Lovelace: 89985820 - 9b2c45472487bc82ae575fc57a338b1fa4f6a47e536bdd57f864c46c: - + Ada: Lovelace: 89985763 + a00668ced9003f5b42834072802daeec9a7dd1eb777662a161f2ab06: - ---- Output 1 ---- Destination: PaymentPubKeyHash: a2c20c77887ace1cd986193e4e75babd8993cfd5... (Wallet 872cb83b5ee40eb23bfdab1772660c822a48d491) Value: - 9b2c45472487bc82ae575fc57a338b1fa4f6a47e536bdd57f864c46c: guess: 1 + a00668ced9003f5b42834072802daeec9a7dd1eb777662a161f2ab06: guess: 1 Ada: Lovelace: 2000000 ---- Output 2 ---- - Destination: Script: 21927cbad33338d4eae6141407bf783b198aa7e55dd9089dc73c8d1d + Destination: Script: e39b4969cde4623e3bbc488dcee1e1820c00c2b69df67248769aff40 Value: Ada: Lovelace: 8000000 @@ -242,8 +242,8 @@ Balances Carried Forward: PaymentPubKeyHash: a2c20c77887ace1cd986193e4e75babd8993cfd5... (Wallet 872cb83b5ee40eb23bfdab1772660c822a48d491) Value: - Ada: Lovelace: 91985820 - 9b2c45472487bc82ae575fc57a338b1fa4f6a47e536bdd57f864c46c: guess: 1 + Ada: Lovelace: 91985763 + a00668ced9003f5b42834072802daeec9a7dd1eb777662a161f2ab06: guess: 1 PaymentPubKeyHash: a96a668ed7be83e332c872f51da7925b4472ca98... (Wallet bdf8dbca0cadeb365480c6ec29ec746a2b85274f) Value: @@ -261,34 +261,34 @@ Balances Carried Forward: Value: Ada: Lovelace: 100000000 - Script: 21927cbad33338d4eae6141407bf783b198aa7e55dd9089dc73c8d1d + Script: e39b4969cde4623e3bbc488dcee1e1820c00c2b69df67248769aff40 Value: Ada: Lovelace: 8000000 ==== Slot #3, Tx #0 ==== -TxId: ee4d350e115107d177d6f66c3ee6f1008474b306f90cc4c5519f654b7f9ce07d +TxId: 5f874f7ee33c30397e64c805c17b1944c092645aa3ff771e5ab6342359bbeb28 Fee: Ada: Lovelace: 10 Mint: - Signatures PubKey: 8d9de88fbf445b7f6c3875a14daba94caee2ffcb... - Signature: 58408db3d868a57af927ff3d5339f3e475ddcffb... + Signature: 58409c4bb056f390371190842eaf47b0922fe1b1... Inputs: ---- Input 0 ---- Destination: PaymentPubKeyHash: a2c20c77887ace1cd986193e4e75babd8993cfd5... (Wallet 872cb83b5ee40eb23bfdab1772660c822a48d491) Value: - Ada: Lovelace: 89985820 - 9b2c45472487bc82ae575fc57a338b1fa4f6a47e536bdd57f864c46c: - + Ada: Lovelace: 89985763 + a00668ced9003f5b42834072802daeec9a7dd1eb777662a161f2ab06: - Source: - Tx: f02f6bdb4e032c86578adc0c8441b15ccb1033c9cc43cc71d17d689e5d107fd3 + Tx: a0e68431d8b133d45a5e2e1ab2a8b12d1bf3ab6c03d7bab6a1f4f0a24502e299 Output #0 ---- Input 1 ---- Destination: PaymentPubKeyHash: a2c20c77887ace1cd986193e4e75babd8993cfd5... (Wallet 872cb83b5ee40eb23bfdab1772660c822a48d491) Value: - 9b2c45472487bc82ae575fc57a338b1fa4f6a47e536bdd57f864c46c: guess: 1 + a00668ced9003f5b42834072802daeec9a7dd1eb777662a161f2ab06: guess: 1 Ada: Lovelace: 2000000 Source: - Tx: f02f6bdb4e032c86578adc0c8441b15ccb1033c9cc43cc71d17d689e5d107fd3 + Tx: a0e68431d8b133d45a5e2e1ab2a8b12d1bf3ab6c03d7bab6a1f4f0a24502e299 Output #1 @@ -297,13 +297,13 @@ Outputs: ---- Output 0 ---- Destination: PaymentPubKeyHash: a2c20c77887ace1cd986193e4e75babd8993cfd5... (Wallet 872cb83b5ee40eb23bfdab1772660c822a48d491) Value: - Ada: Lovelace: 89985810 - 9b2c45472487bc82ae575fc57a338b1fa4f6a47e536bdd57f864c46c: guess: 0 + Ada: Lovelace: 89985753 + a00668ced9003f5b42834072802daeec9a7dd1eb777662a161f2ab06: guess: 0 ---- Output 1 ---- Destination: PaymentPubKeyHash: 80a4f45b56b88d1139da23bc4c3c75ec6d32943c... (Wallet 7ce812d7a4770bbf58004067665c3a48f28ddd58) Value: - 9b2c45472487bc82ae575fc57a338b1fa4f6a47e536bdd57f864c46c: guess: 1 + a00668ced9003f5b42834072802daeec9a7dd1eb777662a161f2ab06: guess: 1 Ada: Lovelace: 2000000 @@ -319,7 +319,7 @@ Balances Carried Forward: PaymentPubKeyHash: 80a4f45b56b88d1139da23bc4c3c75ec6d32943c... (Wallet 7ce812d7a4770bbf58004067665c3a48f28ddd58) Value: Ada: Lovelace: 102000000 - 9b2c45472487bc82ae575fc57a338b1fa4f6a47e536bdd57f864c46c: guess: 1 + a00668ced9003f5b42834072802daeec9a7dd1eb777662a161f2ab06: guess: 1 PaymentPubKeyHash: 8952ed1aff55f5b7674b122804a3c0a96f4e2863... (Wallet 3a4778247ad35117d7c3150d194da389f3148f4a) Value: @@ -331,8 +331,8 @@ Balances Carried Forward: PaymentPubKeyHash: a2c20c77887ace1cd986193e4e75babd8993cfd5... (Wallet 872cb83b5ee40eb23bfdab1772660c822a48d491) Value: - Ada: Lovelace: 89985810 - 9b2c45472487bc82ae575fc57a338b1fa4f6a47e536bdd57f864c46c: guess: 0 + Ada: Lovelace: 89985753 + a00668ced9003f5b42834072802daeec9a7dd1eb777662a161f2ab06: guess: 0 PaymentPubKeyHash: a96a668ed7be83e332c872f51da7925b4472ca98... (Wallet bdf8dbca0cadeb365480c6ec29ec746a2b85274f) Value: @@ -350,67 +350,67 @@ Balances Carried Forward: Value: Ada: Lovelace: 100000000 - Script: 21927cbad33338d4eae6141407bf783b198aa7e55dd9089dc73c8d1d + Script: e39b4969cde4623e3bbc488dcee1e1820c00c2b69df67248769aff40 Value: Ada: Lovelace: 8000000 ==== Slot #4, Tx #0 ==== -TxId: 7a084925ff291d944232e98b25a0980c7349ce46f01fed961494a58ff35be4fc -Fee: Ada: Lovelace: 14170 -Mint: 9b2c45472487bc82ae575fc57a338b1fa4f6a47e536bdd57f864c46c: guess: 0 +TxId: c1ec211021d84ab02e39fa50468da1dfcc20c737cf19427a804f9b649658e051 +Fee: Ada: Lovelace: 14227 +Mint: a00668ced9003f5b42834072802daeec9a7dd1eb777662a161f2ab06: guess: 0 Signatures PubKey: 98c77c40ccc536e0d433874dae97d4a0787b10b3... - Signature: 58406192d4c5813c83877ac9ec0b688e574c41a7... + Signature: 584000934b04d6a26aee9bdc148153bf1d922b48... Inputs: ---- Input 0 ---- Destination: PaymentPubKeyHash: 80a4f45b56b88d1139da23bc4c3c75ec6d32943c... (Wallet 7ce812d7a4770bbf58004067665c3a48f28ddd58) Value: - Ada: Lovelace: 100000000 + a00668ced9003f5b42834072802daeec9a7dd1eb777662a161f2ab06: guess: 1 + Ada: Lovelace: 2000000 Source: - Tx: 98d5fbcefe21113b3f0390c1441e075b8a870cc5a8fa2a56dcde1d8247e41715 - Output #2 + Tx: 5f874f7ee33c30397e64c805c17b1944c092645aa3ff771e5ab6342359bbeb28 + Output #1 ---- Input 1 ---- Destination: PaymentPubKeyHash: 80a4f45b56b88d1139da23bc4c3c75ec6d32943c... (Wallet 7ce812d7a4770bbf58004067665c3a48f28ddd58) Value: - 9b2c45472487bc82ae575fc57a338b1fa4f6a47e536bdd57f864c46c: guess: 1 - Ada: Lovelace: 2000000 + Ada: Lovelace: 100000000 Source: - Tx: ee4d350e115107d177d6f66c3ee6f1008474b306f90cc4c5519f654b7f9ce07d - Output #1 + Tx: 98d5fbcefe21113b3f0390c1441e075b8a870cc5a8fa2a56dcde1d8247e41715 + Output #2 ---- Input 2 ---- - Destination: Script: 21927cbad33338d4eae6141407bf783b198aa7e55dd9089dc73c8d1d + Destination: Script: e39b4969cde4623e3bbc488dcee1e1820c00c2b69df67248769aff40 Value: Ada: Lovelace: 8000000 Source: - Tx: f02f6bdb4e032c86578adc0c8441b15ccb1033c9cc43cc71d17d689e5d107fd3 + Tx: a0e68431d8b133d45a5e2e1ab2a8b12d1bf3ab6c03d7bab6a1f4f0a24502e299 Output #2 - Script: 59dba60100003323232332233322233322233332... + Script: 59dd450100003323232332233322233322233332... Outputs: ---- Output 0 ---- Destination: PaymentPubKeyHash: 80a4f45b56b88d1139da23bc4c3c75ec6d32943c... (Wallet 7ce812d7a4770bbf58004067665c3a48f28ddd58) Value: - Ada: Lovelace: 100985830 - 9b2c45472487bc82ae575fc57a338b1fa4f6a47e536bdd57f864c46c: guess: 0 + a00668ced9003f5b42834072802daeec9a7dd1eb777662a161f2ab06: guess: 0 + Ada: Lovelace: 100985773 ---- Output 1 ---- Destination: PaymentPubKeyHash: 80a4f45b56b88d1139da23bc4c3c75ec6d32943c... (Wallet 7ce812d7a4770bbf58004067665c3a48f28ddd58) Value: - 9b2c45472487bc82ae575fc57a338b1fa4f6a47e536bdd57f864c46c: - + a00668ced9003f5b42834072802daeec9a7dd1eb777662a161f2ab06: - Ada: Lovelace: 2000000 ---- Output 2 ---- Destination: PaymentPubKeyHash: 80a4f45b56b88d1139da23bc4c3c75ec6d32943c... (Wallet 7ce812d7a4770bbf58004067665c3a48f28ddd58) Value: - 9b2c45472487bc82ae575fc57a338b1fa4f6a47e536bdd57f864c46c: guess: 1 + a00668ced9003f5b42834072802daeec9a7dd1eb777662a161f2ab06: guess: 1 Ada: Lovelace: 2000000 ---- Output 3 ---- - Destination: Script: 21927cbad33338d4eae6141407bf783b198aa7e55dd9089dc73c8d1d + Destination: Script: e39b4969cde4623e3bbc488dcee1e1820c00c2b69df67248769aff40 Value: Ada: Lovelace: 5000000 @@ -426,8 +426,8 @@ Balances Carried Forward: PaymentPubKeyHash: 80a4f45b56b88d1139da23bc4c3c75ec6d32943c... (Wallet 7ce812d7a4770bbf58004067665c3a48f28ddd58) Value: - Ada: Lovelace: 104985830 - 9b2c45472487bc82ae575fc57a338b1fa4f6a47e536bdd57f864c46c: guess: 1 + Ada: Lovelace: 104985773 + a00668ced9003f5b42834072802daeec9a7dd1eb777662a161f2ab06: guess: 1 PaymentPubKeyHash: 8952ed1aff55f5b7674b122804a3c0a96f4e2863... (Wallet 3a4778247ad35117d7c3150d194da389f3148f4a) Value: @@ -439,8 +439,8 @@ Balances Carried Forward: PaymentPubKeyHash: a2c20c77887ace1cd986193e4e75babd8993cfd5... (Wallet 872cb83b5ee40eb23bfdab1772660c822a48d491) Value: - Ada: Lovelace: 89985810 - 9b2c45472487bc82ae575fc57a338b1fa4f6a47e536bdd57f864c46c: guess: 0 + Ada: Lovelace: 89985753 + a00668ced9003f5b42834072802daeec9a7dd1eb777662a161f2ab06: guess: 0 PaymentPubKeyHash: a96a668ed7be83e332c872f51da7925b4472ca98... (Wallet bdf8dbca0cadeb365480c6ec29ec746a2b85274f) Value: @@ -458,6 +458,6 @@ Balances Carried Forward: Value: Ada: Lovelace: 100000000 - Script: 21927cbad33338d4eae6141407bf783b198aa7e55dd9089dc73c8d1d + Script: e39b4969cde4623e3bbc488dcee1e1820c00c2b69df67248769aff40 Value: Ada: Lovelace: 5000000 \ No newline at end of file