hydra icon indicating copy to clipboard operation
hydra copied to clipboard

Non-determinism in plutus validation

Open lehins opened this issue 6 months ago • 2 comments

This location usage of unsafeDupablePerformIO is technically not safe, since it can introduce non-determinism into the computation:

https://github.com/cardano-scaling/hydra/blob/d2b467b2dd00b8aa15e9b9319a863e59848a58ed/hydra-node/src/Hydra/Ledger/Cardano.hs#L96-L99

In plutusDebug we have added a timeout to bound any potentially unbounded script execution, hence the switch to IO, because upon failing execution plutusDebug will execute the script once again without any execution limits and report the expected execution units, which does not guarantee termination. So, depending on how long this operation takes it could be within or outside of the 5 second limit we impose, thus potentially leading to a different outcome, i.e. non-determinism.

With respect to the feature itself it is very useful for debugging execution units. However, it is not safe to use in production setting, since it effectively unbounds script execution.

We have a PR into cardano-ledger#5127 that adds back a pure version without a timeout called plutusDebugUnbouded. We also add a flag pdoExUnitsEnforced that allows disabling this duplicate execution for the purpose of reporting expected execution units, effectively bounding function execution.

This is what I would recommend to change the logic in Hydra after the ledger PR is merged and is integrated into hydra:

    toValidationError (Ledger.ApplyTxError (e :| _)) = case e of
      (ConwayUtxowFailure (UtxoFailure (UtxosFailure (ValidationTagMismatch _ (FailedUnexpectedly (PlutusFailure msg ctx :| _)))))) ->
        ValidationError $
          "Plutus validation failed: "
            <> msg
            <> "Debug info: "
            <> show (debugPlutusUnbounded (decodeUtf8 ctx) (defaultPlutusDebugOverrides {pdoExUnitsEnforced = True}))

lehins avatar Jun 17 '25 20:06 lehins

CC @ch1bo

lehins avatar Jun 17 '25 21:06 lehins

Thanks, this would make the usage nicer. Having it unbounded and potentially block the node is fine in our case (much lower liveness guarantees needed on the L2).

ch1bo avatar Jul 07 '25 07:07 ch1bo