From 5c43b3a51370ff2343d1f1c7c7405621ac7169bd Mon Sep 17 00:00:00 2001 From: sourabhxyz Date: Wed, 15 Jan 2025 17:37:36 +0530 Subject: [PATCH] feat(#391 & #306): make datum as optional when spending an input in case it is inlined or not required --- CHANGELOG.md | 4 ++++ atlas-cardano.cabal | 2 +- src/GeniusYield/Test/Privnet/Examples/Gift.hs | 4 ++-- src/GeniusYield/Test/Privnet/Examples/Oracle.hs | 4 ++-- src/GeniusYield/Test/Privnet/Examples/Treat.hs | 2 +- src/GeniusYield/TxBuilder/Common.hs | 12 ++++++++---- src/GeniusYield/Types/TxIn.hs | 8 ++++---- tests-privnet/GeniusYield/Test/Privnet/Blueprint.hs | 4 ++-- .../GeniusYield/Test/Unified/BetRef/Operations.hs | 2 +- tests/GeniusYield/Test/FeeTracking.hs | 10 +++++----- tests/GeniusYield/Test/RefInput.hs | 2 +- 11 files changed, 31 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84b0c686..7df42342 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.0 + +* When spending an input, datum is now optional since it is not required to be specified in case it's inlined or not needed by associated Plutus script. + ## 0.8.1 * Add combined stake address registration and delegation certificate. diff --git a/atlas-cardano.cabal b/atlas-cardano.cabal index ad231e45..a2816b67 100644 --- a/atlas-cardano.cabal +++ b/atlas-cardano.cabal @@ -1,6 +1,6 @@ cabal-version: 3.8 name: atlas-cardano -version: 0.8.1 +version: 0.9.0 synopsis: Application backend for Plutus smart contracts on Cardano description: Atlas is an all-in-one, Haskell-native application backend for writing off-chain code for on-chain Plutus smart contracts. diff --git a/src/GeniusYield/Test/Privnet/Examples/Gift.hs b/src/GeniusYield/Test/Privnet/Examples/Gift.hs index d7753420..7b262d67 100644 --- a/src/GeniusYield/Test/Privnet/Examples/Gift.hs +++ b/src/GeniusYield/Test/Privnet/Examples/Gift.hs @@ -610,7 +610,7 @@ grabGifts validator = do , gyTxInWitness = GYTxInWitnessScript (GYBuildPlutusScriptInlined validator) - (datumFromPlutus' od) + (Just $ datumFromPlutus' od) unitRedeemer } | (oref, (_addr, _value, od)) <- itoList datums @@ -639,7 +639,7 @@ grabGiftsRef ref validator = do , gyTxInWitness = GYTxInWitnessScript (GYBuildPlutusScriptReference ref $ validatorToScript validator) - (datumFromPlutus' od) + (Just $ datumFromPlutus' od) unitRedeemer } | (oref, (_addr, _value, od)) <- itoList datums diff --git a/src/GeniusYield/Test/Privnet/Examples/Oracle.hs b/src/GeniusYield/Test/Privnet/Examples/Oracle.hs index 873c418d..3f211e22 100644 --- a/src/GeniusYield/Test/Privnet/Examples/Oracle.hs +++ b/src/GeniusYield/Test/Privnet/Examples/Oracle.hs @@ -57,7 +57,7 @@ tests setup = , gyTxInWitness = GYTxInWitnessScript (GYBuildPlutusScriptInlined @PlutusV2 readOracleValidatorV2) - (datumFromPlutusData (d :: ())) + (Just $ datumFromPlutusData (d :: ())) unitRedeemer } | (ref, (_, _, d)) <- Map.toList datums @@ -108,7 +108,7 @@ tests setup = , gyTxInWitness = GYTxInWitnessScript (GYBuildPlutusScriptInlined @PlutusV2 readOracleValidatorV2) - (datumFromPlutusData (d :: ())) + (Just $ datumFromPlutusData (d :: ())) unitRedeemer } | (ref, (_, _, d)) <- Map.toList datums diff --git a/src/GeniusYield/Test/Privnet/Examples/Treat.hs b/src/GeniusYield/Test/Privnet/Examples/Treat.hs index a8cd3d5e..35708af6 100644 --- a/src/GeniusYield/Test/Privnet/Examples/Treat.hs +++ b/src/GeniusYield/Test/Privnet/Examples/Treat.hs @@ -109,7 +109,7 @@ grabTreats validator = do , gyTxInWitness = GYTxInWitnessScript (GYBuildPlutusScriptInlined validator) - (datumFromPlutus' od) + (Just $ datumFromPlutus' od) unitRedeemer } | (oref, (_addr, _value, od)) <- itoList datums diff --git a/src/GeniusYield/TxBuilder/Common.hs b/src/GeniusYield/TxBuilder/Common.hs index 08edb677..6c23a984 100644 --- a/src/GeniusYield/TxBuilder/Common.hs +++ b/src/GeniusYield/TxBuilder/Common.hs @@ -35,7 +35,7 @@ import Data.List (nubBy) import Data.List.NonEmpty (NonEmpty ((:|))) import Data.List.NonEmpty qualified as NE import Data.Map.Strict qualified as Map -import Data.Maybe (maybeToList) +import Data.Maybe (isNothing, maybeToList) import Data.Ratio ((%)) import Data.Set qualified as Set import GeniusYield.Imports @@ -300,9 +300,13 @@ buildTxCore ss eh pp ps cstrat ownUtxoUpdateF addrs change reservedCollateral sk checkDatumMatch _ GYTxInWitnessKey = True checkDatumMatch _ GYTxInWitnessSimpleScript {} = True checkDatumMatch ud (GYTxInWitnessScript _ wd _) = case ud of - GYOutDatumNone -> False - GYOutDatumHash h -> h == hashDatum wd - GYOutDatumInline uid -> uid == wd + GYOutDatumNone -> isNothing wd + GYOutDatumHash h -> case wd of + Nothing -> False + Just wd' -> h == hashDatum wd' + GYOutDatumInline uid -> case wd of + Nothing -> True + Just wd' -> uid == wd' -- This operation is `O(n)` where `n` denotes the number of UTxOs in `ownUtxos'`. let totalRefScriptSize = foldl' (\acc GYUTxO {..} -> acc + maybe 0 scriptSize utxoRefScript) 0 $ refInsUtxos <> map utxoFromTxInDetailed gyTxInsDetailed diff --git a/src/GeniusYield/Types/TxIn.hs b/src/GeniusYield/Types/TxIn.hs index d272e731..07bdc77d 100644 --- a/src/GeniusYield/Types/TxIn.hs +++ b/src/GeniusYield/Types/TxIn.hs @@ -46,8 +46,8 @@ data GYTxIn v = GYTxIn data GYTxInWitness v = -- | Key witness without datum. GYTxInWitnessKey - | -- | Script witness with associated script, datum, and redeemer. - GYTxInWitnessScript !(GYBuildPlutusScript v) !GYDatum !GYRedeemer + | -- | Script witness with associated script, datum, and redeemer. Datum can be omitted if it is inlined in the input or if it's not needed under PlutusV3 (or beyond) script. + GYTxInWitnessScript !(GYBuildPlutusScript v) !(Maybe GYDatum) !GYRedeemer | -- | Simple script witness. GYTxInWitnessSimpleScript !(GYBuildSimpleScript v) deriving stock (Eq, Show) @@ -88,13 +88,13 @@ txInToApi useInline (GYTxIn oref m) = (txOutRefToApi oref, Api.BuildTxWith $ f m where f :: GYTxInWitness v -> Api.Witness Api.WitCtxTxIn ApiEra f GYTxInWitnessKey = Api.KeyWitness Api.KeyWitnessForSpending - f (GYTxInWitnessScript v d r) = + f (GYTxInWitnessScript v md r) = Api.ScriptWitness Api.ScriptWitnessForSpending $ ( case v of GYBuildPlutusScriptInlined s -> validatorToApiPlutusScriptWitness s GYBuildPlutusScriptReference ref s -> referenceScriptToApiPlutusScriptWitness ref s ) - (if useInline then Api.InlineScriptDatum else Api.ScriptDatumForTxIn $ Just $ datumToApi' d) + (if useInline then Api.InlineScriptDatum else Api.ScriptDatumForTxIn $ datumToApi' <$> md) (redeemerToApi r) (Api.ExecutionUnits 0 0) f (GYTxInWitnessSimpleScript v) = diff --git a/tests-privnet/GeniusYield/Test/Privnet/Blueprint.hs b/tests-privnet/GeniusYield/Test/Privnet/Blueprint.hs index ef3f187a..5943727b 100644 --- a/tests-privnet/GeniusYield/Test/Privnet/Blueprint.hs +++ b/tests-privnet/GeniusYield/Test/Privnet/Blueprint.hs @@ -41,10 +41,10 @@ blueprintTests setup = (\e -> if isTxBodyErrorAutoBalance e then pure () else throwError e) $ asUser user $ do - void $ buildTxBody $ mustHaveInput @'PlutusV3 $ GYTxIn oref (GYTxInWitnessScript (GYBuildPlutusScriptInlined val) dat unsatRedeemer) + void $ buildTxBody $ mustHaveInput @'PlutusV3 $ GYTxIn oref (GYTxInWitnessScript (GYBuildPlutusScriptInlined val) (Just dat) unsatRedeemer) lg "Successfully failed to consume from blueprint script for unsatisfying redeemer" tid <- asUser user $ do - txBody <- buildTxBody $ mustHaveInput @'PlutusV3 $ GYTxIn oref (GYTxInWitnessScript (GYBuildPlutusScriptInlined val) dat satRedeemer) + txBody <- buildTxBody $ mustHaveInput @'PlutusV3 $ GYTxIn oref (GYTxInWitnessScript (GYBuildPlutusScriptInlined val) (Just dat) satRedeemer) signAndSubmitConfirmed txBody lg $ "Successfully consumed from blueprint script, with tx id: " <> show tid ] diff --git a/tests-unified/GeniusYield/Test/Unified/BetRef/Operations.hs b/tests-unified/GeniusYield/Test/Unified/BetRef/Operations.hs index eee80026..f09febf7 100644 --- a/tests-unified/GeniusYield/Test/Unified/BetRef/Operations.hs +++ b/tests-unified/GeniusYield/Test/Unified/BetRef/Operations.hs @@ -141,6 +141,6 @@ input brp refScript inputRef dat red = , gyTxInWitness = GYTxInWitnessScript (GYBuildPlutusScriptReference refScript $ validatorToScript $ mkBetRefValidator brp) - (datumFromPlutusData dat) + (Just $ datumFromPlutusData dat) (redeemerFromPlutusData red) } diff --git a/tests/GeniusYield/Test/FeeTracking.hs b/tests/GeniusYield/Test/FeeTracking.hs index 5e438919..300ba6e6 100644 --- a/tests/GeniusYield/Test/FeeTracking.hs +++ b/tests/GeniusYield/Test/FeeTracking.hs @@ -64,7 +64,7 @@ sendAndConsume Wallets {w1, w2} amt = withWalletBalancesCheckSimple [w1 := value txBody <- buildTxBody @PlutusV1 . mustHaveInput $ GYTxIn - { gyTxInWitness = GYTxInWitnessScript (GYBuildPlutusScriptInlined gyAlwaysSucceedsValidator) unitDatum unitRedeemer + { gyTxInWitness = GYTxInWitnessScript (GYBuildPlutusScriptInlined gyAlwaysSucceedsValidator) (Just unitDatum) unitRedeemer , gyTxInTxOutRef = txOutRefFromTuple (txId, 0) } signAndSubmitConfirmed_ txBody @@ -81,7 +81,7 @@ sendAndContinue Wallets {w1, w2} amt = withWalletBalancesCheckSimple [w1 := valu mconcat [ mustHaveInput $ GYTxIn - { gyTxInWitness = GYTxInWitnessScript (GYBuildPlutusScriptInlined gyAlwaysSucceedsValidator) unitDatum unitRedeemer + { gyTxInWitness = GYTxInWitnessScript (GYBuildPlutusScriptInlined gyAlwaysSucceedsValidator) (Just unitDatum) unitRedeemer , gyTxInTxOutRef = txOutRefFromTuple (txId, 0) } , mustHaveOutput $ mkGYTxOut target amt unitDatum @@ -97,7 +97,7 @@ selfConsume Wallets {w1} amt = withWalletBalancesCheckSimple [w1 := mempty] $ do consumeBody <- buildTxBody @PlutusV1 . mustHaveInput $ GYTxIn - { gyTxInWitness = GYTxInWitnessScript (GYBuildPlutusScriptInlined gyAlwaysSucceedsValidator) unitDatum unitRedeemer + { gyTxInWitness = GYTxInWitnessScript (GYBuildPlutusScriptInlined gyAlwaysSucceedsValidator) (Just unitDatum) unitRedeemer , gyTxInTxOutRef = txOutRefFromTuple (txId, 0) } signAndSubmitConfirmed_ consumeBody @@ -113,7 +113,7 @@ selfContinue Wallets {w1} amt = withWalletBalancesCheckSimple [w1 := valueNegate mconcat [ mustHaveInput $ GYTxIn - { gyTxInWitness = GYTxInWitnessScript (GYBuildPlutusScriptInlined gyAlwaysSucceedsValidator) unitDatum unitRedeemer + { gyTxInWitness = GYTxInWitnessScript (GYBuildPlutusScriptInlined gyAlwaysSucceedsValidator) (Just unitDatum) unitRedeemer , gyTxInTxOutRef = txOutRefFromTuple (txId, 0) } , mustHaveOutput $ mkGYTxOut target amt unitDatum @@ -134,7 +134,7 @@ selfPartialConsume lovelaceConf TestInfo {testWallets = Wallets {w1}, testGoldAs mconcat [ mustHaveInput $ GYTxIn - { gyTxInWitness = GYTxInWitnessScript (GYBuildPlutusScriptInlined gyAlwaysSucceedsValidator) unitDatum unitRedeemer + { gyTxInWitness = GYTxInWitnessScript (GYBuildPlutusScriptInlined gyAlwaysSucceedsValidator) (Just unitDatum) unitRedeemer , gyTxInTxOutRef = txOutRefFromTuple (txId, 0) } , mustHaveOutput $ mkGYTxOut target partialAmt unitDatum diff --git a/tests/GeniusYield/Test/RefInput.hs b/tests/GeniusYield/Test/RefInput.hs index 26b92920..b53d3d74 100644 --- a/tests/GeniusYield/Test/RefInput.hs +++ b/tests/GeniusYield/Test/RefInput.hs @@ -53,7 +53,7 @@ guessRefInputRun refInputORef consumeRef guess = do , gyTxInWitness = GYTxInWitnessScript (GYBuildPlutusScriptInlined gyGuessRefInputDatumValidator) - (datumFromPlutusData ()) + (Just $ datumFromPlutusData ()) (redeemerFromPlutusData redeemer) } <> mustHaveRefInput refInputORef