Skip to content
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

new predicate for non-output supplementary datums #2345

Merged
merged 1 commit into from
Jun 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
36 changes: 28 additions & 8 deletions alonzo/impl/src/Cardano/Ledger/Alonzo/Rules/Utxow.hs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import Control.DeepSeq (NFData (..))
import Control.Iterate.SetAlgebra (domain, eval, (⊆), (◁), (➖))
import Control.State.Transition.Extended
import Data.Coders
import Data.Foldable (toList)
import qualified Data.Map.Strict as Map
import Data.Sequence.Strict (StrictSeq)
import Data.Set (Set)
Expand Down Expand Up @@ -97,6 +98,9 @@ data AlonzoPredFail era
| MissingRequiredDatums
!(Set (DataHash (Crypto era))) -- Set of missing data hashes
!(Set (DataHash (Crypto era))) -- Set of received data hashes
| NonOutputSupplimentaryDatums
!(Set (DataHash (Crypto era))) -- Set of unallowed data hashes
!(Set (DataHash (Crypto era))) -- Set of acceptable supplimental data hashes
| PPViewHashesDontMatch
!(StrictMaybe (WitnessPPDataHash (Crypto era)))
-- ^ The PPHash in the TxBody
Expand Down Expand Up @@ -149,9 +153,10 @@ encodePredFail ::
encodePredFail (WrappedShelleyEraFailure x) = Sum WrappedShelleyEraFailure 0 !> E toCBOR x
encodePredFail (UnRedeemableScripts x) = Sum UnRedeemableScripts 1 !> To x
encodePredFail (MissingRequiredDatums x y) = Sum MissingRequiredDatums 2 !> To x !> To y
encodePredFail (PPViewHashesDontMatch x y) = Sum PPViewHashesDontMatch 3 !> To x !> To y
encodePredFail (MissingRequiredSigners x) = Sum MissingRequiredSigners 4 !> To x
encodePredFail (UnspendableUTxONoDatumHash x) = Sum UnspendableUTxONoDatumHash 5 !> To x
encodePredFail (NonOutputSupplimentaryDatums x y) = Sum NonOutputSupplimentaryDatums 3 !> To x !> To y
encodePredFail (PPViewHashesDontMatch x y) = Sum PPViewHashesDontMatch 4 !> To x !> To y
encodePredFail (MissingRequiredSigners x) = Sum MissingRequiredSigners 5 !> To x
encodePredFail (UnspendableUTxONoDatumHash x) = Sum UnspendableUTxONoDatumHash 6 !> To x

instance
( Era era,
Expand All @@ -174,9 +179,10 @@ decodePredFail ::
decodePredFail 0 = SumD WrappedShelleyEraFailure <! D fromCBOR
decodePredFail 1 = SumD UnRedeemableScripts <! From
decodePredFail 2 = SumD MissingRequiredDatums <! From <! From
decodePredFail 3 = SumD PPViewHashesDontMatch <! From <! From
decodePredFail 4 = SumD MissingRequiredSigners <! From
decodePredFail 5 = SumD UnspendableUTxONoDatumHash <! From
decodePredFail 3 = SumD NonOutputSupplimentaryDatums <! From <! From
decodePredFail 4 = SumD PPViewHashesDontMatch <! From <! From
decodePredFail 5 = SumD MissingRequiredSigners <! From
decodePredFail 6 = SumD UnspendableUTxONoDatumHash <! From
decodePredFail n = Invalid n

-- =============================================
Expand Down Expand Up @@ -270,8 +276,22 @@ alonzoStyleWitness = do
SJust utxoHashes -> do
let txHashes = domain (unTxDats . txdats . wits $ tx)
inputHashes = Set.fromList utxoHashes
unmatchedInputHashes = eval (inputHashes ➖ txHashes)
Set.null unmatchedInputHashes ?! MissingRequiredDatums unmatchedInputHashes txHashes
unmatchedDatumHashes = eval (inputHashes ➖ txHashes)
Set.null unmatchedDatumHashes ?! MissingRequiredDatums unmatchedDatumHashes txHashes

-- Check that all supplimental datums contained in the witness set appear in the outputs.
let outputDatumHashes =
Set.fromList
[ dh
| out <- toList $ getField @"outputs" txbody,
SJust dh <- [getField @"datahash" out]
]
supplimentalDatumHashes = eval (txHashes ➖ inputHashes)
(okSupplimentalDHs, notOkSupplimentalDHs) =
Set.partition (`Set.member` outputDatumHashes) supplimentalDatumHashes
Set.null notOkSupplimentalDHs
?! NonOutputSupplimentaryDatums notOkSupplimentalDHs okSupplimentalDHs

{- ∀ sph ∈ scriptsNeeded utxo tx, checkScriptData tx utxo ph -}
let sphs :: [(ScriptPurpose (Crypto era), ScriptHash (Crypto era))]
sphs = scriptsNeeded utxo tx
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,58 @@ utxoStEx9 ::
UTxOState era
utxoStEx9 pf = UTxOState (utxoEx9 pf) (Coin 0) (Coin 5) def

-- ====================================================================================
-- Example 10: A transaction with an acceptable supplimentary datum
-- ====================================================================================

outEx10 :: forall era. (Scriptic era) => Proof era -> Core.TxOut era
outEx10 pf =
newTxOut
Override
pf
[ Address (scriptAddr (always 3 pf) pf),
Amount (inject $ Coin 995),
DHash [hashData $ datumExample1 @era]
]

okSupplimentaryDatumTxBody :: Scriptic era => Proof era -> Core.TxBody era
okSupplimentaryDatumTxBody pf =
newTxBody
Override
pf
[ Inputs [TxIn genesisId 3],
Outputs [outEx10 pf],
Txfee (Coin 5)
]

okSupplimentaryDatumTx ::
forall era.
( Scriptic era,
SignBody era
) =>
Proof era ->
Core.Tx era
okSupplimentaryDatumTx pf =
newTx
Override
pf
[ Body (okSupplimentaryDatumTxBody pf),
Witnesses'
[ AddrWits [makeWitnessVKey (hashAnnotated (okSupplimentaryDatumTxBody pf)) (someKeys pf)],
DataWits [datumExample1]
]
]

utxoEx10 :: forall era. PostShelley era => Proof era -> UTxO era
utxoEx10 pf = expectedUTxO pf (ExpectSuccess (okSupplimentaryDatumTxBody pf) (outEx10 pf)) 3

utxoStEx10 ::
forall era.
(Default (State (EraRule "PPUP" era)), PostShelley era) =>
Proof era ->
UTxOState era
utxoStEx10 pf = UTxOState (utxoEx10 pf) (Coin 0) (Coin 5) def

-- =======================
-- Invalid Transactions
-- =======================
Expand Down Expand Up @@ -1254,6 +1306,40 @@ plutusOutputWithNoDataTx pf =
]
]

totallyIrrelevantDatum :: Data era
totallyIrrelevantDatum = Data (Plutus.I 1729)

outputWithNoDatum :: forall era. Era era => Proof era -> Core.TxOut era
outputWithNoDatum pf = newTxOut Override pf [Address $ someAddr pf, Amount (inject $ Coin 995)]

notOkSupplimentaryDatumTxBody :: Scriptic era => Proof era -> Core.TxBody era
notOkSupplimentaryDatumTxBody pf =
newTxBody
Override
pf
[ Inputs [TxIn genesisId 3],
Outputs [outputWithNoDatum pf],
Txfee (Coin 5)
]

notOkSupplimentaryDatumTx ::
forall era.
( Scriptic era,
SignBody era
) =>
Proof era ->
Core.Tx era
notOkSupplimentaryDatumTx pf =
newTx
Override
pf
[ Body (notOkSupplimentaryDatumTxBody pf),
Witnesses'
[ AddrWits [makeWitnessVKey (hashAnnotated (notOkSupplimentaryDatumTxBody pf)) (someKeys pf)],
DataWits [totallyIrrelevantDatum]
]
]

-- =======================
-- Alonzo UTXOW Tests
-- =======================
Expand Down Expand Up @@ -1318,7 +1404,11 @@ alonzoUTXOWexamples =
testCase "validating scripts everywhere" $
testUTXOW
(trustMe True $ validatingTxManyScripts pf)
(Right . utxoStEx9 $ pf)
(Right . utxoStEx9 $ pf),
testCase "acceptable supplimentary datum" $
testUTXOW
(trustMe True $ okSupplimentaryDatumTx pf)
(Right . utxoStEx10 $ pf)
],
testGroup
"invalid transactions"
Expand Down Expand Up @@ -1508,6 +1598,16 @@ alonzoUTXOWexamples =
testUTXOW
(trustMe True $ plutusOutputWithNoDataTx pf)
( Left [[UnspendableUTxONoDatumHash . Set.singleton $ TxIn genesisId 101]]
),
testCase "unacceptable supplimentary datum" $
testUTXOW
(trustMe True $ notOkSupplimentaryDatumTx pf)
( Left
[ [ NonOutputSupplimentaryDatums
(Set.singleton $ hashData @A totallyIrrelevantDatum)
mempty
]
]
)
]
]
Expand Down