From 65923fba29405fb161bfbf87fd4a609c6890b711 Mon Sep 17 00:00:00 2001 From: Ana Pantilie Date: Fri, 14 Jun 2024 15:06:08 +0300 Subject: [PATCH 1/8] Revert "Remove AssocMap comparison instances (#6173)" This reverts commit 294eaca62676d0cebf9f2e349416f7bf4e32d929. --- .../src/PlutusBenchmark/ScriptContexts.hs | 18 +++ ...ScriptContextEqualityTerm-20.budget.golden | 2 + ...ckScriptContextEqualityTerm-20.eval.golden | 1 + plutus-benchmark/script-contexts/test/Spec.hs | 4 + .../src/PlutusLedgerApi/V2/Contexts.hs | 13 ++- .../src/PlutusLedgerApi/V3/Contexts.hs | 103 ++++++++++++++++-- ...2_ana.pantilie95_fix_assocmap_instances.md | 3 - plutus-tx/src/PlutusTx/AssocMap.hs | 4 +- plutus-tx/src/PlutusTx/Data/AssocMap.hs | 2 +- 9 files changed, 135 insertions(+), 15 deletions(-) create mode 100644 plutus-benchmark/script-contexts/test/9.6/checkScriptContextEqualityTerm-20.budget.golden create mode 100644 plutus-benchmark/script-contexts/test/9.6/checkScriptContextEqualityTerm-20.eval.golden delete mode 100644 plutus-tx/changelog.d/20240607_155832_ana.pantilie95_fix_assocmap_instances.md diff --git a/plutus-benchmark/script-contexts/src/PlutusBenchmark/ScriptContexts.hs b/plutus-benchmark/script-contexts/src/PlutusBenchmark/ScriptContexts.hs index 479b75e3689..e281a11ff60 100644 --- a/plutus-benchmark/script-contexts/src/PlutusBenchmark/ScriptContexts.hs +++ b/plutus-benchmark/script-contexts/src/PlutusBenchmark/ScriptContexts.hs @@ -134,6 +134,24 @@ mkScriptContextEqualityDataCode sc = `PlutusTx.unsafeApplyCode` PlutusTx.liftCodeDef sc `PlutusTx.unsafeApplyCode` PlutusTx.liftCodeDef d +-- This example checks the script context for equality (with itself) when encoded +-- as a normal (i.e. Scott-encoded) term, using the normal (i.e. typeclass-based) equality +-- functions. This can be quite expensive for a large structure! +{-# INLINABLE scriptContextEqualityTerm #-} +scriptContextEqualityTerm :: ScriptContext -> PlutusTx.BuiltinData -> () +-- See Note [Redundant arguments to equality benchmarks] +scriptContextEqualityTerm sc _ = + if sc PlutusTx.== sc + then () + else PlutusTx.traceError "The argument is not equal to itself" + +mkScriptContextEqualityTermCode :: ScriptContext -> PlutusTx.CompiledCode () +mkScriptContextEqualityTermCode sc = + let d = PlutusTx.toBuiltinData sc + in $$(PlutusTx.compile [|| scriptContextEqualityTerm ||]) + `PlutusTx.unsafeApplyCode` PlutusTx.liftCodeDef sc + `PlutusTx.unsafeApplyCode` PlutusTx.liftCodeDef d + -- This example is just the overhead from the previous two -- See Note [Redundant arguments to equality benchmarks] {-# INLINABLE scriptContextEqualityOverhead #-} diff --git a/plutus-benchmark/script-contexts/test/9.6/checkScriptContextEqualityTerm-20.budget.golden b/plutus-benchmark/script-contexts/test/9.6/checkScriptContextEqualityTerm-20.budget.golden new file mode 100644 index 00000000000..2e284ed406f --- /dev/null +++ b/plutus-benchmark/script-contexts/test/9.6/checkScriptContextEqualityTerm-20.budget.golden @@ -0,0 +1,2 @@ +({cpu: 201713366 +| mem: 1195470}) \ No newline at end of file diff --git a/plutus-benchmark/script-contexts/test/9.6/checkScriptContextEqualityTerm-20.eval.golden b/plutus-benchmark/script-contexts/test/9.6/checkScriptContextEqualityTerm-20.eval.golden new file mode 100644 index 00000000000..1dd2b8ed5d3 --- /dev/null +++ b/plutus-benchmark/script-contexts/test/9.6/checkScriptContextEqualityTerm-20.eval.golden @@ -0,0 +1 @@ +(constr 0) \ No newline at end of file diff --git a/plutus-benchmark/script-contexts/test/Spec.hs b/plutus-benchmark/script-contexts/test/Spec.hs index 7cd5cb5c0d7..62557c4ccb5 100644 --- a/plutus-benchmark/script-contexts/test/Spec.hs +++ b/plutus-benchmark/script-contexts/test/Spec.hs @@ -85,6 +85,10 @@ testCheckScEquality = testGroup "checkScriptContextEquality" mkScriptContextEqualityDataCode (mkScriptContext 20) , Tx.goldenEvalCekCatch "checkScriptContextEqualityData-20" $ [mkScriptContextEqualityDataCode (mkScriptContext 20)] + , Tx.goldenBudget "checkScriptContextEqualityTerm-20" $ + mkScriptContextEqualityTermCode (mkScriptContext 20) + , Tx.goldenEvalCekCatch "checkScriptContextEqualityTerm-20" $ + [mkScriptContextEqualityTermCode (mkScriptContext 20)] , Tx.goldenBudget "checkScriptContextEqualityOverhead-20" $ mkScriptContextEqualityOverheadCode (mkScriptContext 20) , Tx.goldenEvalCekCatch "checkScriptContextEqualityOverhead-20" $ diff --git a/plutus-ledger-api/src/PlutusLedgerApi/V2/Contexts.hs b/plutus-ledger-api/src/PlutusLedgerApi/V2/Contexts.hs index d32fd7e10b6..1314c6cfaff 100644 --- a/plutus-ledger-api/src/PlutusLedgerApi/V2/Contexts.hs +++ b/plutus-ledger-api/src/PlutusLedgerApi/V2/Contexts.hs @@ -84,7 +84,12 @@ data TxInfo = TxInfo , txInfoData :: Map DatumHash Datum -- ^ The lookup table of datums attached to the transaction -- /V1->V2/: changed from assoc list to a 'PlutusTx.AssocMap' , txInfoId :: TxId -- ^ Hash of the pending transaction body (i.e. transaction excluding witnesses) - } deriving stock (Generic, Haskell.Show) + } deriving stock (Generic, Haskell.Show, Haskell.Eq) + +instance Eq TxInfo where + {-# INLINABLE (==) #-} + TxInfo i ri o f m c w r s rs d tid == TxInfo i' ri' o' f' m' c' w' r' s' rs' d' tid' = + i == i' && ri == ri' && o == o' && f == f' && m == m' && c == c' && w == w' && r == r' && s == s' && rs == rs' && d == d' && tid == tid' instance Pretty TxInfo where pretty TxInfo{txInfoInputs, txInfoReferenceInputs, txInfoOutputs, txInfoFee, txInfoMint, txInfoDCert, txInfoWdrl, txInfoValidRange, txInfoSignatories, txInfoRedeemers, txInfoData, txInfoId} = @@ -108,7 +113,11 @@ data ScriptContext = ScriptContext { scriptContextTxInfo :: TxInfo -- ^ information about the transaction the currently-executing script is included in , scriptContextPurpose :: ScriptPurpose -- ^ the purpose of the currently-executing script } - deriving stock (Generic, Haskell.Show) + deriving stock (Generic, Haskell.Eq, Haskell.Show) + +instance Eq ScriptContext where + {-# INLINABLE (==) #-} + ScriptContext info purpose == ScriptContext info' purpose' = info == info' && purpose == purpose' instance Pretty ScriptContext where pretty ScriptContext{scriptContextTxInfo, scriptContextPurpose} = diff --git a/plutus-ledger-api/src/PlutusLedgerApi/V3/Contexts.hs b/plutus-ledger-api/src/PlutusLedgerApi/V3/Contexts.hs index 0fac2e88685..3d26a2f05dd 100644 --- a/plutus-ledger-api/src/PlutusLedgerApi/V3/Contexts.hs +++ b/plutus-ledger-api/src/PlutusLedgerApi/V3/Contexts.hs @@ -237,7 +237,7 @@ data Committee = Committee , committeeQuorum :: PlutusTx.Rational -- ^ Quorum of the committee that is necessary for a successful vote } - deriving stock (Generic, Haskell.Show) + deriving stock (Generic, Haskell.Show, Haskell.Eq) instance Pretty Committee where pretty Committee{..} = @@ -246,6 +246,11 @@ instance Pretty Committee where , "committeeQuorum:" <+> pretty committeeQuorum ] +instance PlutusTx.Eq Committee where + {-# INLINEABLE (==) #-} + Committee a b == Committee a' b' = + a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' + -- | A constitution. The optional anchor is omitted. newtype Constitution = Constitution { constitutionScript :: Haskell.Maybe V2.ScriptHash @@ -317,16 +322,35 @@ data GovernanceAction Rational -- ^ New quorum | NewConstitution (Haskell.Maybe GovernanceActionId) Constitution | InfoAction - deriving stock (Generic, Haskell.Show) + deriving stock (Generic, Haskell.Show, Haskell.Eq) deriving (Pretty) via (PrettyShow GovernanceAction) +instance PlutusTx.Eq GovernanceAction where + {-# INLINEABLE (==) #-} + ParameterChange a b c == ParameterChange a' b' c' = + a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' PlutusTx.&& c PlutusTx.== c' + HardForkInitiation a b == HardForkInitiation a' b' = + a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' + TreasuryWithdrawals a b == TreasuryWithdrawals a' b' = + a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' + NoConfidence a == NoConfidence a' = a PlutusTx.== a' + UpdateCommittee a b c d == UpdateCommittee a' b' c' d' = + a PlutusTx.== a' + PlutusTx.&& b PlutusTx.== b' + PlutusTx.&& c PlutusTx.== c' + PlutusTx.&& d PlutusTx.== d' + NewConstitution a b == NewConstitution a' b' = + a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' + InfoAction == InfoAction = Haskell.True + _ == _ = Haskell.False + -- | A proposal procedure. The optional anchor is omitted. data ProposalProcedure = ProposalProcedure { ppDeposit :: V2.Lovelace , ppReturnAddr :: V2.Credential , ppGovernanceAction :: GovernanceAction } - deriving stock (Generic, Haskell.Show) + deriving stock (Generic, Haskell.Show, Haskell.Eq) instance Pretty ProposalProcedure where pretty ProposalProcedure{..} = @@ -336,6 +360,13 @@ instance Pretty ProposalProcedure where , "ppGovernanceAction:" <+> pretty ppGovernanceAction ] +instance PlutusTx.Eq ProposalProcedure where + {-# INLINEABLE (==) #-} + ProposalProcedure a b c == ProposalProcedure a' b' c' = + a PlutusTx.== a' + PlutusTx.&& b PlutusTx.== b' + PlutusTx.&& c PlutusTx.== c' + -- | A `ScriptPurpose` uniquely identifies a Plutus script within a transaction. data ScriptPurpose = Minting V2.CurrencySymbol @@ -350,9 +381,25 @@ data ScriptPurpose Haskell.Integer -- ^ 0-based index of the given `ProposalProcedure` in `txInfoProposalProcedures` ProposalProcedure - deriving stock (Generic, Haskell.Show) + deriving stock (Generic, Haskell.Show, Haskell.Eq) deriving (Pretty) via (PrettyShow ScriptPurpose) +instance PlutusTx.Eq ScriptPurpose where + {-# INLINEABLE (==) #-} + Minting a == Minting a' = + a PlutusTx.== a' + Spending a == Spending a' = + a PlutusTx.== a' + Rewarding a == Rewarding a' = + a PlutusTx.== a' + Certifying a b == Certifying a' b' = + a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' + Voting a == Voting a' = + a PlutusTx.== a' + Proposing a b == Proposing a' b' = + a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' + _ == _ = Haskell.False + -- | Like `ScriptPurpose` but with an optional datum for spending scripts. data ScriptInfo = MintingScript V2.CurrencySymbol @@ -367,9 +414,25 @@ data ScriptInfo Haskell.Integer -- ^ 0-based index of the given `ProposalProcedure` in `txInfoProposalProcedures` ProposalProcedure - deriving stock (Generic, Haskell.Show) + deriving stock (Generic, Haskell.Show, Haskell.Eq) deriving (Pretty) via (PrettyShow ScriptInfo) +instance PlutusTx.Eq ScriptInfo where + {-# INLINEABLE (==) #-} + MintingScript a == MintingScript a' = + a PlutusTx.== a' + SpendingScript a b== SpendingScript a' b' = + a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' + RewardingScript a == RewardingScript a' = + a PlutusTx.== a' + CertifyingScript a b == CertifyingScript a' b' = + a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' + VotingScript a == VotingScript a' = + a PlutusTx.== a' + ProposingScript a b == ProposingScript a' b' = + a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' + _ == _ = Haskell.False + -- | An input of a pending transaction. data TxInInfo = TxInInfo { txInInfoOutRef :: V3.TxOutRef @@ -408,7 +471,7 @@ data TxInfo = TxInfo , txInfoCurrentTreasuryAmount :: Haskell.Maybe V2.Lovelace , txInfoTreasuryDonation :: Haskell.Maybe V2.Lovelace } - deriving stock (Generic, Haskell.Show) + deriving stock (Generic, Haskell.Show, Haskell.Eq) instance Pretty TxInfo where pretty TxInfo{..} = @@ -431,6 +494,27 @@ instance Pretty TxInfo where , "Treasury Donation:" <+> pretty txInfoTreasuryDonation ] +instance PlutusTx.Eq TxInfo where + {-# INLINEABLE (==) #-} + TxInfo a b c d e f g h i j k l m n o p + == TxInfo a' b' c' d' e' f' g' h' i' j' k' l' m' n' o' p' = + a PlutusTx.== a' + PlutusTx.&& b PlutusTx.== b' + PlutusTx.&& c PlutusTx.== c' + PlutusTx.&& d PlutusTx.== d' + PlutusTx.&& e PlutusTx.== e' + PlutusTx.&& f PlutusTx.== f' + PlutusTx.&& g PlutusTx.== g' + PlutusTx.&& h PlutusTx.== h' + PlutusTx.&& i PlutusTx.== i' + PlutusTx.&& j PlutusTx.== j' + PlutusTx.&& k PlutusTx.== k' + PlutusTx.&& l PlutusTx.== l' + PlutusTx.&& m PlutusTx.== m' + PlutusTx.&& n PlutusTx.== n' + PlutusTx.&& o PlutusTx.== o' + PlutusTx.&& p PlutusTx.== p' + -- | The context that the currently-executing script can access. data ScriptContext = ScriptContext { scriptContextTxInfo :: TxInfo @@ -441,7 +525,7 @@ data ScriptContext = ScriptContext -- ^ the purpose of the currently-executing script, along with information associated -- with the purpose } - deriving stock (Generic, Haskell.Show) + deriving stock (Generic, Haskell.Eq, Haskell.Show) instance Pretty ScriptContext where pretty ScriptContext{..} = @@ -451,6 +535,11 @@ instance Pretty ScriptContext where , nest 2 (vsep ["Redeemer:", pretty scriptContextRedeemer]) ] +instance PlutusTx.Eq ScriptContext where + {-# INLINEABLE (==) #-} + ScriptContext a b c == ScriptContext a' b' c' = + a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' PlutusTx.&& c PlutusTx.== c' + {-# INLINEABLE findOwnInput #-} -- | Find the input currently being validated. diff --git a/plutus-tx/changelog.d/20240607_155832_ana.pantilie95_fix_assocmap_instances.md b/plutus-tx/changelog.d/20240607_155832_ana.pantilie95_fix_assocmap_instances.md deleted file mode 100644 index 50b2c381d5f..00000000000 --- a/plutus-tx/changelog.d/20240607_155832_ana.pantilie95_fix_assocmap_instances.md +++ /dev/null @@ -1,3 +0,0 @@ -### Removed - -- Removed incorrect Ord and Eq instances from AssocMap and Data.AssocMap. diff --git a/plutus-tx/src/PlutusTx/AssocMap.hs b/plutus-tx/src/PlutusTx/AssocMap.hs index 2e7c32c7163..d5c6c800150 100644 --- a/plutus-tx/src/PlutusTx/AssocMap.hs +++ b/plutus-tx/src/PlutusTx/AssocMap.hs @@ -70,8 +70,8 @@ import Prettyprinter (Pretty (..)) -- Take care when using 'fromBuiltinData' and 'unsafeFromBuiltinData', as neither function performs -- deduplication of the input collection and may create invalid 'Map's! newtype Map k v = Map {unMap :: [(k, v)]} - deriving stock (Generic, Haskell.Show, Data, TH.Lift) - deriving newtype (NFData) + deriving stock (Generic, Haskell.Eq, Haskell.Show, Data, TH.Lift) + deriving newtype (Eq, Ord, NFData) -- | Hand-written instances to use the underlying 'Map' type in 'Data', and -- to be reasonably efficient. diff --git a/plutus-tx/src/PlutusTx/Data/AssocMap.hs b/plutus-tx/src/PlutusTx/Data/AssocMap.hs index 5fded4753d9..59b426915b2 100644 --- a/plutus-tx/src/PlutusTx/Data/AssocMap.hs +++ b/plutus-tx/src/PlutusTx/Data/AssocMap.hs @@ -63,7 +63,7 @@ this implementation provides slow lookup and update operations because it is bas on a list representation. -} newtype Map k a = Map (BI.BuiltinList (BI.BuiltinPair BuiltinData BuiltinData)) - deriving stock (Haskell.Show) + deriving stock (Haskell.Eq, Haskell.Show) instance P.ToData (Map k a) where {-# INLINEABLE toBuiltinData #-} From 609638a66e88970ea31f1837c13bfb240f447387 Mon Sep 17 00:00:00 2001 From: Ana Pantilie Date: Fri, 14 Jun 2024 15:18:22 +0300 Subject: [PATCH 2/8] Add custom Eq and Ord for AssocMap Signed-off-by: Ana Pantilie --- .../src/PlutusLedgerApi/V1/Contexts.hs | 2 +- .../src/PlutusLedgerApi/V3/Contexts.hs | 25 +++++++++++-------- plutus-tx/src/PlutusTx/AssocMap.hs | 12 ++++++++- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/plutus-ledger-api/src/PlutusLedgerApi/V1/Contexts.hs b/plutus-ledger-api/src/PlutusLedgerApi/V1/Contexts.hs index aee8b7a493d..fcfb0acaac1 100644 --- a/plutus-ledger-api/src/PlutusLedgerApi/V1/Contexts.hs +++ b/plutus-ledger-api/src/PlutusLedgerApi/V1/Contexts.hs @@ -82,7 +82,7 @@ data ScriptPurpose | Spending TxOutRef | Rewarding StakingCredential | Certifying DCert - deriving stock (Generic, Haskell.Show, Haskell.Eq) + deriving stock (Generic, Haskell.Show, Haskell.Eq, Haskell.Ord) deriving Pretty via (PrettyShow ScriptPurpose) instance Eq ScriptPurpose where diff --git a/plutus-ledger-api/src/PlutusLedgerApi/V3/Contexts.hs b/plutus-ledger-api/src/PlutusLedgerApi/V3/Contexts.hs index 3d26a2f05dd..a1e31d5d3b1 100644 --- a/plutus-ledger-api/src/PlutusLedgerApi/V3/Contexts.hs +++ b/plutus-ledger-api/src/PlutusLedgerApi/V3/Contexts.hs @@ -68,6 +68,7 @@ newtype ColdCommitteeCredential = ColdCommitteeCredential V2.Credential deriving (Pretty) via (PrettyShow ColdCommitteeCredential) deriving newtype ( Haskell.Eq + , Haskell.Ord , Haskell.Show , PlutusTx.Eq , PlutusTx.ToData @@ -80,6 +81,7 @@ newtype HotCommitteeCredential = HotCommitteeCredential V2.Credential deriving (Pretty) via (PrettyShow HotCommitteeCredential) deriving newtype ( Haskell.Eq + , Haskell.Ord , Haskell.Show , PlutusTx.Eq , PlutusTx.ToData @@ -92,6 +94,7 @@ newtype DRepCredential = DRepCredential V2.Credential deriving (Pretty) via (PrettyShow DRepCredential) deriving newtype ( Haskell.Eq + , Haskell.Ord , Haskell.Show , PlutusTx.Eq , PlutusTx.ToData @@ -103,7 +106,7 @@ data DRep = DRep DRepCredential | DRepAlwaysAbstain | DRepAlwaysNoConfidence - deriving stock (Generic, Haskell.Show, Haskell.Eq) + deriving stock (Generic, Haskell.Show, Haskell.Eq, Haskell.Ord) deriving (Pretty) via (PrettyShow DRep) instance PlutusTx.Eq DRep where @@ -117,7 +120,7 @@ data Delegatee = DelegStake V2.PubKeyHash | DelegVote DRep | DelegStakeVote V2.PubKeyHash DRep - deriving stock (Generic, Haskell.Show, Haskell.Eq) + deriving stock (Generic, Haskell.Show, Haskell.Eq, Haskell.Ord) deriving (Pretty) via (PrettyShow Delegatee) instance PlutusTx.Eq Delegatee where @@ -155,7 +158,7 @@ data TxCert | -- | Authorize a Hot credential for a specific Committee member's cold credential TxCertAuthHotCommittee ColdCommitteeCredential HotCommitteeCredential | TxCertResignColdCommittee ColdCommitteeCredential - deriving stock (Generic, Haskell.Show, Haskell.Eq) + deriving stock (Generic, Haskell.Show, Haskell.Eq, Haskell.Ord) deriving (Pretty) via (PrettyShow TxCert) instance PlutusTx.Eq TxCert where @@ -184,7 +187,7 @@ data Voter = CommitteeVoter HotCommitteeCredential | DRepVoter DRepCredential | StakePoolVoter V2.PubKeyHash - deriving stock (Generic, Haskell.Show, Haskell.Eq) + deriving stock (Generic, Haskell.Show, Haskell.Eq, Haskell.Ord) deriving (Pretty) via (PrettyShow Voter) instance PlutusTx.Eq Voter where @@ -217,7 +220,7 @@ data GovernanceActionId = GovernanceActionId { gaidTxId :: V3.TxId , gaidGovActionIx :: Haskell.Integer } - deriving stock (Generic, Haskell.Show, Haskell.Eq) + deriving stock (Generic, Haskell.Show, Haskell.Eq, Haskell.Ord) instance Pretty GovernanceActionId where pretty GovernanceActionId{..} = @@ -237,7 +240,7 @@ data Committee = Committee , committeeQuorum :: PlutusTx.Rational -- ^ Quorum of the committee that is necessary for a successful vote } - deriving stock (Generic, Haskell.Show, Haskell.Eq) + deriving stock (Generic, Haskell.Show, Haskell.Eq, Haskell.Ord) instance Pretty Committee where pretty Committee{..} = @@ -256,7 +259,7 @@ newtype Constitution = Constitution { constitutionScript :: Haskell.Maybe V2.ScriptHash } deriving stock (Generic) - deriving newtype (Haskell.Show, Haskell.Eq) + deriving newtype (Haskell.Show, Haskell.Eq, Haskell.Ord) instance Pretty Constitution where pretty (Constitution script) = "constitutionScript:" <+> pretty script @@ -269,7 +272,7 @@ data ProtocolVersion = ProtocolVersion { pvMajor :: Haskell.Integer , pvMinor :: Haskell.Integer } - deriving stock (Generic, Haskell.Show, Haskell.Eq) + deriving stock (Generic, Haskell.Show, Haskell.Eq, Haskell.Ord) instance Pretty ProtocolVersion where pretty ProtocolVersion{..} = @@ -322,7 +325,7 @@ data GovernanceAction Rational -- ^ New quorum | NewConstitution (Haskell.Maybe GovernanceActionId) Constitution | InfoAction - deriving stock (Generic, Haskell.Show, Haskell.Eq) + deriving stock (Generic, Haskell.Show, Haskell.Eq, Haskell.Ord) deriving (Pretty) via (PrettyShow GovernanceAction) instance PlutusTx.Eq GovernanceAction where @@ -350,7 +353,7 @@ data ProposalProcedure = ProposalProcedure , ppReturnAddr :: V2.Credential , ppGovernanceAction :: GovernanceAction } - deriving stock (Generic, Haskell.Show, Haskell.Eq) + deriving stock (Generic, Haskell.Show, Haskell.Eq, Haskell.Ord) instance Pretty ProposalProcedure where pretty ProposalProcedure{..} = @@ -381,7 +384,7 @@ data ScriptPurpose Haskell.Integer -- ^ 0-based index of the given `ProposalProcedure` in `txInfoProposalProcedures` ProposalProcedure - deriving stock (Generic, Haskell.Show, Haskell.Eq) + deriving stock (Generic, Haskell.Show, Haskell.Eq, Haskell.Ord) deriving (Pretty) via (PrettyShow ScriptPurpose) instance PlutusTx.Eq ScriptPurpose where diff --git a/plutus-tx/src/PlutusTx/AssocMap.hs b/plutus-tx/src/PlutusTx/AssocMap.hs index d5c6c800150..1e8ba954a2e 100644 --- a/plutus-tx/src/PlutusTx/AssocMap.hs +++ b/plutus-tx/src/PlutusTx/AssocMap.hs @@ -49,6 +49,8 @@ import PlutusTx.These import Control.DeepSeq (NFData) import Data.Data +import Data.Function (on) +import Data.Map.Strict qualified as HMap import GHC.Generics (Generic) import Language.Haskell.TH.Syntax as TH (Lift) import Prettyprinter (Pretty (..)) @@ -70,9 +72,17 @@ import Prettyprinter (Pretty (..)) -- Take care when using 'fromBuiltinData' and 'unsafeFromBuiltinData', as neither function performs -- deduplication of the input collection and may create invalid 'Map's! newtype Map k v = Map {unMap :: [(k, v)]} - deriving stock (Generic, Haskell.Eq, Haskell.Show, Data, TH.Lift) + deriving stock (Generic, Haskell.Show, Data, TH.Lift) deriving newtype (Eq, Ord, NFData) +instance (Haskell.Ord k, Haskell.Eq v) => Haskell.Eq (Map k v) where + Map l == Map r = + on (Haskell.==) HMap.fromList l r + +instance (Haskell.Ord k, Haskell.Ord v) => Haskell.Ord (Map k v) where + Map l <= Map r = + on (Haskell.<=) HMap.fromList l r + -- | Hand-written instances to use the underlying 'Map' type in 'Data', and -- to be reasonably efficient. instance (ToData k, ToData v) => ToData (Map k v) where From 5a51f22cffe55f616c16fdc5758dde674931fc62 Mon Sep 17 00:00:00 2001 From: Ana Pantilie Date: Fri, 14 Jun 2024 15:24:54 +0300 Subject: [PATCH 3/8] Remove PlutusTx instances Signed-off-by: Ana Pantilie --- .../src/PlutusBenchmark/ScriptContexts.hs | 18 ---- ...ScriptContextEqualityTerm-20.budget.golden | 2 - ...ckScriptContextEqualityTerm-20.eval.golden | 1 - plutus-benchmark/script-contexts/test/Spec.hs | 4 - .../src/PlutusLedgerApi/V2/Contexts.hs | 9 -- .../src/PlutusLedgerApi/V3/Contexts.hs | 89 ------------------- plutus-tx/src/PlutusTx/AssocMap.hs | 2 +- 7 files changed, 1 insertion(+), 124 deletions(-) delete mode 100644 plutus-benchmark/script-contexts/test/9.6/checkScriptContextEqualityTerm-20.budget.golden delete mode 100644 plutus-benchmark/script-contexts/test/9.6/checkScriptContextEqualityTerm-20.eval.golden diff --git a/plutus-benchmark/script-contexts/src/PlutusBenchmark/ScriptContexts.hs b/plutus-benchmark/script-contexts/src/PlutusBenchmark/ScriptContexts.hs index e281a11ff60..479b75e3689 100644 --- a/plutus-benchmark/script-contexts/src/PlutusBenchmark/ScriptContexts.hs +++ b/plutus-benchmark/script-contexts/src/PlutusBenchmark/ScriptContexts.hs @@ -134,24 +134,6 @@ mkScriptContextEqualityDataCode sc = `PlutusTx.unsafeApplyCode` PlutusTx.liftCodeDef sc `PlutusTx.unsafeApplyCode` PlutusTx.liftCodeDef d --- This example checks the script context for equality (with itself) when encoded --- as a normal (i.e. Scott-encoded) term, using the normal (i.e. typeclass-based) equality --- functions. This can be quite expensive for a large structure! -{-# INLINABLE scriptContextEqualityTerm #-} -scriptContextEqualityTerm :: ScriptContext -> PlutusTx.BuiltinData -> () --- See Note [Redundant arguments to equality benchmarks] -scriptContextEqualityTerm sc _ = - if sc PlutusTx.== sc - then () - else PlutusTx.traceError "The argument is not equal to itself" - -mkScriptContextEqualityTermCode :: ScriptContext -> PlutusTx.CompiledCode () -mkScriptContextEqualityTermCode sc = - let d = PlutusTx.toBuiltinData sc - in $$(PlutusTx.compile [|| scriptContextEqualityTerm ||]) - `PlutusTx.unsafeApplyCode` PlutusTx.liftCodeDef sc - `PlutusTx.unsafeApplyCode` PlutusTx.liftCodeDef d - -- This example is just the overhead from the previous two -- See Note [Redundant arguments to equality benchmarks] {-# INLINABLE scriptContextEqualityOverhead #-} diff --git a/plutus-benchmark/script-contexts/test/9.6/checkScriptContextEqualityTerm-20.budget.golden b/plutus-benchmark/script-contexts/test/9.6/checkScriptContextEqualityTerm-20.budget.golden deleted file mode 100644 index 2e284ed406f..00000000000 --- a/plutus-benchmark/script-contexts/test/9.6/checkScriptContextEqualityTerm-20.budget.golden +++ /dev/null @@ -1,2 +0,0 @@ -({cpu: 201713366 -| mem: 1195470}) \ No newline at end of file diff --git a/plutus-benchmark/script-contexts/test/9.6/checkScriptContextEqualityTerm-20.eval.golden b/plutus-benchmark/script-contexts/test/9.6/checkScriptContextEqualityTerm-20.eval.golden deleted file mode 100644 index 1dd2b8ed5d3..00000000000 --- a/plutus-benchmark/script-contexts/test/9.6/checkScriptContextEqualityTerm-20.eval.golden +++ /dev/null @@ -1 +0,0 @@ -(constr 0) \ No newline at end of file diff --git a/plutus-benchmark/script-contexts/test/Spec.hs b/plutus-benchmark/script-contexts/test/Spec.hs index 62557c4ccb5..7cd5cb5c0d7 100644 --- a/plutus-benchmark/script-contexts/test/Spec.hs +++ b/plutus-benchmark/script-contexts/test/Spec.hs @@ -85,10 +85,6 @@ testCheckScEquality = testGroup "checkScriptContextEquality" mkScriptContextEqualityDataCode (mkScriptContext 20) , Tx.goldenEvalCekCatch "checkScriptContextEqualityData-20" $ [mkScriptContextEqualityDataCode (mkScriptContext 20)] - , Tx.goldenBudget "checkScriptContextEqualityTerm-20" $ - mkScriptContextEqualityTermCode (mkScriptContext 20) - , Tx.goldenEvalCekCatch "checkScriptContextEqualityTerm-20" $ - [mkScriptContextEqualityTermCode (mkScriptContext 20)] , Tx.goldenBudget "checkScriptContextEqualityOverhead-20" $ mkScriptContextEqualityOverheadCode (mkScriptContext 20) , Tx.goldenEvalCekCatch "checkScriptContextEqualityOverhead-20" $ diff --git a/plutus-ledger-api/src/PlutusLedgerApi/V2/Contexts.hs b/plutus-ledger-api/src/PlutusLedgerApi/V2/Contexts.hs index 1314c6cfaff..5c9d774da3b 100644 --- a/plutus-ledger-api/src/PlutusLedgerApi/V2/Contexts.hs +++ b/plutus-ledger-api/src/PlutusLedgerApi/V2/Contexts.hs @@ -86,11 +86,6 @@ data TxInfo = TxInfo , txInfoId :: TxId -- ^ Hash of the pending transaction body (i.e. transaction excluding witnesses) } deriving stock (Generic, Haskell.Show, Haskell.Eq) -instance Eq TxInfo where - {-# INLINABLE (==) #-} - TxInfo i ri o f m c w r s rs d tid == TxInfo i' ri' o' f' m' c' w' r' s' rs' d' tid' = - i == i' && ri == ri' && o == o' && f == f' && m == m' && c == c' && w == w' && r == r' && s == s' && rs == rs' && d == d' && tid == tid' - instance Pretty TxInfo where pretty TxInfo{txInfoInputs, txInfoReferenceInputs, txInfoOutputs, txInfoFee, txInfoMint, txInfoDCert, txInfoWdrl, txInfoValidRange, txInfoSignatories, txInfoRedeemers, txInfoData, txInfoId} = vsep @@ -115,10 +110,6 @@ data ScriptContext = ScriptContext } deriving stock (Generic, Haskell.Eq, Haskell.Show) -instance Eq ScriptContext where - {-# INLINABLE (==) #-} - ScriptContext info purpose == ScriptContext info' purpose' = info == info' && purpose == purpose' - instance Pretty ScriptContext where pretty ScriptContext{scriptContextTxInfo, scriptContextPurpose} = vsep diff --git a/plutus-ledger-api/src/PlutusLedgerApi/V3/Contexts.hs b/plutus-ledger-api/src/PlutusLedgerApi/V3/Contexts.hs index a1e31d5d3b1..633aaad874b 100644 --- a/plutus-ledger-api/src/PlutusLedgerApi/V3/Contexts.hs +++ b/plutus-ledger-api/src/PlutusLedgerApi/V3/Contexts.hs @@ -249,11 +249,6 @@ instance Pretty Committee where , "committeeQuorum:" <+> pretty committeeQuorum ] -instance PlutusTx.Eq Committee where - {-# INLINEABLE (==) #-} - Committee a b == Committee a' b' = - a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' - -- | A constitution. The optional anchor is omitted. newtype Constitution = Constitution { constitutionScript :: Haskell.Maybe V2.ScriptHash @@ -328,25 +323,6 @@ data GovernanceAction deriving stock (Generic, Haskell.Show, Haskell.Eq, Haskell.Ord) deriving (Pretty) via (PrettyShow GovernanceAction) -instance PlutusTx.Eq GovernanceAction where - {-# INLINEABLE (==) #-} - ParameterChange a b c == ParameterChange a' b' c' = - a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' PlutusTx.&& c PlutusTx.== c' - HardForkInitiation a b == HardForkInitiation a' b' = - a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' - TreasuryWithdrawals a b == TreasuryWithdrawals a' b' = - a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' - NoConfidence a == NoConfidence a' = a PlutusTx.== a' - UpdateCommittee a b c d == UpdateCommittee a' b' c' d' = - a PlutusTx.== a' - PlutusTx.&& b PlutusTx.== b' - PlutusTx.&& c PlutusTx.== c' - PlutusTx.&& d PlutusTx.== d' - NewConstitution a b == NewConstitution a' b' = - a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' - InfoAction == InfoAction = Haskell.True - _ == _ = Haskell.False - -- | A proposal procedure. The optional anchor is omitted. data ProposalProcedure = ProposalProcedure { ppDeposit :: V2.Lovelace @@ -363,13 +339,6 @@ instance Pretty ProposalProcedure where , "ppGovernanceAction:" <+> pretty ppGovernanceAction ] -instance PlutusTx.Eq ProposalProcedure where - {-# INLINEABLE (==) #-} - ProposalProcedure a b c == ProposalProcedure a' b' c' = - a PlutusTx.== a' - PlutusTx.&& b PlutusTx.== b' - PlutusTx.&& c PlutusTx.== c' - -- | A `ScriptPurpose` uniquely identifies a Plutus script within a transaction. data ScriptPurpose = Minting V2.CurrencySymbol @@ -387,22 +356,6 @@ data ScriptPurpose deriving stock (Generic, Haskell.Show, Haskell.Eq, Haskell.Ord) deriving (Pretty) via (PrettyShow ScriptPurpose) -instance PlutusTx.Eq ScriptPurpose where - {-# INLINEABLE (==) #-} - Minting a == Minting a' = - a PlutusTx.== a' - Spending a == Spending a' = - a PlutusTx.== a' - Rewarding a == Rewarding a' = - a PlutusTx.== a' - Certifying a b == Certifying a' b' = - a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' - Voting a == Voting a' = - a PlutusTx.== a' - Proposing a b == Proposing a' b' = - a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' - _ == _ = Haskell.False - -- | Like `ScriptPurpose` but with an optional datum for spending scripts. data ScriptInfo = MintingScript V2.CurrencySymbol @@ -420,22 +373,6 @@ data ScriptInfo deriving stock (Generic, Haskell.Show, Haskell.Eq) deriving (Pretty) via (PrettyShow ScriptInfo) -instance PlutusTx.Eq ScriptInfo where - {-# INLINEABLE (==) #-} - MintingScript a == MintingScript a' = - a PlutusTx.== a' - SpendingScript a b== SpendingScript a' b' = - a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' - RewardingScript a == RewardingScript a' = - a PlutusTx.== a' - CertifyingScript a b == CertifyingScript a' b' = - a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' - VotingScript a == VotingScript a' = - a PlutusTx.== a' - ProposingScript a b == ProposingScript a' b' = - a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' - _ == _ = Haskell.False - -- | An input of a pending transaction. data TxInInfo = TxInInfo { txInInfoOutRef :: V3.TxOutRef @@ -497,27 +434,6 @@ instance Pretty TxInfo where , "Treasury Donation:" <+> pretty txInfoTreasuryDonation ] -instance PlutusTx.Eq TxInfo where - {-# INLINEABLE (==) #-} - TxInfo a b c d e f g h i j k l m n o p - == TxInfo a' b' c' d' e' f' g' h' i' j' k' l' m' n' o' p' = - a PlutusTx.== a' - PlutusTx.&& b PlutusTx.== b' - PlutusTx.&& c PlutusTx.== c' - PlutusTx.&& d PlutusTx.== d' - PlutusTx.&& e PlutusTx.== e' - PlutusTx.&& f PlutusTx.== f' - PlutusTx.&& g PlutusTx.== g' - PlutusTx.&& h PlutusTx.== h' - PlutusTx.&& i PlutusTx.== i' - PlutusTx.&& j PlutusTx.== j' - PlutusTx.&& k PlutusTx.== k' - PlutusTx.&& l PlutusTx.== l' - PlutusTx.&& m PlutusTx.== m' - PlutusTx.&& n PlutusTx.== n' - PlutusTx.&& o PlutusTx.== o' - PlutusTx.&& p PlutusTx.== p' - -- | The context that the currently-executing script can access. data ScriptContext = ScriptContext { scriptContextTxInfo :: TxInfo @@ -538,11 +454,6 @@ instance Pretty ScriptContext where , nest 2 (vsep ["Redeemer:", pretty scriptContextRedeemer]) ] -instance PlutusTx.Eq ScriptContext where - {-# INLINEABLE (==) #-} - ScriptContext a b c == ScriptContext a' b' c' = - a PlutusTx.== a' PlutusTx.&& b PlutusTx.== b' PlutusTx.&& c PlutusTx.== c' - {-# INLINEABLE findOwnInput #-} -- | Find the input currently being validated. diff --git a/plutus-tx/src/PlutusTx/AssocMap.hs b/plutus-tx/src/PlutusTx/AssocMap.hs index 1e8ba954a2e..79c5b694eff 100644 --- a/plutus-tx/src/PlutusTx/AssocMap.hs +++ b/plutus-tx/src/PlutusTx/AssocMap.hs @@ -73,7 +73,7 @@ import Prettyprinter (Pretty (..)) -- deduplication of the input collection and may create invalid 'Map's! newtype Map k v = Map {unMap :: [(k, v)]} deriving stock (Generic, Haskell.Show, Data, TH.Lift) - deriving newtype (Eq, Ord, NFData) + deriving newtype (NFData) instance (Haskell.Ord k, Haskell.Eq v) => Haskell.Eq (Map k v) where Map l == Map r = From 3c475a6b1c72e59ebebbb1da6c67937e50736635 Mon Sep 17 00:00:00 2001 From: Ana Pantilie Date: Fri, 14 Jun 2024 15:27:00 +0300 Subject: [PATCH 4/8] Revert file delete Signed-off-by: Ana Pantilie --- .../20240607_155832_ana.pantilie95_fix_assocmap_instances.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 plutus-tx/changelog.d/20240607_155832_ana.pantilie95_fix_assocmap_instances.md diff --git a/plutus-tx/changelog.d/20240607_155832_ana.pantilie95_fix_assocmap_instances.md b/plutus-tx/changelog.d/20240607_155832_ana.pantilie95_fix_assocmap_instances.md new file mode 100644 index 00000000000..cf04d67e928 --- /dev/null +++ b/plutus-tx/changelog.d/20240607_155832_ana.pantilie95_fix_assocmap_instances.md @@ -0,0 +1,3 @@ +### Removed + +- Removed incorrect Ord and Eq instances from AssocMap and Data.AssocMap. \ No newline at end of file From bccc7217c8a77fcbfce26955609b2d7dc904bc09 Mon Sep 17 00:00:00 2001 From: Ana Pantilie Date: Fri, 14 Jun 2024 15:28:14 +0300 Subject: [PATCH 5/8] Fix Signed-off-by: Ana Pantilie --- .../20240607_155832_ana.pantilie95_fix_assocmap_instances.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plutus-tx/changelog.d/20240607_155832_ana.pantilie95_fix_assocmap_instances.md b/plutus-tx/changelog.d/20240607_155832_ana.pantilie95_fix_assocmap_instances.md index cf04d67e928..7db8d34bcba 100644 --- a/plutus-tx/changelog.d/20240607_155832_ana.pantilie95_fix_assocmap_instances.md +++ b/plutus-tx/changelog.d/20240607_155832_ana.pantilie95_fix_assocmap_instances.md @@ -1,3 +1,3 @@ -### Removed +### Removed - Removed incorrect Ord and Eq instances from AssocMap and Data.AssocMap. \ No newline at end of file From 811a554c8e54cacb438b984b91eb4bd8dcd4d55b Mon Sep 17 00:00:00 2001 From: Ana Pantilie Date: Fri, 14 Jun 2024 15:46:59 +0300 Subject: [PATCH 6/8] Fix Signed-off-by: Ana Pantilie --- .../20240607_155832_ana.pantilie95_fix_assocmap_instances.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plutus-tx/changelog.d/20240607_155832_ana.pantilie95_fix_assocmap_instances.md b/plutus-tx/changelog.d/20240607_155832_ana.pantilie95_fix_assocmap_instances.md index 7db8d34bcba..50b2c381d5f 100644 --- a/plutus-tx/changelog.d/20240607_155832_ana.pantilie95_fix_assocmap_instances.md +++ b/plutus-tx/changelog.d/20240607_155832_ana.pantilie95_fix_assocmap_instances.md @@ -1,3 +1,3 @@ ### Removed -- Removed incorrect Ord and Eq instances from AssocMap and Data.AssocMap. \ No newline at end of file +- Removed incorrect Ord and Eq instances from AssocMap and Data.AssocMap. From e45752f2f558116ead670de400cae4b5faa903c9 Mon Sep 17 00:00:00 2001 From: Ana Pantilie Date: Fri, 14 Jun 2024 15:48:25 +0300 Subject: [PATCH 7/8] Add changelog Signed-off-by: Ana Pantilie --- .../20240614_154728_ana.pantilie95_add_haskell_sc_eq.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 plutus-tx/changelog.d/20240614_154728_ana.pantilie95_add_haskell_sc_eq.md diff --git a/plutus-tx/changelog.d/20240614_154728_ana.pantilie95_add_haskell_sc_eq.md b/plutus-tx/changelog.d/20240614_154728_ana.pantilie95_add_haskell_sc_eq.md new file mode 100644 index 00000000000..ed8f020277c --- /dev/null +++ b/plutus-tx/changelog.d/20240614_154728_ana.pantilie95_add_haskell_sc_eq.md @@ -0,0 +1,3 @@ +### Added + +- Haskell `Eq` and `Ord` instances for `AssocMap` based on `Data.Map.Strict`. \ No newline at end of file From 7c24fd1b9064740f5b56882a6f0692615eaed756 Mon Sep 17 00:00:00 2001 From: Ana Pantilie Date: Fri, 14 Jun 2024 15:49:30 +0300 Subject: [PATCH 8/8] Fix Signed-off-by: Ana Pantilie --- plutus-tx/src/PlutusTx/Data/AssocMap.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plutus-tx/src/PlutusTx/Data/AssocMap.hs b/plutus-tx/src/PlutusTx/Data/AssocMap.hs index 59b426915b2..5fded4753d9 100644 --- a/plutus-tx/src/PlutusTx/Data/AssocMap.hs +++ b/plutus-tx/src/PlutusTx/Data/AssocMap.hs @@ -63,7 +63,7 @@ this implementation provides slow lookup and update operations because it is bas on a list representation. -} newtype Map k a = Map (BI.BuiltinList (BI.BuiltinPair BuiltinData BuiltinData)) - deriving stock (Haskell.Eq, Haskell.Show) + deriving stock (Haskell.Show) instance P.ToData (Map k a) where {-# INLINEABLE toBuiltinData #-}