Skip to content

Commit 8d46065

Browse files
committed
Update tx-generator to not use deprecated cardano-api api
1 parent 4fa3e6c commit 8d46065

14 files changed

Lines changed: 352 additions & 377 deletions

File tree

bench/tx-generator/app/calibrate-script.hs

Lines changed: 105 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,33 @@
11
{-# LANGUAGE CPP #-}
2+
{-# LANGUAGE DataKinds #-}
23
{-# LANGUAGE GADTs #-}
34
{-# LANGUAGE LambdaCase #-}
45
{-# LANGUAGE NamedFieldPuns #-}
56
{-# LANGUAGE NumericUnderscores #-}
7+
{-# LANGUAGE RankNTypes #-}
68
{-# LANGUAGE OverloadedStrings #-}
79
{-# LANGUAGE RecordWildCards #-}
810
{-# LANGUAGE ScopedTypeVariables #-}
911
{-# LANGUAGE TypeApplications #-}
1012

1113
{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
1214

13-
import Cardano.Api
15+
import Cardano.Api hiding (eraProtVerHigh)
16+
import Cardano.Api.Experimental (AnyWitness (..), IsEra (useEra),
17+
PlutusScriptDatum (..), PlutusScriptPurpose (..), SignedTx (..),
18+
eraProtVerHigh, makeKeyWitness, makeUnsignedTx,
19+
obtainCommonConstraints, signTx, toPlutusSLanguage)
20+
import Cardano.Api.Experimental.AnyScriptWitness (AnyPlutusScriptWitness (..),
21+
createPlutusSpendingScriptWitness)
22+
import qualified Cardano.Api.Experimental as Exp (PlutusScriptInEra (..),
23+
PlutusScriptOrReferenceInput (..), PlutusScriptWitness (..),
24+
evaluateTransactionFee)
25+
import Cardano.Api.Experimental.Plutus (AnyPlutusScript (..),
26+
plutusScriptInEraSLanguage)
27+
import qualified Cardano.Api.Experimental.Tx as Exp
28+
29+
import qualified Cardano.Ledger.Plutus.Language as L (PlutusLanguage, Plutus (..), PlutusBinary (..),
30+
SLanguage (..), decodePlutusRunnable)
1431

1532
import Cardano.Benchmarking.Compiler (keyBenchmarkInputs)
1633
import Cardano.Benchmarking.GeneratorTx.SizedMetadata (mkMetadata)
@@ -19,21 +36,22 @@ import Cardano.Benchmarking.PlutusScripts (listPlutusScripts)
1936
#endif
2037
import Cardano.TxGenerator.Calibrate.Utils
2138
import Cardano.TxGenerator.PlutusContext
22-
import Cardano.TxGenerator.ProtocolParameters ( ProtocolParameters (..), convertToLedgerProtocolParameters,
23-
toLedgerPParams)
39+
import Cardano.TxGenerator.ProtocolParameters (ProtocolParameters (..),
40+
convertToLedgerProtocolParameters)
2441
import Cardano.TxGenerator.Setup.Plutus
2542
import Cardano.TxGenerator.Tx (txSizeInBytes)
2643
import Cardano.TxGenerator.Types
2744
import Cardano.TxGenerator.Utils (keyAddress, mkTxIn)
2845

2946
import Control.Exception
47+
import Data.Typeable (Typeable)
3048
import Data.Aeson (decodeFileStrict')
3149
import qualified Data.ByteString.Lazy.Char8 as BSL (writeFile)
50+
3251
import Data.Char
3352
import Data.Function (on, (&))
3453
import Data.List (nub, sort, transpose)
3554
import Data.List.Extra (split)
36-
3755
import Data.Map.Strict as Map (Map, empty, fromList, union)
3856
import Data.Maybe
3957
import qualified Data.Text as T
@@ -157,6 +175,17 @@ runPlutus strategy budgetType protoParamFile plutusDef@PlutusOn{..} scales
157175
= do
158176
protocolParameters <- readProtocolParametersOrDie protoParamFile
159177
(script, resolvedTo) <- either (error . show) pure =<< readPlutusScript plutusScript
178+
let era = useEra @ConwayEra
179+
anyPlutusScript <- obtainCommonConstraints era $
180+
case script of
181+
ScriptInAnyLang _lang (PlutusScript version (PlutusScriptSerialised sbs)) -> do
182+
let slang = toPlutusSLanguage version
183+
decode :: forall l. (L.PlutusLanguage l, Typeable l) => L.SLanguage l -> IO (AnyPlutusScript (ShelleyLedgerEra ConwayEra))
184+
decode _ = case L.decodePlutusRunnable @l (eraProtVerHigh era) (L.Plutus (L.PlutusBinary sbs)) of
185+
Left err -> throwIO $ userError $ "script decode failed: " ++ show err
186+
Right runnable -> pure $ AnyPlutusScript (Exp.PlutusScriptInEra runnable)
187+
obtainLangConstraints slang $ decode slang
188+
_ -> throwIO $ userError "expected a Plutus script"
160189

161190
let
162191
redeemerDef = Right plutusDef
@@ -189,7 +218,10 @@ runPlutus strategy budgetType protoParamFile plutusDef@PlutusOn{..} scales
189218
jsonName = "summaries_" ++ scriptName <.> "json"
190219
csvName = "scaling_" ++ scriptName <.> "csv"
191220

192-
summariesWithApprox <- mapM (approximateTxProperties script protocolParameters) summaries
221+
let ledgerProtocolParameters =
222+
either (error . docToString . prettyError) id
223+
$ convertToLedgerProtocolParameters shelleyBasedEra protocolParameters
224+
summariesWithApprox <- mapM (approximateTxProperties anyPlutusScript ledgerProtocolParameters) summaries
193225
writeResultsJSON jsonName summariesWithApprox
194226
writeResultsCSV csvName summariesWithApprox
195227

@@ -481,75 +513,76 @@ writeResultsJSON jsonName summaries = do
481513
-- | Builds a dummy transaction that resembles the ones submitted during some Plutus benchmark and
482514
-- uses it to augment the budget summary with txn size and fee.
483515
-- * If anything fails to evaluate, the summary is returned unchanged.
484-
-- * This function is currently monorphic in the ledger era and will resolve era parameters to Conway.
485-
approximateTxProperties :: ScriptInAnyLang -> ProtocolParameters -> (PlutusBudgetSummary, ScriptRedeemer) -> IO PlutusBudgetSummary
486-
approximateTxProperties script protocolParameters (summary, redeemer) = do
516+
-- * This function is currently monomorphic in the ledger era and will resolve era parameters to Conway.
517+
approximateTxProperties :: AnyPlutusScript (ShelleyLedgerEra ConwayEra) -> LedgerProtocolParameters ConwayEra -> (PlutusBudgetSummary, ScriptRedeemer) -> IO PlutusBudgetSummary
518+
approximateTxProperties (AnyPlutusScript ps) ledgerProtocolParameters (summary, redeemer) = do
487519
putStrLn $ "--> approximating txn size and fee for: " ++ messageId summary
488-
evaluate $ summary
489-
{ projectedTxSize = Just $ txSizeInBytes dummyTx
490-
, projectedTxFee = Just $ evaluateTransactionFee era ledgerPParams2 (getTxBody dummyTx) 2 0 0 -- 1 (script witness) + 1 (collateral) = 2
491-
}
492-
493-
`catch` \(SomeException e) -> do
494-
putStrLn $ "approximation failed: " ++ show e
495-
++ "\n--> using unmodified summary"
496-
pure summary
497-
where
498-
era = ShelleyBasedEraConway
499-
500-
ledgerPParams1 :: LedgerProtocolParameters ConwayEra
501-
ledgerPParams1 =
502-
either (error . docToString . prettyError) id
503-
$ convertToLedgerProtocolParameters era protocolParameters
504-
505-
ledgerPParams2 =
506-
either (error . docToString . prettyError) id
507-
$ toLedgerPParams era protocolParameters
508-
509-
witness :: Witness WitCtxTxIn ConwayEra
510-
witness =
511-
fromMaybe (error "could not get PlutusScriptWitness")
512-
$ case script of
513-
ScriptInAnyLang lang (PlutusScript version script') -> do
514-
scriptLang <- scriptLanguageSupportedInEra era lang
515-
pure
516-
$ ScriptWitness ScriptWitnessForSpending
517-
$ PlutusScriptWitness
518-
scriptLang
519-
version
520-
(PScript script')
521-
(ScriptDatumForTxIn $ Just $ unsafeHashableScriptData $ ScriptDataNumber 0)
522-
redeemer
523-
(budgetUsedPerTxInput summary)
524-
_ -> Nothing
525-
526-
-- build a dummy tx akin to what we'd get in the tx-generator's benchmarking workload;
527-
-- it just needs to be sufficient to get our approximations.
528-
dummyTx :: Tx ConwayEra
529-
dummyTx
530-
= signShelleyTransaction era txbody [WitnessPaymentKey keyBenchmarkInputs]
531-
where
532-
txbody =
533-
either (error . docToString . prettyError) id
534-
$ createTransactionBody era content
535-
536-
content =
537-
defaultTxBodyContent era
538-
& setTxIns [(dummyTxIn 0, BuildTxWith witness)]
539-
& setTxInsCollateral (TxInsCollateral AlonzoEraOnwardsConway [dummyTxIn 1])
540-
& setTxOuts [dummyTxOut]
541-
& setTxValidityLowerBound TxValidityNoLowerBound
542-
& setTxValidityUpperBound (defaultTxValidityUpperBound era)
543-
& setTxMetadata dummyMetadata
544-
& setTxFee (TxFeeExplicit era 1_000_000)
545-
& setTxProtocolParams (BuildTxWith (Just ledgerPParams1))
546-
520+
let
521+
era = useEra @ConwayEra
522+
pparams = unLedgerProtocolParameters ledgerProtocolParameters
523+
slang = plutusScriptInEraSLanguage ps
524+
dummyDatum = unsafeHashableScriptData $ ScriptDataNumber 0
525+
datum = mkSpendingScriptDatum slang dummyDatum
526+
anyWitness =
527+
let witness = Exp.PlutusScriptWitness slang (Exp.PScript ps) datum redeemer (budgetUsedPerTxInput summary)
528+
in AnyPlutusScriptWitness (AnyPlutusSpendingScriptWitness (createPlutusSpendingScriptWitness slang witness))
529+
obtainCommonConstraints era (do
547530
-- Corresponds to the metadata inserted in benchmarking workloads, which is why it's needed for the estimate.
548531
-- default value taken from: `add_tx_size` in nix/nixos/tx-generator-service.nix
549-
dummyMetadata :: TxMetadataInEra ConwayEra
550-
dummyMetadata = either error id $ mkMetadata 100
532+
dummyMetadata <- either (\e -> throwIO $ userError $ "approximateTxProperties: mkMetadata: " ++ e) pure
533+
$ mkMetadata @ConwayEra 100
534+
let
535+
expMetadata = case dummyMetadata of
536+
TxMetadataNone -> mempty
537+
TxMetadataInEra _ m -> m
538+
539+
-- just placeholders
540+
dummyTxIn ix = mkTxIn $ "900fc5da77a0747da53f7675cbb7d149d46779346dea2f879ab811ccc72a2162#" <> textShow @Int ix
541+
dummyTxOut = TxOut (keyAddress (Testnet (NetworkMagic 42)) keyBenchmarkInputs) (lovelaceToTxOutValue shelleyBasedEra 1_000_000) TxOutDatumNone ReferenceScriptNone
542+
543+
-- build a dummy tx akin to what we'd get in the tx-generator's benchmarking workload;
544+
-- it just needs to be sufficient to get our approximations.
545+
txBodyContent =
546+
Exp.defaultTxBodyContent
547+
& Exp.setTxIns [(dummyTxIn 0, anyWitness)]
548+
& Exp.setTxInsCollateral [dummyTxIn 1]
549+
& Exp.setTxOuts [Exp.TxOut $ toShelleyTxOutAny shelleyBasedEra dummyTxOut]
550+
& Exp.setTxFee (Coin 1_000_000)
551+
& Exp.setTxMetadata expMetadata
552+
& Exp.setTxProtocolParams pparams
553+
554+
unsignedTx <- either (\err -> throwIO $ userError $ "approximateTxProperties: " ++ show err) pure
555+
$ makeUnsignedTx era txBodyContent
551556

552-
-- just placeholders
553-
dummyTxIn ix = mkTxIn $ "900fc5da77a0747da53f7675cbb7d149d46779346dea2f879ab811ccc72a2162#" <> textShow @Int ix
554-
dummyTxOut = TxOut (keyAddress (Testnet (NetworkMagic 42)) keyBenchmarkInputs) (lovelaceToTxOutValue era 1_000_000) TxOutDatumNone ReferenceScriptNone
557+
let
558+
witVKey = makeKeyWitness era unsignedTx (WitnessPaymentKey keyBenchmarkInputs)
559+
dummyTx :: Tx ConwayEra
560+
dummyTx =
561+
case signTx era [] [witVKey] unsignedTx of
562+
SignedTx signedLedgerTx -> ShelleyTx shelleyBasedEra signedLedgerTx
563+
564+
pure summary
565+
{ projectedTxSize = Just $ txSizeInBytes dummyTx
566+
, projectedTxFee = Just $ Exp.evaluateTransactionFee pparams unsignedTx 2 0 0 -- 1 (script witness) + 1 (collateral) = 2
567+
}
568+
) `catch` \(SomeException e) -> do
569+
putStrLn $ "approximation failed: " ++ show e
570+
++ "\n--> using unmodified summary"
571+
pure summary
572+
573+
-- TODO: remove these vendored functions and import from
574+
-- Cardano.Api.Experimental when the published cardano-api version includes them.
575+
576+
obtainLangConstraints :: L.SLanguage lang -> ((L.PlutusLanguage lang, Typeable lang) => a) -> a
577+
obtainLangConstraints L.SPlutusV1 f = f
578+
obtainLangConstraints L.SPlutusV2 f = f
579+
obtainLangConstraints L.SPlutusV3 f = f
580+
obtainLangConstraints L.SPlutusV4 f = f
581+
582+
mkSpendingScriptDatum :: L.SLanguage lang -> HashableScriptData -> PlutusScriptDatum lang 'SpendingScript
583+
mkSpendingScriptDatum = \case
584+
L.SPlutusV1 -> SpendingScriptDatum
585+
L.SPlutusV2 -> SpendingScriptDatum
586+
L.SPlutusV3 -> SpendingScriptDatum . Just
587+
L.SPlutusV4 -> SpendingScriptDatum . Just
555588

bench/tx-generator/src/Cardano/Benchmarking/GeneratorTx.hs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
{-# LANGUAGE RankNTypes #-}
55
{-# LANGUAGE RecordWildCards #-}
66
{-# LANGUAGE ScopedTypeVariables #-}
7+
{-# LANGUAGE TypeApplications #-}
78
{-# LANGUAGE UndecidableInstances #-}
89

910
{-# OPTIONS_GHC -Wno-all-missed-specialisations #-}
@@ -19,7 +20,8 @@ module Cardano.Benchmarking.GeneratorTx
1920
, waitBenchmark
2021
) where
2122

22-
import Cardano.Api hiding (txFee, label)
23+
import Cardano.Api hiding (label, txFee)
24+
import Cardano.Api.Experimental (IsEra, obtainCommonConstraints, useEra)
2325

2426
import Cardano.Benchmarking.GeneratorTx.NodeToNode
2527
import Cardano.Benchmarking.GeneratorTx.Submission
@@ -110,7 +112,7 @@ handleTxSubmissionClientError
110112
LogErrors -> traceWith traceSubmit $
111113
TraceBenchTxSubError (pack errDesc)
112114

113-
walletBenchmark :: forall era. IsShelleyBasedEra era
115+
walletBenchmark :: forall era. IsEra era
114116
=> Trace IO (TraceBenchTxSubmit TxId)
115117
-> Trace IO NodeToNodeSubmissionTrace
116118
-> ConnectClient
@@ -137,7 +139,7 @@ walletBenchmark
137139
_era
138140
count
139141
txSource
140-
= liftIO $ do
142+
= obtainCommonConstraints (useEra @era) $ liftIO $ do
141143
traceDebug "******* Tx generator, phase 2: pay to recipients *******"
142144

143145
let numTargets :: Natural = fromIntegral $ NE.length targets

0 commit comments

Comments
 (0)