{-# LANGUAGE DataKinds       #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies    #-}

module PlutusCore.Evaluation.Machine.ExBudgetingDefaults
    ( defaultBuiltinsRuntime
    , defaultCekCostModel
    , defaultCekMachineCosts
    , defaultCekParameters
    , defaultCostModelParams
    , defaultUnliftingMode
    , defaultBuiltinCostModel
    , unitCekMachineCosts
    , unitCekParameters
    )

where

import PlutusCore.Builtin

import PlutusCore.DataFilePaths qualified as DFP
import PlutusCore.Default
import PlutusCore.Evaluation.Machine.BuiltinCostModel
import PlutusCore.Evaluation.Machine.CostModelInterface
import PlutusCore.Evaluation.Machine.ExBudget ()
import PlutusCore.Evaluation.Machine.ExMemory ()
import PlutusCore.Evaluation.Machine.MachineParameters

import UntypedPlutusCore.Evaluation.Machine.Cek.CekMachineCosts
import UntypedPlutusCore.Evaluation.Machine.Cek.Internal

import Data.Aeson.THReader


-- | The default cost model for built-in functions.
defaultBuiltinCostModel :: BuiltinCostModel
defaultBuiltinCostModel :: BuiltinCostModel
defaultBuiltinCostModel =
    $$(readJSONFromFile DFP.builtinCostModelFile)

{- Note [Modifying the cost model]
   When the Haskell representation of the cost model is changed, for example by
   adding a new builtin or changing the name of an existing one,
   readJSONFromFile will fail when it tries to read a JSON file generated using
   the previous version.  When this happens, uncomment the three lines below (and
   comment out the three above) then rerun

      cabal bench plutus-core:update-cost-model

   (You may also need to add 'data-default' to the 'build-depends' for the
   library in plutus-core.cabal). This will generate a new JSON file filled with
   default values.  After that, restore this file to its previous state and then
   run "update-cost-model" again to fill in the JSON file with the correct
   values (assuming that suitable benchmarking data is in benching.csv and that
   models.R contains R code to generate cost models for any new functions).

   Alternatively, modify builtinCostModelFile by hand so that it matches the new
   format.
 -}

-- import           Data.Default
-- defaultBuiltinCostModel :: BuiltinCostModel
-- defaultBuiltinCostModel = def

-- | Default costs for CEK machine instructions.
defaultCekMachineCosts :: CekMachineCosts
defaultCekMachineCosts :: CekMachineCosts
defaultCekMachineCosts =
  $$(readJSONFromFile DFP.cekMachineCostsFile)

defaultCekCostModel :: CostModel CekMachineCosts BuiltinCostModel
defaultCekCostModel :: CostModel CekMachineCosts BuiltinCostModel
defaultCekCostModel = CekMachineCosts
-> BuiltinCostModel -> CostModel CekMachineCosts BuiltinCostModel
forall machinecosts builtincosts.
machinecosts -> builtincosts -> CostModel machinecosts builtincosts
CostModel CekMachineCosts
defaultCekMachineCosts BuiltinCostModel
defaultBuiltinCostModel
--- defaultCekMachineCosts is CekMachineCosts

-- | The default cost model data.  This is exposed to the ledger, so let's not
-- confuse anybody by mentioning the CEK machine
defaultCostModelParams :: Maybe CostModelParams
defaultCostModelParams :: Maybe CostModelParams
defaultCostModelParams = CostModel CekMachineCosts BuiltinCostModel -> Maybe CostModelParams
forall machinecosts builtincosts.
(ToJSON machinecosts, ToJSON builtincosts) =>
CostModel machinecosts builtincosts -> Maybe CostModelParams
extractCostModelParams CostModel CekMachineCosts BuiltinCostModel
defaultCekCostModel

defaultUnliftingMode :: UnliftingMode
defaultUnliftingMode :: UnliftingMode
defaultUnliftingMode = UnliftingMode
UnliftingImmediate

defaultCekParameters :: MachineParameters CekMachineCosts CekValue DefaultUni DefaultFun
defaultCekParameters :: MachineParameters CekMachineCosts CekValue DefaultUni DefaultFun
defaultCekParameters = UnliftingMode
-> CostModel CekMachineCosts BuiltinCostModel
-> MachineParameters CekMachineCosts CekValue DefaultUni DefaultFun
forall (uni :: * -> *) fun builtincosts (val :: (* -> *) -> * -> *)
       machinecosts.
(CostingPart uni fun ~ builtincosts,
 HasConstantIn uni (val uni fun), ToBuiltinMeaning uni fun) =>
UnliftingMode
-> CostModel machinecosts builtincosts
-> MachineParameters machinecosts val uni fun
mkMachineParameters UnliftingMode
defaultUnliftingMode CostModel CekMachineCosts BuiltinCostModel
defaultCekCostModel

unitCekParameters :: MachineParameters CekMachineCosts CekValue DefaultUni DefaultFun
unitCekParameters :: MachineParameters CekMachineCosts CekValue DefaultUni DefaultFun
unitCekParameters =
    UnliftingMode
-> CostModel CekMachineCosts BuiltinCostModel
-> MachineParameters CekMachineCosts CekValue DefaultUni DefaultFun
forall (uni :: * -> *) fun builtincosts (val :: (* -> *) -> * -> *)
       machinecosts.
(CostingPart uni fun ~ builtincosts,
 HasConstantIn uni (val uni fun), ToBuiltinMeaning uni fun) =>
UnliftingMode
-> CostModel machinecosts builtincosts
-> MachineParameters machinecosts val uni fun
mkMachineParameters UnliftingMode
defaultUnliftingMode (CostModel CekMachineCosts BuiltinCostModel
 -> MachineParameters
      CekMachineCosts CekValue DefaultUni DefaultFun)
-> CostModel CekMachineCosts BuiltinCostModel
-> MachineParameters CekMachineCosts CekValue DefaultUni DefaultFun
forall a b. (a -> b) -> a -> b
$
        CekMachineCosts
-> BuiltinCostModel -> CostModel CekMachineCosts BuiltinCostModel
forall machinecosts builtincosts.
machinecosts -> builtincosts -> CostModel machinecosts builtincosts
CostModel CekMachineCosts
unitCekMachineCosts BuiltinCostModel
unitCostBuiltinCostModel

defaultBuiltinsRuntime :: HasConstantIn DefaultUni term => BuiltinsRuntime DefaultFun term
defaultBuiltinsRuntime :: BuiltinsRuntime DefaultFun term
defaultBuiltinsRuntime = UnliftingMode
-> BuiltinCostModel -> BuiltinsRuntime DefaultFun term
forall cost (uni :: * -> *) fun val.
(cost ~ CostingPart uni fun, HasConstantIn uni val,
 ToBuiltinMeaning uni fun) =>
UnliftingMode -> cost -> BuiltinsRuntime fun val
toBuiltinsRuntime UnliftingMode
defaultUnliftingMode BuiltinCostModel
defaultBuiltinCostModel


-- A cost model with unit costs, so we can count how often each builtin is called

unitCostOneArgument :: CostingFun ModelOneArgument
unitCostOneArgument :: CostingFun ModelOneArgument
unitCostOneArgument =  ModelOneArgument -> ModelOneArgument -> CostingFun ModelOneArgument
forall model. model -> model -> CostingFun model
CostingFun (SatInt -> ModelOneArgument
ModelOneArgumentConstantCost SatInt
1) (SatInt -> ModelOneArgument
ModelOneArgumentConstantCost SatInt
0)

unitCostTwoArguments :: CostingFun ModelTwoArguments
unitCostTwoArguments :: CostingFun ModelTwoArguments
unitCostTwoArguments   =  ModelTwoArguments
-> ModelTwoArguments -> CostingFun ModelTwoArguments
forall model. model -> model -> CostingFun model
CostingFun (SatInt -> ModelTwoArguments
ModelTwoArgumentsConstantCost SatInt
1) (SatInt -> ModelTwoArguments
ModelTwoArgumentsConstantCost SatInt
0)

unitCostThreeArguments :: CostingFun ModelThreeArguments
unitCostThreeArguments :: CostingFun ModelThreeArguments
unitCostThreeArguments =  ModelThreeArguments
-> ModelThreeArguments -> CostingFun ModelThreeArguments
forall model. model -> model -> CostingFun model
CostingFun (SatInt -> ModelThreeArguments
ModelThreeArgumentsConstantCost SatInt
1) (SatInt -> ModelThreeArguments
ModelThreeArgumentsConstantCost SatInt
0)

unitCostSixArguments :: CostingFun ModelSixArguments
unitCostSixArguments :: CostingFun ModelSixArguments
unitCostSixArguments   =  ModelSixArguments
-> ModelSixArguments -> CostingFun ModelSixArguments
forall model. model -> model -> CostingFun model
CostingFun (SatInt -> ModelSixArguments
ModelSixArgumentsConstantCost SatInt
1) (SatInt -> ModelSixArguments
ModelSixArgumentsConstantCost SatInt
0)

unitCostBuiltinCostModel :: BuiltinCostModel
unitCostBuiltinCostModel :: BuiltinCostModel
unitCostBuiltinCostModel = BuiltinCostModelBase :: forall (f :: * -> *).
f ModelTwoArguments
-> f ModelTwoArguments
-> f ModelTwoArguments
-> f ModelTwoArguments
-> f ModelTwoArguments
-> f ModelTwoArguments
-> f ModelTwoArguments
-> f ModelTwoArguments
-> f ModelTwoArguments
-> f ModelTwoArguments
-> f ModelTwoArguments
-> f ModelTwoArguments
-> f ModelThreeArguments
-> f ModelOneArgument
-> f ModelTwoArguments
-> f ModelTwoArguments
-> f ModelTwoArguments
-> f ModelTwoArguments
-> f ModelOneArgument
-> f ModelOneArgument
-> f ModelOneArgument
-> f ModelThreeArguments
-> f ModelThreeArguments
-> f ModelThreeArguments
-> f ModelTwoArguments
-> f ModelTwoArguments
-> f ModelOneArgument
-> f ModelOneArgument
-> f ModelThreeArguments
-> f ModelTwoArguments
-> f ModelTwoArguments
-> f ModelOneArgument
-> f ModelOneArgument
-> f ModelThreeArguments
-> f ModelTwoArguments
-> f ModelOneArgument
-> f ModelOneArgument
-> f ModelOneArgument
-> f ModelSixArguments
-> f ModelTwoArguments
-> f ModelOneArgument
-> f ModelOneArgument
-> f ModelOneArgument
-> f ModelOneArgument
-> f ModelOneArgument
-> f ModelOneArgument
-> f ModelOneArgument
-> f ModelOneArgument
-> f ModelOneArgument
-> f ModelTwoArguments
-> f ModelTwoArguments
-> f ModelOneArgument
-> f ModelOneArgument
-> f ModelOneArgument
-> BuiltinCostModelBase f
BuiltinCostModelBase
    {
     -- Integers
      paramAddInteger :: CostingFun ModelTwoArguments
paramAddInteger                      = CostingFun ModelTwoArguments
unitCostTwoArguments
    , paramSubtractInteger :: CostingFun ModelTwoArguments
paramSubtractInteger                 = CostingFun ModelTwoArguments
unitCostTwoArguments
    , paramMultiplyInteger :: CostingFun ModelTwoArguments
paramMultiplyInteger                 = CostingFun ModelTwoArguments
unitCostTwoArguments
    , paramDivideInteger :: CostingFun ModelTwoArguments
paramDivideInteger                   = CostingFun ModelTwoArguments
unitCostTwoArguments
    , paramQuotientInteger :: CostingFun ModelTwoArguments
paramQuotientInteger                 = CostingFun ModelTwoArguments
unitCostTwoArguments
    , paramRemainderInteger :: CostingFun ModelTwoArguments
paramRemainderInteger                = CostingFun ModelTwoArguments
unitCostTwoArguments
    , paramModInteger :: CostingFun ModelTwoArguments
paramModInteger                      = CostingFun ModelTwoArguments
unitCostTwoArguments
    , paramEqualsInteger :: CostingFun ModelTwoArguments
paramEqualsInteger                   = CostingFun ModelTwoArguments
unitCostTwoArguments
    , paramLessThanInteger :: CostingFun ModelTwoArguments
paramLessThanInteger                 = CostingFun ModelTwoArguments
unitCostTwoArguments
    , paramLessThanEqualsInteger :: CostingFun ModelTwoArguments
paramLessThanEqualsInteger           = CostingFun ModelTwoArguments
unitCostTwoArguments
    -- Bytestrings
    , paramAppendByteString :: CostingFun ModelTwoArguments
paramAppendByteString                = CostingFun ModelTwoArguments
unitCostTwoArguments
    , paramConsByteString :: CostingFun ModelTwoArguments
paramConsByteString                  = CostingFun ModelTwoArguments
unitCostTwoArguments
    , paramSliceByteString :: CostingFun ModelThreeArguments
paramSliceByteString                 = CostingFun ModelThreeArguments
unitCostThreeArguments
    , paramLengthOfByteString :: CostingFun ModelOneArgument
paramLengthOfByteString              = CostingFun ModelOneArgument
unitCostOneArgument
    , paramIndexByteString :: CostingFun ModelTwoArguments
paramIndexByteString                 = CostingFun ModelTwoArguments
unitCostTwoArguments
    , paramEqualsByteString :: CostingFun ModelTwoArguments
paramEqualsByteString                = CostingFun ModelTwoArguments
unitCostTwoArguments
    , paramLessThanByteString :: CostingFun ModelTwoArguments
paramLessThanByteString              = CostingFun ModelTwoArguments
unitCostTwoArguments
    , paramLessThanEqualsByteString :: CostingFun ModelTwoArguments
paramLessThanEqualsByteString        = CostingFun ModelTwoArguments
unitCostTwoArguments
    -- Cryptography and hashes
    , paramSha2_256 :: CostingFun ModelOneArgument
paramSha2_256                        = CostingFun ModelOneArgument
unitCostOneArgument
    , paramSha3_256 :: CostingFun ModelOneArgument
paramSha3_256                        = CostingFun ModelOneArgument
unitCostOneArgument
    , paramBlake2b_256 :: CostingFun ModelOneArgument
paramBlake2b_256                     = CostingFun ModelOneArgument
unitCostOneArgument
    , paramVerifyEd25519Signature :: CostingFun ModelThreeArguments
paramVerifyEd25519Signature          = CostingFun ModelThreeArguments
unitCostThreeArguments
    , paramVerifyEcdsaSecp256k1Signature :: CostingFun ModelThreeArguments
paramVerifyEcdsaSecp256k1Signature   = CostingFun ModelThreeArguments
unitCostThreeArguments
    , paramVerifySchnorrSecp256k1Signature :: CostingFun ModelThreeArguments
paramVerifySchnorrSecp256k1Signature = CostingFun ModelThreeArguments
unitCostThreeArguments
    -- Strings
    , paramAppendString :: CostingFun ModelTwoArguments
paramAppendString                    = CostingFun ModelTwoArguments
unitCostTwoArguments
    , paramEqualsString :: CostingFun ModelTwoArguments
paramEqualsString                    = CostingFun ModelTwoArguments
unitCostTwoArguments
    , paramEncodeUtf8 :: CostingFun ModelOneArgument
paramEncodeUtf8                      = CostingFun ModelOneArgument
unitCostOneArgument
    , paramDecodeUtf8 :: CostingFun ModelOneArgument
paramDecodeUtf8                      = CostingFun ModelOneArgument
unitCostOneArgument
    -- Bool
    , paramIfThenElse :: CostingFun ModelThreeArguments
paramIfThenElse                      = CostingFun ModelThreeArguments
unitCostThreeArguments
    -- Unit
    , paramChooseUnit :: CostingFun ModelTwoArguments
paramChooseUnit                      = CostingFun ModelTwoArguments
unitCostTwoArguments
    -- Tracing
    , paramTrace :: CostingFun ModelTwoArguments
paramTrace                           = CostingFun ModelTwoArguments
unitCostTwoArguments
    -- Pairs
    , paramFstPair :: CostingFun ModelOneArgument
paramFstPair                         = CostingFun ModelOneArgument
unitCostOneArgument
    , paramSndPair :: CostingFun ModelOneArgument
paramSndPair                         = CostingFun ModelOneArgument
unitCostOneArgument
    -- Lists
    , paramChooseList :: CostingFun ModelThreeArguments
paramChooseList                      = CostingFun ModelThreeArguments
unitCostThreeArguments
    , paramMkCons :: CostingFun ModelTwoArguments
paramMkCons                          = CostingFun ModelTwoArguments
unitCostTwoArguments
    , paramHeadList :: CostingFun ModelOneArgument
paramHeadList                        = CostingFun ModelOneArgument
unitCostOneArgument
    , paramTailList :: CostingFun ModelOneArgument
paramTailList                        = CostingFun ModelOneArgument
unitCostOneArgument
    , paramNullList :: CostingFun ModelOneArgument
paramNullList                        = CostingFun ModelOneArgument
unitCostOneArgument
    -- Data
    , paramChooseData :: CostingFun ModelSixArguments
paramChooseData                      = CostingFun ModelSixArguments
unitCostSixArguments
    , paramConstrData :: CostingFun ModelTwoArguments
paramConstrData                      = CostingFun ModelTwoArguments
unitCostTwoArguments
    , paramMapData :: CostingFun ModelOneArgument
paramMapData                         = CostingFun ModelOneArgument
unitCostOneArgument
    , paramListData :: CostingFun ModelOneArgument
paramListData                        = CostingFun ModelOneArgument
unitCostOneArgument
    , paramIData :: CostingFun ModelOneArgument
paramIData                           = CostingFun ModelOneArgument
unitCostOneArgument
    , paramBData :: CostingFun ModelOneArgument
paramBData                           = CostingFun ModelOneArgument
unitCostOneArgument
    , paramUnConstrData :: CostingFun ModelOneArgument
paramUnConstrData                    = CostingFun ModelOneArgument
unitCostOneArgument
    , paramUnMapData :: CostingFun ModelOneArgument
paramUnMapData                       = CostingFun ModelOneArgument
unitCostOneArgument
    , paramUnListData :: CostingFun ModelOneArgument
paramUnListData                      = CostingFun ModelOneArgument
unitCostOneArgument
    , paramUnIData :: CostingFun ModelOneArgument
paramUnIData                         = CostingFun ModelOneArgument
unitCostOneArgument
    , paramUnBData :: CostingFun ModelOneArgument
paramUnBData                         = CostingFun ModelOneArgument
unitCostOneArgument
    , paramEqualsData :: CostingFun ModelTwoArguments
paramEqualsData                      = CostingFun ModelTwoArguments
unitCostTwoArguments
    -- Misc constructors
    , paramMkPairData :: CostingFun ModelTwoArguments
paramMkPairData                      = CostingFun ModelTwoArguments
unitCostTwoArguments
    , paramMkNilData :: CostingFun ModelOneArgument
paramMkNilData                       = CostingFun ModelOneArgument
unitCostOneArgument
    , paramMkNilPairData :: CostingFun ModelOneArgument
paramMkNilPairData                   = CostingFun ModelOneArgument
unitCostOneArgument
    , paramSerialiseData :: CostingFun ModelOneArgument
paramSerialiseData                   = CostingFun ModelOneArgument
unitCostOneArgument
    }