Skip to content

Reference inputs improvements #482

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 80 commits into from
May 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
06c7b00
improve testing framework
mmontin Apr 10, 2025
6b9c2c4
updating docs
mmontin Apr 10, 2025
f84d6d2
Update CHANGELOG.md
mmontin Apr 11, 2025
909534b
initial refactoring of pretty modules
mmontin Apr 11, 2025
f0779de
finishing skeleton
mmontin Apr 11, 2025
5adfc33
adding mockchain.hs in pretty
mmontin Apr 11, 2025
87796ac
PrettyCookedL instead of PrettyCooked for skeletons
mmontin Apr 14, 2025
3347de5
only instances in Skeleton
mmontin Apr 14, 2025
b54e353
type applying [DocCooked] properly
mmontin Apr 14, 2025
7d0ebd5
Mockchain.hs revamped
mmontin Apr 14, 2025
fc7eca2
updating documentation
mmontin Apr 14, 2025
0f46b08
changelog
mmontin Apr 14, 2025
09b3f58
first mockchainst adjustment
mmontin Apr 14, 2025
d93759e
TxSkelOutDatum to DatumContent
mmontin Apr 15, 2025
68c07b2
Merge branch 'main' into mm/improve-testing
mmontin Apr 16, 2025
213d9c2
Merge branch 'main' into mm/improve-testing
mmontin Apr 17, 2025
d7d27e1
Merge branch 'main' into mm/pretty-printer
mmontin Apr 17, 2025
8e830f1
Merge branch 'mm/pretty-printer' into mm/better-mockchainst
mmontin Apr 17, 2025
a7e5d30
fixing doc warnings
mmontin Apr 17, 2025
1a8091d
fixing doc
mmontin Apr 17, 2025
6f5207e
Merge branch 'main' into mm/improve-testing
mmontin Apr 17, 2025
3fb54e4
Merge branch 'main' into mm/pretty-printer
mmontin Apr 17, 2025
6dbead7
Merge branch 'mm/pretty-printer' into mm/better-mockchainst
mmontin Apr 17, 2025
e3af6f2
Merge branch 'main' into mm/improve-testing
mmontin Apr 19, 2025
188b0db
nice merge
mmontin Apr 19, 2025
e29c1e8
rollback after merge error
mmontin Apr 19, 2025
fd127e6
unsafe helpers
mmontin Apr 20, 2025
f93d7a5
WIP
mmontin Apr 22, 2025
46ffbd0
merging main into this
mmontin Apr 22, 2025
15d1ff6
clarifying and simplifying errors
mmontin Apr 22, 2025
356dbcc
more refinement of errors
mmontin Apr 22, 2025
95d1834
Refactoring of outputs WIP
mmontin Apr 22, 2025
afc65c2
all tests pass
mmontin Apr 23, 2025
c416083
No more doc warnings
mmontin Apr 23, 2025
2b9a8ad
bye bye datum and script hashes maps
mmontin Apr 23, 2025
de86e5b
updating MockChainReturn
mmontin Apr 24, 2025
d26ba47
adding doc comments
mmontin Apr 24, 2025
d99179f
some cleaning up
mmontin Apr 24, 2025
48ae489
better printing
mmontin Apr 25, 2025
6e1aed6
tests pass now, but need to investigate the ledger state update in CNE
mmontin Apr 25, 2025
7e40d42
lighter init dist, printing of list of MockChainReturn
mmontin Apr 26, 2025
fe08b48
exploring the bug
mmontin Apr 26, 2025
dd92558
getting there
mmontin Apr 28, 2025
a8fae34
no more TxBodyError
mmontin Apr 28, 2025
9861623
fix count of key witnesses
mmontin Apr 29, 2025
edc6cf3
Proper execution units computation
mmontin Apr 29, 2025
7a23628
supporting proposals
mmontin Apr 29, 2025
9c88b14
update flake and body
mmontin Apr 30, 2025
6ecdc25
proposing scripts tests
mmontin Apr 30, 2025
459aafe
handling withdrawals!
mmontin Apr 30, 2025
21e9033
wallet withdrawals
mmontin May 1, 2025
5ec2a18
removing usless comments, reorganizing Blockchain.hs
mmontin May 6, 2025
b4de056
cooked v6.0.0 release
mmontin May 6, 2025
fc8a6d5
Merge branch 'mm/release-cooked-v6' into mm/better-mockchainst
mmontin May 6, 2025
0252026
ensuring the proper version of cardano-api
mmontin May 6, 2025
4defaa4
add export in Proposal
mmontin May 6, 2025
31beee1
full changelog
mmontin May 6, 2025
aa40aee
updating cheatsheet
mmontin May 6, 2025
ea7a700
updating the conway doc
mmontin May 6, 2025
f29b046
time
mmontin May 7, 2025
1dd4663
fixing tests
mmontin May 12, 2025
eff2164
Merge branch 'main' into mm/better-mockchainst
mmontin May 19, 2025
e969d60
Merge branch 'mm/better-mockchainst' into mm/time-management
mmontin May 19, 2025
0581638
updating to capi 10.16 with proper handling of ref input data hashes
mmontin May 19, 2025
7db188e
proper handling of reference inputs in inputs
mmontin May 19, 2025
7ad1f12
changelog updated
mmontin May 19, 2025
5f50ea0
adding a test for reference scripts in inputs
mmontin May 19, 2025
e47bb6b
adding test, removing extra log event
mmontin May 19, 2025
17a44d8
changelog
mmontin May 19, 2025
21a83de
Merge branch 'mm/time-management' into mm/inputs-and-ref-inputs
mmontin May 19, 2025
6af1006
haddock comments
mmontin May 20, 2025
7c860fb
Update CHANGELOG.md
mmontin May 20, 2025
00f3cd2
Merge branch 'main' into mm/time-management
mmontin May 20, 2025
88c9c57
Merge branch 'mm/time-management' into mm/inputs-and-ref-inputs
mmontin May 20, 2025
1256565
more documentation
mmontin May 20, 2025
ac9a54b
improving auto ref script algorithm
mmontin May 20, 2025
90de9b4
Merge branch 'main' into mm/inputs-and-ref-inputs
mmontin May 21, 2025
58e3019
Update src/Cooked/MockChain/GenerateTx/ReferenceInputs.hs
mmontin May 23, 2025
81fb34b
update cabal.project and flake.lock (#483)
mmontin May 28, 2025
e020085
clarifying test on ref input in inputs
mmontin May 28, 2025
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@
estimated by cardano-api while it is in fact found in the skeleton itself.
- A bug where the execution units of the scripts were not computed and fed to
the transaction body.
- An imprecision where reference inputs in redeemers that also appear in inputs
would be kept in the reference inputs list during generation.

## [[6.0.0]](https://github.com/tweag/cooked-validators/releases/tag/v6.0.0) - 2025-05-15

Expand Down
8 changes: 4 additions & 4 deletions cabal.project
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ repository cardano-haskell-packages

index-state:
, hackage.haskell.org 2025-04-16T16:04:13Z
, cardano-haskell-packages 2025-04-25T15:50:18Z
, cardano-haskell-packages 2025-05-16T15:25:35Z

-- We never, ever, want this.
write-ghc-environment-files: never
Expand All @@ -47,12 +47,12 @@ package cardano-crypto-praos
flags: -external-libsodium-vrf

constraints:
cardano-api ^>= 10.15
cardano-api == 10.16.1.0

source-repository-package
type: git
location: https://github.com/tweag/cardano-node-emulator-forked
tag: 93de6dc68244eed1eb439fb0c7753e8b513b7aa4
location: https://github.com/intersectMBO/cardano-node-emulator
tag: 6d65996418d2b00fa791407ec47e2fe77c208790
subdir:
plutus-script-utils
plutus-ledger
Expand Down
3 changes: 2 additions & 1 deletion cooked-validators.cabal
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cabal-version: 3.4

-- This file has been generated from package.yaml by hpack version 0.36.1.
-- This file has been generated from package.yaml by hpack version 0.37.0.
--
-- see: https://github.com/sol/hpack

Expand Down Expand Up @@ -33,6 +33,7 @@ library
Cooked.MockChain.GenerateTx.Mint
Cooked.MockChain.GenerateTx.Output
Cooked.MockChain.GenerateTx.Proposal
Cooked.MockChain.GenerateTx.ReferenceInputs
Cooked.MockChain.GenerateTx.Withdrawals
Cooked.MockChain.GenerateTx.Witness
Cooked.MockChain.MinAda
Expand Down
12 changes: 6 additions & 6 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

53 changes: 29 additions & 24 deletions src/Cooked/MockChain/AutoReferenceScripts.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,49 +7,54 @@ import Control.Monad
import Cooked.MockChain.BlockChain
import Cooked.MockChain.UtxoSearch
import Cooked.Skeleton
import Data.List (find)
import Data.Map qualified as Map
import Data.Maybe
import Optics.Core
import Plutus.Script.Utils.Scripts qualified as Script
import PlutusLedgerApi.V3 qualified as Api

-- | Searches through the known utxos for a utxo containing a reference script
-- with a given script hash, and returns the first such utxo found, if any.
retrieveReferenceScript :: (MonadBlockChain m, Script.ToScriptHash s) => s -> m (Maybe Api.TxOutRef)
retrieveReferenceScript = (listToMaybe . (fst <$>) <$>) . runUtxoSearch . referenceScriptOutputsSearch

-- | Attempts to find in the index a utxo containing a reference script with the
-- given script hash, and attaches it to a redeemer when it does not yet have a
-- reference input and when it is allowed, in which case an event is logged.
updateRedeemer :: (MonadBlockChain m, Script.ToScriptHash s) => s -> TxSkelRedeemer -> m TxSkelRedeemer
updateRedeemer script txSkelRed@(TxSkelRedeemer _ Nothing True) = do
oRefM <- retrieveReferenceScript script
case oRefM of
Nothing -> return txSkelRed
Just oRef -> do
logEvent $ MCLogAddedReferenceScript txSkelRed oRef (Script.toScriptHash script)
return $ txSkelRed `withReferenceInput` oRef
updateRedeemer _ redeemer = return redeemer
updateRedeemer :: (MonadBlockChain m, Script.ToScriptHash s) => s -> [Api.TxOutRef] -> TxSkelRedeemer -> m TxSkelRedeemer
updateRedeemer script inputs txSkelRed@(TxSkelRedeemer _ Nothing True) = do
oRefsInInputs <- runUtxoSearch (referenceScriptOutputsSearch script)
maybe
-- We leave the redeemer unchanged if no reference input was found
(return txSkelRed)
-- If a reference input is found, we assign it and log the event
( \oRef -> do
logEvent $ MCLogAddedReferenceScript txSkelRed oRef (Script.toScriptHash script)
return $ txSkelRed `withReferenceInput` oRef
)
$ case oRefsInInputs of
[] -> Nothing
-- If possible, we use a reference input appearing in regular inputs
l | Just (oRefM', _) <- find (\(r, _) -> r `elem` inputs) l -> Just oRefM'
-- If none exist, we use the first one we find elsewhere
((oRefM', _) : _) -> Just oRefM'
updateRedeemer _ _ redeemer = return redeemer

-- | Goes through the various parts of the skeleton where a redeemer can appear,
-- and attempts to attach a reference input to each of them, whenever it is
-- allowed and one has not already been set.
toTxSkelWithReferenceScripts :: (MonadBlockChain m) => TxSkel -> m TxSkel
toTxSkelWithReferenceScripts txSkel = do
newMints <- forM (txSkelMintsToList $ txSkel ^. txSkelMintsL) $ \(Mint mPol red tks) ->
(\x -> Mint mPol x tks) <$> updateRedeemer (Script.toVersioned @Script.MintingPolicy mPol) red
newInputs <- forM (Map.toList $ txSkel ^. txSkelInsL) $ \(oRef, red) -> do
toTxSkelWithReferenceScripts txSkel@TxSkel {..} = do
let inputs = Map.keys txSkelIns
newMints <- forM (txSkelMintsToList txSkelMints) $ \(Mint mPol red tks) ->
(\x -> Mint mPol x tks) <$> updateRedeemer (Script.toVersioned @Script.MintingPolicy mPol) inputs red
newInputs <- forM (Map.toList txSkelIns) $ \(oRef, red) -> do
validatorM <- txSkelOutValidator <$> unsafeTxOutByRef oRef
case validatorM of
Nothing -> return (oRef, red)
Just scriptHash -> (oRef,) <$> updateRedeemer scriptHash red
newProposals <- forM (txSkel ^. txSkelProposalsL) $ \prop ->
Just scriptHash -> (oRef,) <$> updateRedeemer scriptHash inputs red
newProposals <- forM txSkelProposals $ \prop ->
case prop ^. txSkelProposalWitnessL of
Nothing -> return prop
Just (script, red) -> flip (set txSkelProposalWitnessL) prop . Just . (script,) <$> updateRedeemer script red
newWithdrawals <- forM (Map.toList $ txSkel ^. txSkelWithdrawalsL) $ \(wit, (red, quantity)) -> case wit of
Just (script, red) -> flip (set txSkelProposalWitnessL) prop . Just . (script,) <$> updateRedeemer script inputs red
newWithdrawals <- forM (Map.toList txSkelWithdrawals) $ \(wit, (red, quantity)) -> case wit of
Right _ -> return (wit, (red, quantity))
Left script -> (Left script,) . (,quantity) <$> updateRedeemer script red
Left script -> (Left script,) . (,quantity) <$> updateRedeemer script inputs red
return $
txSkel
& txSkelMintsL
Expand Down
114 changes: 29 additions & 85 deletions src/Cooked/MockChain/GenerateTx/Body.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,29 @@ where

import Cardano.Api qualified as Cardano
import Cardano.Api.Internal.Fees qualified as Cardano
import Cardano.Api.Internal.ProtocolParameters qualified as Cardano
import Cardano.Api.Internal.Script qualified as Cardano
import Cardano.Api.Internal.Tx.Body qualified as Cardano
import Cardano.Api.Ledger qualified as Cardano
import Cardano.Ledger.Alonzo.Tx qualified as Alonzo
import Cardano.Ledger.Alonzo.TxBody qualified as Alonzo
import Cardano.Ledger.Alonzo.TxWits qualified as Alonzo
import Cardano.Ledger.Conway.PParams qualified as Conway
import Cardano.Ledger.Plutus qualified as Cardano
import Cardano.Node.Emulator.Internal.Node qualified as Emulator
import Control.Lens qualified as Lens
import Control.Monad
import Control.Monad.Except
import Cooked.MockChain.BlockChain
import Cooked.MockChain.GenerateTx.Collateral qualified as Collateral
import Cooked.MockChain.GenerateTx.Collateral
import Cooked.MockChain.GenerateTx.Common
import Cooked.MockChain.GenerateTx.Input qualified as Input
import Cooked.MockChain.GenerateTx.Mint qualified as Mint
import Cooked.MockChain.GenerateTx.Output qualified as Output
import Cooked.MockChain.GenerateTx.Proposal qualified as Proposal
import Cooked.MockChain.GenerateTx.Withdrawals qualified as Withdrawals
import Cooked.MockChain.GenerateTx.Witness qualified as Witness
import Cooked.MockChain.GenerateTx.Input
import Cooked.MockChain.GenerateTx.Mint
import Cooked.MockChain.GenerateTx.Output
import Cooked.MockChain.GenerateTx.Proposal
import Cooked.MockChain.GenerateTx.ReferenceInputs
import Cooked.MockChain.GenerateTx.Withdrawals
import Cooked.MockChain.GenerateTx.Witness
import Cooked.Skeleton
import Cooked.Wallet
import Data.Map qualified as Map
import Data.Set (Set)
import Data.Set qualified as Set
import Ledger.Address qualified as Ledger
import Ledger.Tx.CardanoAPI qualified as Ledger
import Optics.Core
import Plutus.Script.Utils.Address qualified as Script
import PlutusLedgerApi.V3 qualified as Api

Expand All @@ -54,23 +47,16 @@ txSkelToTxBodyContent ::
Maybe (Set Api.TxOutRef, Wallet) ->
-- | Returns a Cardano body content
m (Cardano.TxBodyContent Cardano.BuildTx Cardano.ConwayEra)
txSkelToTxBodyContent skel@TxSkel {..} fee mCollaterals | txSkelReferenceInputs <- txSkelReferenceTxOutRefs skel = do
txIns <- mapM Input.toTxInAndWitness $ Map.toList txSkelIns
txInsReference <-
if null txSkelReferenceInputs
then return Cardano.TxInsReferenceNone
else
throwOnToCardanoErrorOrApply
"txSkelToBodyContent: Unable to translate reference inputs."
(Cardano.TxInsReference Cardano.BabbageEraOnwardsConway)
$ mapM Ledger.toCardanoTxIn txSkelReferenceInputs
(txInsCollateral, txTotalCollateral, txReturnCollateral) <- Collateral.toCollateralTriplet fee mCollaterals
txOuts <- mapM Output.toCardanoTxOut txSkelOuts
txSkelToTxBodyContent skel@TxSkel {..} fee mCollaterals = do
txIns <- mapM toTxInAndWitness $ Map.toList txSkelIns
txInsReference <- toInsReference skel
(txInsCollateral, txTotalCollateral, txReturnCollateral) <- toCollateralTriplet fee mCollaterals
txOuts <- mapM toCardanoTxOut txSkelOuts
(txValidityLowerBound, txValidityUpperBound) <-
throwOnToCardanoError
"txSkelToBodyContent: Unable to translate transaction validity range."
$ Ledger.toCardanoValidityRange txSkelValidityRange
txMintValue <- Mint.toMintValue txSkelMints
txMintValue <- toMintValue txSkelMints
txExtraKeyWits <-
if null txSkelSigners
then return Cardano.TxExtraKeyWitnessesNone
Expand All @@ -80,12 +66,12 @@ txSkelToTxBodyContent skel@TxSkel {..} fee mCollaterals | txSkelReferenceInputs
(Cardano.TxExtraKeyWitnesses Cardano.AlonzoEraOnwardsConway)
$ mapM (Ledger.toCardanoPaymentKeyHash . Ledger.PaymentPubKeyHash . Script.toPubKeyHash) txSkelSigners
txProtocolParams <- Cardano.BuildTxWith . Just . Emulator.ledgerProtocolParameters <$> getParams
let txFee = Cardano.TxFeeExplicit Cardano.ShelleyBasedEraConway $ Cardano.Coin fee
txProposalProcedures <-
Just . Cardano.Featured Cardano.ConwayEraOnwardsConway
<$> Proposal.toProposalProcedures txSkelProposals (txOptAnchorResolution txSkelOpts)
txWithdrawals <- Withdrawals.toWithdrawals txSkelWithdrawals
let txMetadata = Cardano.TxMetadataNone
<$> toProposalProcedures txSkelProposals (txOptAnchorResolution txSkelOpts)
txWithdrawals <- toWithdrawals txSkelWithdrawals
let txFee = Cardano.TxFeeExplicit Cardano.ShelleyBasedEraConway $ Cardano.Coin fee
txMetadata = Cardano.TxMetadataNone
txAuxScripts = Cardano.TxAuxScriptsNone
txUpdateProposal = Cardano.TxUpdateProposalNone
txCertificates = Cardano.TxCertificatesNone
Expand All @@ -96,56 +82,14 @@ txSkelToTxBodyContent skel@TxSkel {..} fee mCollaterals | txSkelReferenceInputs
return Cardano.TxBodyContent {..}

-- | Generates a transaction body from a body content
txBodyContentToTxBody :: (MonadBlockChainBalancing m) => Cardano.TxBodyContent Cardano.BuildTx Cardano.ConwayEra -> TxSkel -> m (Cardano.TxBody Cardano.ConwayEra)
txBodyContentToTxBody txBodyContent skel = do
txBodyContentToTxBody :: (MonadBlockChainBalancing m) => Cardano.TxBodyContent Cardano.BuildTx Cardano.ConwayEra -> m (Cardano.TxBody Cardano.ConwayEra)
txBodyContentToTxBody txBodyContent = do
params <- getParams
-- We create the associated Shelley TxBody
txBody@(Cardano.ShelleyTxBody a body c dats e f) <-
either
(throwError . MCEToCardanoError "generateTx :")
return
(Emulator.createTransactionBody params (Ledger.CardanoBuildTx txBodyContent))

-- There is a chance that the body is in need of additional data. This happens
-- when the set of reference inputs contains hashed datums that will need to
-- be resolved during phase 2 validation. All that follows aims at doing just
-- that. In the process, we have to reconstruct the body with the new data and
-- the associated hash. Hopefully, in the future, cardano-api provides a way
-- to add those data in the body directly without requiring this method, which
-- somewhat feels like a hack.

-- We gather the datums of the reference inputs in the skeleton
refIns <- forM (txSkelReferenceTxOutRefs skel) $ fmap (view txSkelOutDatumL) . unsafeTxOutByRef
-- We collect the additional data of the hashed datums as a map
let additionalDataMap =
Map.fromList [(Cardano.hashData dat, dat) | TxSkelOutSomeDatum (Cardano.Data . Api.toData -> dat) (Hashed _) <- refIns]
-- We return the body directly if no additional data is required
if null additionalDataMap
then return txBody
else do
-- We retrieve a needed parameter to process difference plutus languages
toLangDepViewParam <- Conway.getLanguageView . Cardano.unLedgerProtocolParameters . Emulator.ledgerProtocolParameters <$> getParams
-- We convert our data map into a 'TxDats'
let txDats' = Alonzo.TxDats additionalDataMap
-- We compute the new era, datums and redeemers based on the current dats
-- in the body and the additional data to include in the body.
(era, datums, redeemers) = case dats of
Cardano.TxBodyNoScriptData -> (Cardano.AlonzoEraOnwardsConway, txDats', Alonzo.Redeemers Map.empty)
Cardano.TxBodyScriptData era' txDats reds -> (era', txDats <> txDats', reds)
-- We collect the various witnesses in the body
witnesses = Cardano.collectTxBodyScriptWitnesses Cardano.ShelleyBasedEraConway txBodyContent
-- We collect their languages and convert them to Ledger languages
languages =
[ Cardano.toAlonzoScriptLanguage (Cardano.AnyPlutusScriptVersion v)
| (_, Cardano.AnyScriptWitness (Cardano.PlutusScriptWitness _ v _ _ _ _)) <- witnesses
]
-- We compute the new script integrity hash with the added data
scriptIntegrityHash =
Cardano.alonzoEraOnwardsConstraints era $
Alonzo.hashScriptIntegrity (Set.fromList $ toLangDepViewParam <$> languages) redeemers datums
-- We wrap all of this in the new body
body' = body & Alonzo.scriptIntegrityHashTxBodyL Lens..~ scriptIntegrityHash
return $ Cardano.ShelleyTxBody a body' c (Cardano.TxBodyScriptData era datums redeemers) e f
either
(throwError . MCEToCardanoError "generateTx :")
return
(Emulator.createTransactionBody params (Ledger.CardanoBuildTx txBodyContent))

-- | Generates an index with utxos known to a 'TxSkel'
txSkelToIndex :: (MonadBlockChainBalancing m) => TxSkel -> Maybe (Set Api.TxOutRef, Wallet) -> m (Cardano.UTxO Cardano.ConwayEra)
Expand All @@ -156,9 +100,9 @@ txSkelToIndex txSkel mCollaterals = do
Nothing -> []
Just (s, _) -> Set.toList s
-- We retrieve all the outputs known to the skeleton
(knownTxORefs, knownTxOuts) <- unzip . Map.toList <$> lookupUtxos (txSkelKnownTxOutRefs txSkel <> collateralIns)
(knownTxORefs, knownTxOuts) <- unzip . Map.toList <$> lookupUtxos (Set.toList (txSkelKnownTxOutRefs txSkel) <> collateralIns)
-- We then compute their Cardano counterparts
txOutL <- forM knownTxOuts Output.toCardanoTxOut
txOutL <- forM knownTxOuts toCardanoTxOut
-- We build the index and handle the possible error
either (throwError . MCEToCardanoError "txSkelToIndex:") return $ do
txInL <- forM knownTxORefs Ledger.toCardanoTxIn
Expand All @@ -171,9 +115,9 @@ txSkelToTxBody :: (MonadBlockChainBalancing m) => TxSkel -> Integer -> Maybe (Se
txSkelToTxBody txSkel fee mCollaterals = do
-- We create a first body content and body, without execution units
txBodyContent' <- txSkelToTxBodyContent txSkel fee mCollaterals
txBody' <- txBodyContentToTxBody txBodyContent' txSkel
txBody' <- txBodyContentToTxBody txBodyContent'
-- We create a full transaction from the body
let tx' = Cardano.Tx txBody' (Witness.toKeyWitness txBody' <$> txSkelSigners txSkel)
let tx' = Cardano.Tx txBody' (toKeyWitness txBody' <$> txSkelSigners txSkel)
-- We retrieve the index and parameters to feed to @getTxExUnitsWithLogs@
index <- txSkelToIndex txSkel mCollaterals
params <- getParams
Expand All @@ -191,4 +135,4 @@ txSkelToTxBody txSkel fee mCollaterals = do
Left _ -> throwError $ FailWith "Error while assigning execution units"
-- We now have a body content with proper execution units and can create
-- the final body from it
Right txBody -> txBodyContentToTxBody txBody txSkel
Right txBody -> txBodyContentToTxBody txBody
38 changes: 38 additions & 0 deletions src/Cooked/MockChain/GenerateTx/ReferenceInputs.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
-- | This module allows the generation of Cardano reference inputs
module Cooked.MockChain.GenerateTx.ReferenceInputs (toInsReference) where

import Cardano.Api qualified as Cardano
import Cooked.MockChain.BlockChain
import Cooked.MockChain.GenerateTx.Common
import Cooked.Skeleton
import Data.Map qualified as Map
import Data.Set qualified as Set
import Ledger.Tx.CardanoAPI qualified as Ledger
import PlutusLedgerApi.V3 qualified as Api

-- | Takes a 'TxSkel' and generates the associated 'Cardano.TxInsReference' from
-- its content. These reference inputs can be found in two places, either in
-- direct reference inputs 'txSkelInsReference' or scattered in the various
-- redeemers of the transaction, which can be gathered with
-- 'txSkelInsReferenceInRedeemers'.
toInsReference :: (MonadBlockChainBalancing m) => TxSkel -> m (Cardano.TxInsReference Cardano.BuildTx Cardano.ConwayEra)
toInsReference skel = do
-- As regular inputs can be used to hold scripts as if in reference inputs, we
-- need to remove from the reference inputs stored in redeemers the ones that
-- already appear in the inputs to avoid validation errors.
let indirectReferenceInputs = txSkelInsReferenceInRedeemers skel
redundantReferenceInputs = indirectReferenceInputs `Set.intersection` Map.keysSet (txSkelIns skel)
refInputs = Set.toList (txSkelInsReference skel <> indirectReferenceInputs `Set.difference` redundantReferenceInputs)
if null refInputs
then return Cardano.TxInsReferenceNone
else do
cardanoRefInputs <-
throwOnToCardanoError
"toInsReference: Unable to translate reference inputs."
(mapM Ledger.toCardanoTxIn refInputs)
resolvedOutputs <- mapM unsafeDatumFromTxOutRef refInputs
return $
Cardano.TxInsReference Cardano.BabbageEraOnwardsConway cardanoRefInputs $
Cardano.BuildTxWith $
Set.fromList
[Ledger.toCardanoScriptData $ Api.toBuiltinData dat | TxSkelOutSomeDatum dat (Hashed _) <- resolvedOutputs]
Loading