Skip to content
This repository has been archived by the owner on Dec 2, 2024. It is now read-only.

Add TimeValidity emulator test for different protocol versions #466

Merged
merged 6 commits into from
May 23, 2022
Merged
Show file tree
Hide file tree
Changes from 5 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
1 change: 1 addition & 0 deletions plutus-contract/plutus-contract.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ test-suite plutus-contract-test
Spec.Rows
Spec.State
Spec.ThreadToken
Spec.TimeValidity
Spec.Secrets
Spec.Plutus.Contract.Wallet
Spec.Plutus.Contract.Oracle
Expand Down
2 changes: 2 additions & 0 deletions plutus-contract/test/Spec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Spec.Rows qualified
import Spec.Secrets qualified
import Spec.State qualified
import Spec.ThreadToken qualified
import Spec.TimeValidity qualified
import Test.Tasty (TestTree, defaultMain, testGroup)

main :: IO ()
Expand All @@ -23,6 +24,7 @@ tests = testGroup "plutus-contract" [
Spec.State.tests,
Spec.Rows.tests,
Spec.ThreadToken.tests,
Spec.TimeValidity.tests,
Spec.Secrets.tests,
Spec.ErrorChecking.tests,
Spec.Plutus.Contract.Wallet.tests,
Expand Down
119 changes: 119 additions & 0 deletions plutus-contract/test/Spec/TimeValidity.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
module Spec.TimeValidity(tests) where

import Cardano.Api.Shelley (protocolParamProtocolVersion)
import Control.Lens hiding (contains, from, (.>))
import Control.Monad (void)
import Data.Map qualified as Map
import Data.Void (Void)
import Test.Tasty (TestTree, testGroup)

import Ledger qualified
import Ledger.Ada qualified as Ada
import Ledger.Constraints qualified as Constraints
import Ledger.Tx qualified as Tx
import Ledger.Typed.Scripts qualified as Scripts
import Plutus.Contract as Con
import Plutus.Contract.Test (assertFailedTransaction, assertValidatedTransactionCount, checkPredicateOptions,
defaultCheckOptions, emulatorConfig, w1)
import Plutus.Script.Utils.V1.Scripts (ValidatorHash)
import Plutus.Trace qualified as Trace
import Plutus.V1.Ledger.Api (POSIXTime, TxInfo, Validator)
import Plutus.V1.Ledger.Api qualified as P
import Plutus.V1.Ledger.Interval (contains, from)
import Plutus.V1.Ledger.Scripts (ScriptError (EvaluationError), unitDatum, unitRedeemer)
import PlutusTx qualified
import PlutusTx.Prelude qualified as P
import Prelude hiding (not)
import Wallet.Emulator.Stream (params)

tests :: TestTree
tests =
testGroup "time validity"
[ protocolV5
, protocolV6
, defaultProtocolParams
]

contract :: Contract () Empty ContractError ()
contract = do
now <- Con.currentTime
logInfo @String $ "now: " ++ show now
let tx1 = Constraints.mustPayToOtherScript valHash unitDatum $ Ada.lovelaceValueOf 25000000
ledgerTx1 <- submitTx tx1
awaitTxConfirmed $ Tx.getCardanoTxId ledgerTx1
utxos <- utxosAt scrAddress
let orefs = fst <$> Map.toList utxos
lookups =
Constraints.otherScript (validatorScript deadline)
<> Constraints.unspentOutputs utxos
tx2 =
mconcat [Constraints.mustSpendScriptOutput oref unitRedeemer | oref <- orefs]
catch-21 marked this conversation as resolved.
Show resolved Hide resolved
<> Constraints.mustIncludeDatum unitDatum
<> Constraints.mustValidateIn (from $ now + 1000)
ledgerTx2 <- submitTxConstraintsWith @Void lookups tx2
awaitTxConfirmed $ Tx.getCardanoTxId ledgerTx2

trace :: Trace.EmulatorTrace ()
trace = do
void $ Trace.activateContractWallet w1 contract
void $ Trace.waitNSlots 3

protocolV5 :: TestTree
protocolV5 = checkPredicateOptions
(defaultCheckOptions & over (emulatorConfig . params . Ledger.protocolParamsL) (\pp -> pp { protocolParamProtocolVersion = (5, 0) }))
"tx valid time interval is not supported in protocol v5"
(assertFailedTransaction (\_ err _ -> case err of {Ledger.ScriptFailure (EvaluationError ("Invalid range":_) _) -> True; _ -> False }))
(void trace)

protocolV6 :: TestTree
protocolV6 = checkPredicateOptions
(defaultCheckOptions & over (emulatorConfig . params . Ledger.protocolParamsL) (\pp -> pp { protocolParamProtocolVersion = (6, 0) }))
"tx valid time interval is supported in protocol v6"
(assertValidatedTransactionCount 2)
(void trace)

defaultProtocolParams :: TestTree
defaultProtocolParams = checkPredicateOptions
defaultCheckOptions
"tx valid time interval is supported in protocol v6+"
(assertValidatedTransactionCount 2)
(void trace)

deadline :: POSIXTime
deadline = 1596059092000 -- (milliseconds) transaction's valid range must be after this

{-# INLINEABLE mkValidator #-}
mkValidator :: P.POSIXTime -> () -> () -> P.ScriptContext -> Bool
mkValidator dl _ _ ctx = (from dl `contains` range) || P.traceError "Invalid range"
catch-21 marked this conversation as resolved.
Show resolved Hide resolved
where
info :: TxInfo
info = P.scriptContextTxInfo ctx

range :: P.POSIXTimeRange
range = P.txInfoValidRange info


data UnitTest
instance Scripts.ValidatorTypes UnitTest

typedValidator :: POSIXTime -> Scripts.TypedValidator UnitTest
typedValidator = Scripts.mkTypedValidatorParam @UnitTest
$$(PlutusTx.compile [||mkValidator||])
$$(PlutusTx.compile [|| wrap ||])
where
wrap = Scripts.mkUntypedValidator

validatorScript :: P.POSIXTime -> Validator
validatorScript = Scripts.validatorScript . typedValidator
catch-21 marked this conversation as resolved.
Show resolved Hide resolved

valHash :: ValidatorHash
valHash = Scripts.validatorHash $ typedValidator deadline

scrAddress :: Ledger.Address
scrAddress = Ledger.scriptHashAddress valHash
8 changes: 4 additions & 4 deletions plutus-example/test/plutus-example-test.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Cardano.Prelude

import GHC.IO.Encoding
import Test.PlutusExample.Direct.CertifyingAndWithdrawingPlutus qualified
-- import Test.PlutusExample.Direct.CertifyingAndWithdrawingPlutus qualified
import Test.PlutusExample.Direct.ScriptContextEquality qualified
import Test.PlutusExample.Direct.ScriptContextEqualityMint qualified
import Test.PlutusExample.Direct.TxInLockingPlutus qualified
Expand All @@ -19,9 +19,9 @@ main = do

plutusExampleTests :: TestTree
plutusExampleTests = testGroup "plutus-example"
[ -- Fails to meet deadline on MacOS for an unknown reason
testProperty "Plutus.Direct.CertifyingAndWithdrawingPlutus" Test.PlutusExample.Direct.CertifyingAndWithdrawingPlutus.hprop_plutus_certifying_withdrawing
, testProperty "prop_TxId_Api_Ledger_Plutus_Roundtrip" Test.PlutusExample.Plutus.prop_TxId_Api_Ledger_Plutus_Roundtrip
[ -- Flaky test:
-- testProperty "Plutus.Direct.CertifyingAndWithdrawingPlutus" Test.PlutusExample.Direct.CertifyingAndWithdrawingPlutus.hprop_plutus_certifying_withdrawing
testProperty "prop_TxId_Api_Ledger_Plutus_Roundtrip" Test.PlutusExample.Plutus.prop_TxId_Api_Ledger_Plutus_Roundtrip
, testProperty "prop_TxId_Api_Ledger_Roundtrip" Test.PlutusExample.Plutus.prop_TxId_Api_Ledger_Roundtrip
, testProperty "prop_script_ScriptContextEquality" Test.PlutusExample.Direct.ScriptContextEquality.hprop_plutus_script_context_equality
, testProperty "prop_direct_ScriptContextEqualityMint" Test.PlutusExample.Direct.ScriptContextEqualityMint.hprop_plutus_script_context_mint_equality
Expand Down