@@ -301,6 +301,8 @@ module Cardano.Api.Internal.Tx.Body
301301 -- ** Other transaction body types
302302 , TxInsCollateral (.. )
303303 , TxInsReference (.. )
304+ , TxInsReferenceActualDatums
305+ , getReferenceInputDatumMap
304306 , TxReturnCollateral (.. )
305307 , TxTotalCollateral (.. )
306308 , TxFee (.. )
@@ -432,6 +434,8 @@ import Cardano.Api.Internal.SerialiseJSON
432434import Cardano.Api.Internal.Tx.BuildTxWith
433435import Cardano.Api.Internal.Tx.Output
434436import Cardano.Api.Internal.Tx.Sign
437+ import Cardano.Api.Internal.Tx.UTxO (UTxO )
438+ import Cardano.Api.Internal.Tx.UTxO qualified as UTxO
435439import Cardano.Api.Internal.TxIn
436440import Cardano.Api.Internal.TxMetadata
437441import Cardano.Api.Internal.Utils
@@ -570,16 +574,32 @@ deriving instance Eq (TxTotalCollateral era)
570574
571575deriving instance Show (TxTotalCollateral era )
572576
573- data TxInsReference era where
574- TxInsReferenceNone :: TxInsReference era
577+ data TxInsReference build era where
578+ TxInsReferenceNone :: TxInsReference build era
575579 TxInsReference
576580 :: BabbageEraOnwards era
577581 -> [TxIn ]
578- -> TxInsReference era
582+ -- ^ A list of reference inputs
583+ -> TxInsReferenceActualDatums build
584+ -- ^ A set of datums, which hashes are referenced in UTXO of reference inputs. Those datums will be inserted
585+ -- to the datum map available to the scripts.
586+ -> TxInsReference build era
579587
580- deriving instance Eq (TxInsReference era )
588+ deriving instance Eq (TxInsReference build era )
581589
582- deriving instance Show (TxInsReference era )
590+ deriving instance Show (TxInsReference build era )
591+
592+ -- | The actual datums, referenced by hash in the transaction reference inputs.
593+ --
594+ -- Only datums referenced by hashes in UTXOs of reference inputs, will be inserted into the transaction.
595+ type TxInsReferenceActualDatums build = BuildTxWith build (Set HashableScriptData )
596+
597+ getReferenceInputDatumMap
598+ :: TxInsReferenceActualDatums build
599+ -> Map (Hash ScriptData ) HashableScriptData
600+ getReferenceInputDatumMap = \ case
601+ ViewTx -> mempty
602+ BuildTxWith datumSet -> fromList $ map (\ h -> (hashScriptDataBytes h, h)) $ toList datumSet
583603
584604-- ----------------------------------------------------------------------------
585605-- Transaction fees
@@ -984,7 +1004,7 @@ data TxBodyContent build era
9841004 = TxBodyContent
9851005 { txIns :: TxIns build era
9861006 , txInsCollateral :: TxInsCollateral era
987- , txInsReference :: TxInsReference era
1007+ , txInsReference :: TxInsReference build era
9881008 , txOuts :: [TxOut CtxTx era ]
9891009 , txTotalCollateral :: TxTotalCollateral era
9901010 , txReturnCollateral :: TxReturnCollateral CtxTx era
@@ -1075,25 +1095,35 @@ addTxInCollateral
10751095 :: IsAlonzoBasedEra era => TxIn -> TxBodyContent build era -> TxBodyContent build era
10761096addTxInCollateral txInCollateral = addTxInsCollateral [txInCollateral]
10771097
1078- setTxInsReference :: TxInsReference era -> TxBodyContent build era -> TxBodyContent build era
1098+ setTxInsReference :: TxInsReference build era -> TxBodyContent build era -> TxBodyContent build era
10791099setTxInsReference v txBodyContent = txBodyContent{txInsReference = v}
10801100
10811101modTxInsReference
1082- :: (TxInsReference era -> TxInsReference era ) -> TxBodyContent build era -> TxBodyContent build era
1102+ :: (TxInsReference build era -> TxInsReference build era )
1103+ -> TxBodyContent build era
1104+ -> TxBodyContent build era
10831105modTxInsReference f txBodyContent = txBodyContent{txInsReference = f (txInsReference txBodyContent)}
10841106
10851107addTxInsReference
1086- :: IsBabbageBasedEra era => [TxIn ] -> TxBodyContent build era -> TxBodyContent build era
1087- addTxInsReference txInsReference =
1088- modTxInsReference
1089- ( \ case
1090- TxInsReferenceNone -> TxInsReference babbageBasedEra txInsReference
1091- TxInsReference era xs -> TxInsReference era (xs <> txInsReference)
1092- )
1108+ :: Applicative (BuildTxWith build )
1109+ => IsBabbageBasedEra era
1110+ => [TxIn ]
1111+ -> Set HashableScriptData
1112+ -> TxBodyContent build era
1113+ -> TxBodyContent build era
1114+ addTxInsReference txInsReference scriptData =
1115+ modTxInsReference $
1116+ \ case
1117+ TxInsReferenceNone -> TxInsReference babbageBasedEra txInsReference (pure scriptData)
1118+ TxInsReference era xs bScriptData' -> TxInsReference era (xs <> txInsReference) ((<> scriptData) <$> bScriptData')
10931119
10941120addTxInReference
1095- :: IsBabbageBasedEra era => TxIn -> TxBodyContent build era -> TxBodyContent build era
1096- addTxInReference txInReference = addTxInsReference [txInReference]
1121+ :: Applicative (BuildTxWith build )
1122+ => IsBabbageBasedEra era
1123+ => TxIn
1124+ -> TxBodyContent build era
1125+ -> TxBodyContent build era
1126+ addTxInReference txInReference = addTxInsReference [txInReference] mempty
10971127
10981128setTxOuts :: [TxOut CtxTx era ] -> TxBodyContent build era -> TxBodyContent build era
10991129setTxOuts v txBodyContent = txBodyContent{txOuts = v}
@@ -1370,9 +1400,11 @@ createTransactionBody
13701400 :: forall era
13711401 . HasCallStack
13721402 => ShelleyBasedEra era
1403+ -> UTxO era
1404+ -- ^ UTXO for reference inputs
13731405 -> TxBodyContent BuildTx era
13741406 -> Either TxBodyError (TxBody era )
1375- createTransactionBody sbe bc =
1407+ createTransactionBody sbe utxo bc =
13761408 shelleyBasedEraConstraints sbe $ do
13771409 (sData, mScriptIntegrityHash, scripts) <-
13781410 caseShelleyToMaryOrAlonzoEraOnwards
@@ -1387,7 +1419,7 @@ createTransactionBody sbe bc =
13871419 )
13881420 ( \ aeon -> do
13891421 TxScriptWitnessRequirements languages scripts dats redeemers <-
1390- collectTxBodyScriptWitnessRequirements aeon bc
1422+ collectTxBodyScriptWitnessRequirements aeon utxo bc
13911423
13921424 let pparams = txProtocolParams bc
13931425 sData = TxBodyScriptData aeon dats redeemers
@@ -1742,11 +1774,11 @@ fromLedgerTxInsCollateral sbe body =
17421774 sbe
17431775
17441776fromLedgerTxInsReference
1745- :: ShelleyBasedEra era -> Ledger. TxBody (ShelleyLedgerEra era ) -> TxInsReference era
1777+ :: ShelleyBasedEra era -> Ledger. TxBody (ShelleyLedgerEra era ) -> TxInsReference ViewTx era
17461778fromLedgerTxInsReference sbe txBody =
17471779 caseShelleyToAlonzoOrBabbageEraOnwards
17481780 (const TxInsReferenceNone )
1749- (\ w -> TxInsReference w $ map fromShelleyTxIn . toList $ txBody ^. L. referenceInputsTxBodyL)
1781+ (\ w -> TxInsReference w ( map fromShelleyTxIn . toList $ txBody ^. L. referenceInputsTxBodyL) ViewTx )
17501782 sbe
17511783
17521784fromLedgerTxTotalCollateral
@@ -2108,11 +2140,11 @@ convPParamsToScriptIntegrityHash
21082140 -> Alonzo. TxDats (ShelleyLedgerEra era )
21092141 -> Set Plutus. Language
21102142 -> StrictMaybe L. ScriptIntegrityHash
2111- convPParamsToScriptIntegrityHash w txProtocolParams redeemers datums languages =
2143+ convPParamsToScriptIntegrityHash w ( BuildTxWith mTxProtocolParams) redeemers datums languages =
21122144 alonzoEraOnwardsConstraints w $
2113- case txProtocolParams of
2114- BuildTxWith Nothing -> SNothing
2115- BuildTxWith ( Just (LedgerProtocolParameters pp) ) ->
2145+ case mTxProtocolParams of
2146+ Nothing -> SNothing
2147+ Just (LedgerProtocolParameters pp) ->
21162148 Alonzo. hashScriptIntegrity (Set. map (L. getLanguageView pp) languages) redeemers datums
21172149
21182150convLanguages :: [(ScriptWitnessIndex , AnyScriptWitness era )] -> Set Plutus. Language
@@ -2122,11 +2154,11 @@ convLanguages witnesses =
21222154 | (_, AnyScriptWitness (PlutusScriptWitness _ v _ _ _ _)) <- witnesses
21232155 ]
21242156
2125- convReferenceInputs :: TxInsReference era -> Set Ledger. TxIn
2157+ convReferenceInputs :: TxInsReference build era -> Set Ledger. TxIn
21262158convReferenceInputs txInsReference =
21272159 case txInsReference of
21282160 TxInsReferenceNone -> mempty
2129- TxInsReference _ refTxins -> fromList $ map toShelleyTxIn refTxins
2161+ TxInsReference _ refTxins _ -> fromList $ map toShelleyTxIn refTxins
21302162
21312163-- | Returns an OSet of proposals from 'TxProposalProcedures'.
21322164convProposalProcedures
@@ -2986,18 +3018,27 @@ collectTxBodyScriptWitnessRequirements
29863018 :: forall era
29873019 . IsShelleyBasedEra era
29883020 => AlonzoEraOnwards era
3021+ -> UTxO era
3022+ -- ^ UTXO for reference inputs
29893023 -> TxBodyContent BuildTx era
29903024 -> Either
29913025 TxBodyError
29923026 (TxScriptWitnessRequirements (ShelleyLedgerEra era ))
29933027collectTxBodyScriptWitnessRequirements
29943028 aEon
3029+ utxo
29953030 bc@ TxBodyContent
2996- { txOuts
3031+ { txInsReference
3032+ , txOuts
29973033 } =
29983034 obtainAlonzoScriptPurposeConstraints aEon $ do
29993035 let sbe = shelleyBasedEra @ era
3000- supplementaldatums = TxScriptWitnessRequirements mempty mempty (getSupplementalDatums aEon txOuts) mempty
3036+ supplementaldatums =
3037+ TxScriptWitnessRequirements
3038+ mempty
3039+ mempty
3040+ (getDatums aEon txInsReference utxo txOuts)
3041+ mempty
30013042 txInWits <-
30023043 first TxBodyPlutusScriptDecodeError $
30033044 legacyWitnessToScriptRequirements aEon $
@@ -3051,19 +3092,35 @@ collectTxBodyScriptWitnessRequirements
30513092 , txProposalWits
30523093 ]
30533094
3054- getSupplementalDatums
3095+ -- | Extract datum:
3096+ -- 1. supplemental datums from transaction outputs
3097+ -- 2. datums from reference inputs, whose hashes are present in UTXO (for those inputs)
3098+ getDatums
30553099 :: AlonzoEraOnwards era
3100+ -> TxInsReference BuildTx era
3101+ -- ^ reference inputs
3102+ -> UTxO era
3103+ -- ^ UTxO for reference inputs
30563104 -> [TxOut CtxTx era ]
30573105 -> L. TxDats (ShelleyLedgerEra era )
3058- getSupplementalDatums eon [] = alonzoEraOnwardsConstraints eon mempty
3059- getSupplementalDatums eon txouts =
3060- alonzoEraOnwardsConstraints eon $
3061- L. TxDats $
3062- fromList
3063- [ (L. hashData ledgerData, ledgerData)
3064- | TxOut _ _ (TxOutSupplementalDatum _ d) _ <- txouts
3065- , let ledgerData = toAlonzoData d
3106+ getDatums eon txInsRef utxo txOutsFromTx = alonzoEraOnwardsConstraints eon $ do
3107+ let refTxInsDats =
3108+ [ d
3109+ | TxInsReference _ txIns datumSet <- [txInsRef]
3110+ , let datumMap = getReferenceInputDatumMap datumSet
3111+ , txIn <- txIns
3112+ , -- resolve only hashes
3113+ TxOut _ _ (TxOutDatumHash _ datumHash) _ <- maybeToList $ UTxO. lookup txIn utxo
3114+ , d <- maybeToList $ Map. lookup datumHash datumMap
30663115 ]
3116+ -- use only supplemental datum
3117+ txOutsDats = [d | TxOut _ _ (TxOutSupplementalDatum _ d) _ <- txOutsFromTx]
3118+ L. TxDats $
3119+ fromList $
3120+ [ (L. hashData ledgerData, ledgerData)
3121+ | d <- refTxInsDats <> txOutsDats
3122+ , let ledgerData = toAlonzoData d
3123+ ]
30673124
30683125extractWitnessableTxIns
30693126 :: AlonzoEraOnwards era
0 commit comments