Skip to content

Commit

Permalink
plutus-scripts-bench: migrate scripts into project
Browse files Browse the repository at this point in the history
  • Loading branch information
mgmeier committed Dec 15, 2022
1 parent fa2b5fe commit 33f9f73
Show file tree
Hide file tree
Showing 12 changed files with 309 additions and 177 deletions.
47 changes: 17 additions & 30 deletions bench/plutus-scripts-bench/plutus-scripts-bench.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ flag defer-plugin-errors
default: False
manual: True

common project-config
if os(windows)
buildable: False

common common-definitions
build-depends: base ^>=4.14
default-language: Haskell2010
Expand All @@ -33,45 +37,33 @@ common common-definitions
ghc-options:
-Wall -Wcompat -Wincomplete-record-updates
-Wincomplete-uni-patterns -Wpartial-fields -Wredundant-constraints
-Wunused-packages -fobject-code -fno-ignore-interface-pragmas
-fno-omit-interface-pragmas
-fobject-code -fno-ignore-interface-pragmas -fno-omit-interface-pragmas

if flag(defer-plugin-errors)
ghc-options: -fplugin-opt PlutusTx.Plugin:defer-errors

common maybe-Win32

library
import: common-definitions
hs-source-dirs: src

if os(windows)
build-depends: Win32

if flag(unexpected_thunks)
cpp-options: -DUNEXPECTED_THUNKS

exposed-modules:
Cardano.Benchmarking.PlutusScripts
Cardano.Benchmarking.PlutusScripts.CustomCallTypes

other-modules:
Cardano.Benchmarking.PlutusScripts.CustomCall
Cardano.Benchmarking.PlutusScripts.EcdsaSecp256k1Loop
Cardano.Benchmarking.PlutusScripts.Loop

--------------------
-- Local components
--------------------
-- build-depends: plutus-script-utils >=1.0.0

Cardano.Benchmarking.PlutusScripts.SchnorrSecp256k1Loop

--------------------------
-- Other IOG dependencies
-- IOG dependencies
--------------------------
build-depends:
, cardano-api >=1.35
--, cardano-cli >=1.35
--, cardano-ledger-alonzo
--, cardano-ledger-babbage
--, cardano-ledger-core
--, cardano-ledger-shelley
--, cardano-slotting
--, ouroboros-consensus
--, ouroboros-network
, plutus-ledger-api >=1.0.0
, plutus-tx >=1.0.0
, plutus-tx-plugin >=1.0.0
Expand All @@ -80,11 +72,6 @@ library
-- Non-IOG dependencies
------------------------
build-depends:
--, aeson
--, bytestring
--, containers
--, serialise
--, strict-containers
--, text
--, transformers
--, transformers-except
, bytestring
, serialise
, template-haskell
Original file line number Diff line number Diff line change
@@ -1,21 +1,36 @@
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

module Cardano.Benchmarking.PlutusScripts
( findPlutusScript
( encodePlutusScript
, findPlutusScript
, getAllScripts
, listPlutusScripts
) where

import Prelude

import Data.ByteString.Lazy as LBS (ByteString)

import Cardano.Api

import qualified Cardano.Benchmarking.PlutusScripts.CustomCall as CustomCall
import qualified Cardano.Benchmarking.PlutusScripts.EcdsaSecp256k1Loop as ECDSA
import qualified Cardano.Benchmarking.PlutusScripts.Loop as Loop
import qualified Cardano.Benchmarking.PlutusScripts.SchnorrSecp256k1Loop as Schnorr


getAllScripts ::
[(String, ScriptInAnyLang)]
getAllScripts =
[ (normalizeModuleName Loop.scriptName, asAnyLang Loop.scriptSerialized)
[ (normalizeModuleName CustomCall.scriptName, asAnyLang CustomCall.scriptSerialized)
, (normalizeModuleName ECDSA.scriptName , asAnyLang ECDSA.scriptSerialized)
, (normalizeModuleName Loop.scriptName , asAnyLang Loop.scriptSerialized)
, (normalizeModuleName Schnorr.scriptName , asAnyLang Schnorr.scriptSerialized)
]

listPlutusScripts ::
Expand All @@ -29,6 +44,16 @@ findPlutusScript ::
findPlutusScript
= (`lookup` getAllScripts)

encodePlutusScript ::
ScriptInAnyLang
-> LBS.ByteString
encodePlutusScript
= \case
ScriptInAnyLang (PlutusScriptLanguage PlutusScriptV1) s -> textEnvelopeToJSON Nothing s
ScriptInAnyLang (PlutusScriptLanguage PlutusScriptV2) s -> textEnvelopeToJSON Nothing s
_ -> "{}"


asAnyLang :: forall lang. IsPlutusScriptLanguage lang =>
PlutusScript lang
-> ScriptInAnyLang
Expand All @@ -37,7 +62,7 @@ asAnyLang script

-- "A.B.C" --> "C.hs"
normalizeModuleName ::
String
String
-> String
normalizeModuleName
= (++ ".hs") . reverse . takeWhile (/= '.') . reverse
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}

{-# OPTIONS_GHC -fno-warn-orphans #-}

module Cardano.Benchmarking.PlutusScripts.CustomCall
( scriptName
, scriptSerialized
) where

import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import Prelude as Haskell (String, (.), (<$>))

import Cardano.Api (PlutusScript, PlutusScriptV2)
import Cardano.Api.Shelley (PlutusScript (..))
import Codec.Serialise (serialise)
import qualified Data.ByteString.Lazy as LBS
import qualified Data.ByteString.Short as SBS
import qualified Plutus.V2.Ledger.Api as PlutusV2
import qualified PlutusTx
import PlutusTx.Prelude as Plutus hiding (Semigroup (..), (.), (<$>))

import Cardano.Benchmarking.PlutusScripts.CustomCallTypes


scriptName :: Haskell.String
scriptName
= $(LitE . StringL . loc_module <$> qLocation)


instance Plutus.Eq CustomCallData where
CCNone == CCNone = True
CCInteger i == CCInteger i' = i == i'
CCSum i is == CCSum i' is' = i == i' && is == is'
CCByteString s == CCByteString s' = s == s'
CCConcat s ss == CCConcat s' ss' = s == s' && ss == ss'
_ == _ = False

{-# INLINEABLE mkValidator #-}
mkValidator :: BuiltinData -> BuiltinData -> BuiltinData -> ()
mkValidator datum_ redeemer_ _txContext =
let
result = case cmd of
EvalSpine -> length redeemerArg == length datumArg
EvalValues -> redeemerArg == datumArg
EvalAndValidate -> all validateValue redeemerArg && redeemerArg == datumArg
in if result then () else error ()
where
datum, redeemer :: CustomCallArg
datum = unwrap datum_
redeemer = unwrap redeemer_

datumArg = snd datum
(cmd, redeemerArg) = redeemer

validateValue :: CustomCallData -> Bool
validateValue (CCSum i is) = i == sum is
validateValue (CCConcat s ss) = s == mconcat ss
validateValue _ = True

{-# INLINEABLE unwrap #-}
unwrap :: BuiltinData -> CustomCallArg
unwrap = PlutusV2.unsafeFromBuiltinData
-- Note: type-constraining unsafeFromBuiltinData decreases script's execution units.

validator :: PlutusV2.Validator
validator = PlutusV2.mkValidatorScript $$(PlutusTx.compile [|| mkValidator ||])

script :: PlutusV2.Script
script = PlutusV2.unValidatorScript validator

customCallScriptShortBs :: SBS.ShortByteString
customCallScriptShortBs = SBS.toShort . LBS.toStrict $ serialise script

scriptSerialized :: PlutusScript PlutusScriptV2
scriptSerialized = PlutusScriptSerialised customCallScriptShortBs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}

module Cardano.Benchmarking.PlutusScripts.CustomCallTypes
where

import qualified PlutusTx
import PlutusTx.Prelude as Plutus hiding (Semigroup (..), (.))
import Prelude as Haskell (Eq, Show)


-- this alias describes what the CustomCall script
-- expects both as datum and as redeemer
type CustomCallArg = (CustomCallCommand, [CustomCallData])

data CustomCallCommand
= EvalSpine
| EvalValues
| EvalAndValidate
deriving (Haskell.Eq, Haskell.Show)

data CustomCallData
= CCNone
| CCInteger Integer
| CCByteString BuiltinByteString
| CCSum Integer [Integer]
| CCConcat BuiltinByteString [BuiltinByteString]
deriving (Haskell.Eq, Haskell.Show)


PlutusTx.unstableMakeIsData ''CustomCallCommand
PlutusTx.unstableMakeIsData ''CustomCallData
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}

module Cardano.Benchmarking.PlutusScripts.EcdsaSecp256k1Loop
( scriptName
, scriptSerialized
) where

import Language.Haskell.TH
import Language.Haskell.TH.Syntax

import Cardano.Api (PlutusScript, PlutusScriptV2)
import Cardano.Api.Shelley (PlutusScript (..))
import Codec.Serialise (serialise)
import qualified Data.ByteString.Lazy as LBS
import qualified Data.ByteString.Short as SBS
import qualified Plutus.V2.Ledger.Api as PlutusV2
import qualified PlutusTx
import qualified PlutusTx.Builtins as BI
import PlutusTx.Prelude as P hiding (Semigroup (..), (.), (<$>))
import Prelude as Haskell (String, (.), (<$>))


scriptName :: Haskell.String
scriptName
= $(LitE . StringL . loc_module <$> qLocation)


{-# INLINEABLE mkValidator #-}
mkValidator :: BuiltinData -> BuiltinData -> BuiltinData -> ()
mkValidator _datum red _txContext =
case PlutusV2.fromBuiltinData red of
Nothing -> P.traceError "Trace error: Invalid redeemer"
Just (n, vkey, msg, sig) ->
if n < (1000000 :: Integer) -- large number ensures same bitsize for all counter values
then traceError "redeemer is < 1000000"
else loop n vkey msg sig
where
loop i v m s
| i == 1000000 = ()
| BI.verifyEcdsaSecp256k1Signature v m s = loop (pred i) v m s
| otherwise = P.traceError "Trace error: ECDSA validation failed"

validator :: PlutusV2.Validator
validator = PlutusV2.mkValidatorScript $$(PlutusTx.compile [|| mkValidator ||])

script :: PlutusV2.Script
script = PlutusV2.unValidatorScript validator

v2EcdsaLoopScriptShortBs :: SBS.ShortByteString
v2EcdsaLoopScriptShortBs = SBS.toShort . LBS.toStrict $ serialise script

scriptSerialized :: PlutusScript PlutusScriptV2
scriptSerialized = PlutusScriptSerialised v2EcdsaLoopScriptShortBs
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}

module Cardano.Benchmarking.PlutusScripts.Loop
( scriptName
, scriptSerialized
) where

import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import Prelude hiding (pred, ($), (&&), (<), (==))
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import Prelude hiding (pred, ($), (&&), (<), (==))

import Cardano.Api.Shelley (PlutusScript (..), PlutusScriptV1)
import Cardano.Api.Shelley (PlutusScript (..), PlutusScriptV1)

import Codec.Serialise
import Data.ByteString.Lazy qualified as LBS
import Data.ByteString.Short qualified as SBS
import Codec.Serialise
import qualified Data.ByteString.Lazy as LBS
import qualified Data.ByteString.Short as SBS

import Plutus.V1.Ledger.Scripts qualified as Plutus
import PlutusTx
import PlutusTx.Builtins (unsafeDataAsI)
import PlutusTx.Prelude hiding (Semigroup (..), unless, (.))
import qualified Plutus.V1.Ledger.Scripts as Plutus
import PlutusTx
import PlutusTx.Builtins (unsafeDataAsI)
import PlutusTx.Prelude hiding (Semigroup (..), unless, (.), (<$>))


scriptName :: String
Expand Down
Loading

0 comments on commit 33f9f73

Please sign in to comment.