Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use-cases: Add TH module for tests #185

Merged
merged 3 commits into from
Oct 11, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .hlint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
- ignore: {name: Parse error}
- ignore: {name: Eta reduce, within: [Language.PlutusCore.MkPlc]}
# PLC plugin only accepts lists that are constructed in a certain way
- ignore: {name: Use list literal, within: [Spec.Crowdfunding]}
- ignore: {name: Use list literal, within: [Spec.TH]}
# PLC plugin requires && to be defined in side TH splices
- ignore: {name: Redundant if, within: [Language.Plutus.Coordination.Contracts.CrowdFunding, Language.Plutus.Coordination.Contracts.Vesting]}

Expand Down
1 change: 1 addition & 0 deletions pkgs/default.nix

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion plutus-use-cases/plutus-use-cases.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ test-suite plutus-use-cases-test
other-modules:
Spec.Crowdfunding
Spec.Vesting
Spec.TH
build-depends:
base >=4.9 && <5,
containers -any,
Expand All @@ -67,4 +68,5 @@ test-suite plutus-use-cases-test
plutus-use-cases,
plutus-th -any,
microlens -any,
core-to-plc -any
core-to-plc -any,
template-haskell -any
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
-- This is the fully parallel version that collects all contributions
-- in a single transaction. This is, of course, limited by the maximum
-- number of inputs a transaction can have.
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ViewPatterns #-}
{-# OPTIONS -fplugin=Language.Plutus.CoreToPLC.Plugin -fplugin-opt Language.Plutus.CoreToPLC.Plugin:dont-typecheck #-}
module Language.Plutus.Coordination.Contracts.CrowdFunding (
-- * Campaign parameters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ module Language.Plutus.Coordination.Contracts.Vesting (
VestingData(..),
vestFunds,
retrieveFunds,
validatorScript
validatorScript,
totalAmount
) where

import Control.Monad.Error.Class (MonadError (..))
Expand Down
75 changes: 27 additions & 48 deletions plutus-use-cases/test/Spec/Crowdfunding.hs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS -fplugin=Language.Plutus.CoreToPLC.Plugin -fplugin-opt Language.Plutus.CoreToPLC.Plugin:dont-typecheck #-}
module Spec.Crowdfunding(tests) where

Expand All @@ -23,11 +25,12 @@ import qualified Wallet.Generators as Gen
import Language.Plutus.Coordination.Contracts.CrowdFunding (Campaign (..), CampaignActor, CampaignPLC (..),
contribute, refund)
import qualified Language.Plutus.Coordination.Contracts.CrowdFunding as CF
import Language.Plutus.CoreToPLC.Plugin (plc)
import Language.Plutus.Runtime (Hash (..), PendingTx (..), PendingTxIn (..),
PendingTxOut (..), PendingTxOutRef (..), Value)
import qualified Language.Plutus.Runtime as Runtime
import Language.Plutus.TH (plutus)
import qualified Wallet.UTXO as UTXO

import Spec.TH (pendingTxCrowdfunding)

tests :: TestTree
tests = testGroup "crowdfunding" [
testProperty "make a contribution" makeContribution,
Expand All @@ -40,7 +43,7 @@ tests = testGroup "crowdfunding" [
-- | Make a contribution to the campaign from a wallet. Returns the reference
-- to the transaction output that is locked by the campaign's validator
-- script (and can be collected by the campaign owner)
contrib :: Wallet -> CampaignPLC -> Value -> Trace TxOutRef'
contrib :: Wallet -> CampaignPLC -> Runtime.Value -> Trace TxOutRef'
contrib w c v = exContrib <$> walletAction w (contribute c v) where
exContrib = snd . head . filter (isPayToScriptOut . fst) . txOutRefs . head

Expand All @@ -56,7 +59,7 @@ makeContribution :: Property
makeContribution = checkCFTrace scenario1 $ do
let w = Wallet 2
contribution = 600
rest = fromIntegral $ 1000 - contribution
rest = startingBalance - fromIntegral contribution
blockchainActions >>= walletNotifyBlock w
contrib w (cfCampaign scenario1) contribution
blockchainActions >>= walletNotifyBlock w
Expand All @@ -72,17 +75,10 @@ successfulCampaign = checkCFTrace scenario1 $ do
con2 <- contrib w2 c 600
con3 <- contrib w3 c 800
updateAll'
setValidationData $ ValidationData $ plc PendingTx {
pendingTxCurrentInput = (PendingTxIn (PendingTxOutRef 100 1) (), 600),
pendingTxOtherInputs = (PendingTxIn (PendingTxOutRef 200 1) (), 800):[],
pendingTxOutputs = []::[PendingTxOut CampaignActor],
pendingTxForge = 0,
pendingTxFee = 0,
pendingTxBlockHeight = 11
}
setValidationData $ ValidationData $(plutus [| $(pendingTxCrowdfunding) 11 600 (Just 800) |])
collect w1 c [(con2, w2, 600), (con3, w3, 800)]
updateAll'
mapM_ (uncurry assertOwnFundsEq) [(w2, 400), (w3, 200), (w1, 1400)]
mapM_ (uncurry assertOwnFundsEq) [(w2, startingBalance - 600), (w3, startingBalance - 800), (w1, 600 + 800)]
j-mueller marked this conversation as resolved.
Show resolved Hide resolved

-- | Check that the campaign owner cannot collect the monies before the campaign deadline
cantCollectEarly :: Property
Expand All @@ -93,17 +89,10 @@ cantCollectEarly = checkCFTrace scenario1 $ do
con2 <- contrib w2 c 600
con3 <- contrib w3 c 800
updateAll'
setValidationData $ ValidationData $ plc PendingTx {
pendingTxCurrentInput = (PendingTxIn (PendingTxOutRef 100 1) (), 600),
pendingTxOtherInputs = (PendingTxIn (PendingTxOutRef 200 1) (), 800):[],
pendingTxOutputs = []::[PendingTxOut CampaignActor],
pendingTxForge = 0,
pendingTxFee = 0,
pendingTxBlockHeight = 8
}
setValidationData $ ValidationData $(plutus [| $(pendingTxCrowdfunding) 8 600 (Just 800) |])
collect w1 c [(con2, w2, 600), (con3, w3, 800)]
updateAll'
mapM_ (uncurry assertOwnFundsEq) [(w2, 400), (w3, 200), (w1, 0)]
mapM_ (uncurry assertOwnFundsEq) [(w2, startingBalance - 600), (w3, startingBalance - 800), (w1, 0)]


-- | Check that the campaign owner cannot collect the monies after the
Expand All @@ -116,17 +105,10 @@ cantCollectLate = checkCFTrace scenario1 $ do
con2 <- contrib w2 c 600
con3 <- contrib w3 c 800
updateAll'
setValidationData $ ValidationData $ plc PendingTx {
pendingTxCurrentInput = (PendingTxIn (PendingTxOutRef 100 1) (), 600),
pendingTxOtherInputs = (PendingTxIn (PendingTxOutRef 200 1) (), 800):[],
pendingTxOutputs = []::[PendingTxOut CampaignActor],
pendingTxForge = 0,
pendingTxFee = 0,
pendingTxBlockHeight = 17
}
setValidationData $ ValidationData $(plutus [| $(pendingTxCrowdfunding) 17 600 (Just 800) |])
collect w1 c [(con2, w2, 600), (con3, w3, 800)]
updateAll'
mapM_ (uncurry assertOwnFundsEq) [(w2, 400), (w3, 200), (w1, 0)]
mapM_ (uncurry assertOwnFundsEq) [(w2, startingBalance - 600), (w3, startingBalance - 800), (w1, 0)]


-- | Run a successful campaign that ends with a refund
Expand All @@ -138,18 +120,11 @@ canRefund = checkCFTrace scenario1 $ do
con2 <- contrib w2 c 600
con3 <- contrib w3 c 800
updateAll'
setValidationData $ ValidationData $ plc PendingTx {
pendingTxCurrentInput = (PendingTxIn (PendingTxOutRef 100 1) (), 600),
pendingTxOtherInputs = []::[(PendingTxIn (), Value)],
pendingTxOutputs = []::[PendingTxOut CampaignActor],
pendingTxForge = 0,
pendingTxFee = 0,
pendingTxBlockHeight = 18
}
setValidationData $ ValidationData $(plutus [| $(pendingTxCrowdfunding) 18 600 Nothing |])
walletAction w2 (refund c con2 600)
walletAction w3 (refund c con3 800)
updateAll'
mapM_ (uncurry assertOwnFundsEq) [(w2, 1000), (w3, 1000), (w1, 0)]
mapM_ (uncurry assertOwnFundsEq) [(w2, startingBalance), (w3, startingBalance), (w1, 0)]

-- | Crowdfunding scenario with test parameters
data CFScenario = CFScenario {
Expand All @@ -160,17 +135,21 @@ data CFScenario = CFScenario {

scenario1 :: CFScenario
scenario1 = CFScenario{..} where
cfCampaign = CampaignPLC $ plc Campaign {
cfCampaign = CampaignPLC $(plutus [| Campaign {
campaignDeadline = 10,
campaignTarget = 1000,
campaignCollectionDeadline = 15,
campaignOwner = PubKey 1
}
} |])
cfWallets = Wallet <$> [1..3]
cfInitialBalances = Map.fromList [
(PubKey 1, 0),
(PubKey 2, 1000),
(PubKey 3, 1000)]
(PubKey 2, startingBalance),
(PubKey 3, startingBalance)]

-- | Funds available to wallets `Wallet 2` and `Wallet 3`
startingBalance :: UTXO.Value
startingBalance = 1000

-- | Run a trace with the given scenario and check that the emulator finished
-- successfully with an empty transaction pool.
Expand Down
51 changes: 51 additions & 0 deletions plutus-use-cases/test/Spec/TH.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
-- | Quoted expressions for generating validation data
module Spec.TH(
pendingTxVesting,
pendingTxCrowdfunding
) where

import Language.Haskell.TH (Exp, Q)
import qualified Language.Plutus.CoreToPLC.Primitives as Prim
import Language.Plutus.Runtime (Hash (..), Height, PendingTx (..),
PendingTxIn (..), PendingTxOut (..),
PendingTxOutRef (..), PendingTxOutType (..),
Value)
import Wallet.API (PubKey (..))

import Language.Plutus.Coordination.Contracts.CrowdFunding (CampaignActor)
import Language.Plutus.Coordination.Contracts.Vesting (VestingData (..))

-- | Create a `PendingTx () VestingData` from a block height and a value
-- (of funds taken out of the scheme)
pendingTxVesting :: Q Exp
pendingTxVesting = [| \(h :: Height) (out :: Value) ->
let total = 600
hash = 1123 -- stand-in for a transaction hash
rest = total - out
in PendingTx {
pendingTxCurrentInput = (PendingTxIn (PendingTxOutRef 100 0) (), total),
pendingTxOtherInputs = []::[(PendingTxIn (), Value)],
pendingTxOutputs = (PendingTxOut out Nothing (PubKeyTxOut (PubKey 1))::(PendingTxOut VestingData)):(PendingTxOut rest (Just (VestingData hash out)) DataTxOut::(PendingTxOut VestingData)):([]::[PendingTxOut VestingData]),
pendingTxForge = 0,
pendingTxFee = 0,
pendingTxBlockHeight = h
} |]

-- | Create a `PendingTx () CampaignActor` from a block height and one or two inputs.
pendingTxCrowdfunding :: Q Exp
pendingTxCrowdfunding = [| \(h :: Height) (v1::Value) (v2::Maybe Value) ->
let i1 = (PendingTxIn (PendingTxOutRef 100 1) (), v1)
i2 = case v2 of
Just v2' -> (PendingTxIn (PendingTxOutRef 200 1) (), v2'):[]
Nothing -> []::[(PendingTxIn (), Value)]
in PendingTx {
pendingTxCurrentInput = i1,
pendingTxOtherInputs = i2,
pendingTxOutputs = []::[PendingTxOut CampaignActor],
pendingTxForge = 0,
pendingTxFee = 0,
pendingTxBlockHeight = h
}
|]
Loading