diff --git a/hydra-chain-observer/exe/Main.hs b/hydra-chain-observer/exe/Main.hs index 0625e510d0b..2c53bbac429 100644 --- a/hydra-chain-observer/exe/Main.hs +++ b/hydra-chain-observer/exe/Main.hs @@ -1,8 +1,10 @@ module Main where +import Hydra.Prelude + import Hydra.ChainObserver qualified import Hydra.ChainObserver.NodeClient (defaultObserverHandler) -import Hydra.Prelude +import Hydra.SerialisedScriptRegistry (serialisedScriptRegistry) main :: IO () -main = Hydra.ChainObserver.main defaultObserverHandler +main = Hydra.ChainObserver.main serialisedScriptRegistry defaultObserverHandler diff --git a/hydra-chain-observer/hydra-chain-observer.cabal b/hydra-chain-observer/hydra-chain-observer.cabal index 507f532a65f..150256039b0 100644 --- a/hydra-chain-observer/hydra-chain-observer.cabal +++ b/hydra-chain-observer/hydra-chain-observer.cabal @@ -90,6 +90,7 @@ executable hydra-chain-observer main-is: Main.hs build-depends: , hydra-chain-observer + , hydra-plutus , hydra-prelude test-suite tests @@ -103,6 +104,7 @@ test-suite tests , hydra-cardano-api , hydra-chain-observer , hydra-node + , hydra-plutus , hydra-prelude , hydra-test-utils , hydra-tx:testlib diff --git a/hydra-chain-observer/src/Hydra/Blockfrost/ChainObserver.hs b/hydra-chain-observer/src/Hydra/Blockfrost/ChainObserver.hs index 79894732dc7..40d048dc310 100644 --- a/hydra-chain-observer/src/Hydra/Blockfrost/ChainObserver.hs +++ b/hydra-chain-observer/src/Hydra/Blockfrost/ChainObserver.hs @@ -41,6 +41,7 @@ import Hydra.ChainObserver.NodeClient ( observeAll, ) import Hydra.Logging (Tracer, traceWith) +import Hydra.SerialisedScriptRegistry (SerialisedScriptRegistry) import Hydra.Tx (IsTx (..)) data APIBlockfrostError @@ -66,8 +67,9 @@ blockfrostClient :: Tracer IO ChainObserverLog -> FilePath -> Integer -> + SerialisedScriptRegistry -> NodeClient IO -blockfrostClient tracer projectPath blockConfirmations = do +blockfrostClient tracer projectPath blockConfirmations serialisedScriptRegistry = do NodeClient { follow = \startChainFrom observerHandler -> do prj <- Blockfrost.projectFromFile projectPath @@ -100,7 +102,7 @@ blockfrostClient tracer projectPath blockConfirmations = do stateTVar <- newTVarIO (blockHash, mempty) void $ retrying (retryPolicy blockTime) shouldRetry $ \_ -> do - loop tracer prj networkId blockTime observerHandler blockConfirmations stateTVar + loop tracer prj networkId blockTime serialisedScriptRegistry observerHandler blockConfirmations stateTVar `catch` \(ex :: APIBlockfrostError) -> pure $ Left ex } @@ -121,15 +123,16 @@ loop :: Blockfrost.Project -> NetworkId -> DiffTime -> + SerialisedScriptRegistry -> ObserverHandler m -> Integer -> TVar m (Blockfrost.BlockHash, UTxO) -> m a -loop tracer prj networkId blockTime observerHandler blockConfirmations stateTVar = do +loop tracer prj networkId blockTime serialisedScriptRegistry observerHandler blockConfirmations stateTVar = do current <- readTVarIO stateTVar - next <- rollForward tracer prj networkId observerHandler blockConfirmations current + next <- rollForward tracer prj networkId serialisedScriptRegistry observerHandler blockConfirmations current atomically $ writeTVar stateTVar next - loop tracer prj networkId blockTime observerHandler blockConfirmations stateTVar + loop tracer prj networkId blockTime serialisedScriptRegistry observerHandler blockConfirmations stateTVar -- | From the current block and UTxO view, we collect Hydra observations -- and yield the next block and adjusted UTxO view. @@ -138,11 +141,12 @@ rollForward :: Tracer m ChainObserverLog -> Blockfrost.Project -> NetworkId -> + SerialisedScriptRegistry -> ObserverHandler m -> Integer -> (Blockfrost.BlockHash, UTxO) -> m (Blockfrost.BlockHash, UTxO) -rollForward tracer prj networkId observerHandler blockConfirmations (blockHash, utxo) = do +rollForward tracer prj networkId serialisedScriptRegistry observerHandler blockConfirmations (blockHash, utxo) = do block@Blockfrost.Block { _blockHash , _blockConfirmations @@ -172,7 +176,7 @@ rollForward tracer prj networkId observerHandler blockConfirmations (blockHash, traceWith tracer RollForward{point, receivedTxIds} -- Collect head observations - let (adjustedUTxO, observations) = observeAll networkId utxo receivedTxs + let (adjustedUTxO, observations) = observeAll networkId serialisedScriptRegistry utxo receivedTxs let onChainTxs = mapMaybe convertObservation observations forM_ onChainTxs (traceWith tracer . logOnChainTx) diff --git a/hydra-chain-observer/src/Hydra/ChainObserver.hs b/hydra-chain-observer/src/Hydra/ChainObserver.hs index ac21e82750b..1a95f752dc1 100644 --- a/hydra-chain-observer/src/Hydra/ChainObserver.hs +++ b/hydra-chain-observer/src/Hydra/ChainObserver.hs @@ -10,19 +10,20 @@ import Hydra.ChainObserver.Options (BlockfrostOptions (..), DirectOptions (..), import Hydra.Contract qualified as Contract import Hydra.Logging (Verbosity (..), traceWith, withTracer) import Hydra.Ouroborus.ChainObserver (ouroborusClient) +import Hydra.SerialisedScriptRegistry (SerialisedScriptRegistry) import Options.Applicative (execParser) -main :: ObserverHandler IO -> IO () -main observerHandler = do +main :: SerialisedScriptRegistry -> ObserverHandler IO -> IO () +main serialisedScriptRegistry observerHandler = do opts <- execParser hydraChainObserverOptions withTracer (Verbose "hydra-chain-observer") $ \tracer -> do - traceWith tracer KnownScripts{scriptInfo = Contract.scriptInfo} + traceWith tracer KnownScripts{scriptInfo = Contract.scriptInfo serialisedScriptRegistry} case opts of DirectOpts DirectOptions{networkId, nodeSocket, startChainFrom} -> do - let NodeClient{follow} = ouroborusClient tracer nodeSocket networkId + let NodeClient{follow} = ouroborusClient tracer nodeSocket networkId serialisedScriptRegistry follow startChainFrom observerHandler BlockfrostOpts BlockfrostOptions{projectPath, startChainFrom} -> do -- FIXME: should be configurable let blockConfirmations = 1 - NodeClient{follow} = blockfrostClient tracer projectPath blockConfirmations + NodeClient{follow} = blockfrostClient tracer projectPath blockConfirmations serialisedScriptRegistry follow startChainFrom observerHandler diff --git a/hydra-chain-observer/src/Hydra/ChainObserver/NodeClient.hs b/hydra-chain-observer/src/Hydra/ChainObserver/NodeClient.hs index 4d034a70122..94d0007e064 100644 --- a/hydra-chain-observer/src/Hydra/ChainObserver/NodeClient.hs +++ b/hydra-chain-observer/src/Hydra/ChainObserver/NodeClient.hs @@ -20,6 +20,7 @@ import Hydra.Chain.Direct.Tx ( ) import Hydra.Contract (ScriptInfo) import Hydra.Ledger.Cardano (adjustUTxO) +import Hydra.SerialisedScriptRegistry (SerialisedScriptRegistry) import Hydra.Tx.HeadId (HeadId (..)) type ObserverHandler m = [ChainObservation] -> m () @@ -79,19 +80,19 @@ logOnChainTx = \case OnAbortTx{headId} -> HeadAbortTx{headId} OnContestTx{headId} -> HeadContestTx{headId} -observeTx :: NetworkId -> UTxO -> Tx -> (UTxO, Maybe HeadObservation) -observeTx networkId utxo tx = +observeTx :: NetworkId -> SerialisedScriptRegistry -> UTxO -> Tx -> (UTxO, Maybe HeadObservation) +observeTx networkId serialisedScriptRegistry utxo tx = let utxo' = adjustUTxO tx utxo - in case observeHeadTx networkId utxo tx of + in case observeHeadTx networkId serialisedScriptRegistry utxo tx of NoHeadTx -> (utxo, Nothing) observation -> (utxo', pure observation) -observeAll :: NetworkId -> UTxO -> [Tx] -> (UTxO, [HeadObservation]) -observeAll networkId utxo txs = +observeAll :: NetworkId -> SerialisedScriptRegistry -> UTxO -> [Tx] -> (UTxO, [HeadObservation]) +observeAll networkId serialisedScriptRegistry utxo txs = second reverse $ foldr go (utxo, []) txs where go :: Tx -> (UTxO, [HeadObservation]) -> (UTxO, [HeadObservation]) go tx (utxo'', observations) = - case observeTx networkId utxo'' tx of + case observeTx networkId serialisedScriptRegistry utxo'' tx of (utxo', Nothing) -> (utxo', observations) (utxo', Just observation) -> (utxo', observation : observations) diff --git a/hydra-chain-observer/src/Hydra/Ouroborus/ChainObserver.hs b/hydra-chain-observer/src/Hydra/Ouroborus/ChainObserver.hs index 2953267ce87..c9cb982b998 100644 --- a/hydra-chain-observer/src/Hydra/Ouroborus/ChainObserver.hs +++ b/hydra-chain-observer/src/Hydra/Ouroborus/ChainObserver.hs @@ -36,6 +36,7 @@ import Hydra.ChainObserver.NodeClient ( observeAll, ) import Hydra.Logging (Tracer, traceWith) +import Hydra.SerialisedScriptRegistry (SerialisedScriptRegistry) import Ouroboros.Network.Protocol.ChainSync.Client ( ChainSyncClient (..), ClientStIdle (..), @@ -47,8 +48,9 @@ ouroborusClient :: Tracer IO ChainObserverLog -> SocketPath -> NetworkId -> + SerialisedScriptRegistry -> NodeClient IO -ouroborusClient tracer nodeSocket networkId = +ouroborusClient tracer nodeSocket networkId serialisedScriptRegistry = NodeClient { follow = \startChainFrom observerHandler -> do traceWith tracer ConnectingToNode{nodeSocket, networkId} @@ -58,7 +60,7 @@ ouroborusClient tracer nodeSocket networkId = traceWith tracer StartObservingFrom{chainPoint} connectToLocalNode (connectInfo nodeSocket networkId) - (clientProtocols tracer networkId chainPoint observerHandler) + (clientProtocols tracer networkId chainPoint serialisedScriptRegistry observerHandler) } type BlockType :: Type @@ -79,11 +81,12 @@ clientProtocols :: Tracer IO ChainObserverLog -> NetworkId -> ChainPoint -> + SerialisedScriptRegistry -> ObserverHandler IO -> LocalNodeClientProtocols BlockType ChainPoint ChainTip slot tx txid txerr query IO -clientProtocols tracer networkId startingPoint observerHandler = +clientProtocols tracer networkId startingPoint serialisedScriptRegistry observerHandler = LocalNodeClientProtocols - { localChainSyncClient = LocalChainSyncClient $ chainSyncClient tracer networkId startingPoint observerHandler + { localChainSyncClient = LocalChainSyncClient $ chainSyncClient tracer networkId startingPoint serialisedScriptRegistry observerHandler , localTxSubmissionClient = Nothing , localStateQueryClient = Nothing , localTxMonitoringClient = Nothing @@ -107,9 +110,10 @@ chainSyncClient :: Tracer m ChainObserverLog -> NetworkId -> ChainPoint -> + SerialisedScriptRegistry -> ObserverHandler m -> ChainSyncClient BlockType ChainPoint ChainTip m () -chainSyncClient tracer networkId startingPoint observerHandler = +chainSyncClient tracer networkId startingPoint serialisedScriptRegistry observerHandler = ChainSyncClient $ pure $ SendMsgFindIntersect [startingPoint] clientStIntersect @@ -142,7 +146,7 @@ chainSyncClient tracer networkId startingPoint observerHandler = BlockInMode ConwayEra (Block _ conwayTxs) -> conwayTxs _ -> [] - (utxo', observations) = observeAll networkId utxo txs + (utxo', observations) = observeAll networkId serialisedScriptRegistry utxo txs onChainTxs = mapMaybe convertObservation observations forM_ onChainTxs (traceWith tracer . logOnChainTx) diff --git a/hydra-chain-observer/test/Hydra/ChainObserverSpec.hs b/hydra-chain-observer/test/Hydra/ChainObserverSpec.hs index dcea24cabf5..d586ad57fd3 100644 --- a/hydra-chain-observer/test/Hydra/ChainObserverSpec.hs +++ b/hydra-chain-observer/test/Hydra/ChainObserverSpec.hs @@ -9,6 +9,7 @@ import Hydra.Chain.Direct.State qualified as Transition import Hydra.Chain.Direct.Tx (HeadObservation (..)) import Hydra.ChainObserver.NodeClient (observeAll, observeTx) import Hydra.Ledger.Cardano (genSequenceOfSimplePaymentTransactions) +import Hydra.SerialisedScriptRegistry (serialisedScriptRegistry) import Test.Hydra.Tx.Fixture (testNetworkId) import Test.QuickCheck (counterexample, forAll, forAllBlind, property, (=/=), (===)) import Test.QuickCheck.Property (checkCoverage) @@ -22,7 +23,7 @@ spec = genericCoverTable [transition] $ counterexample (show transition) $ let utxo = getKnownUTxO st <> utxoFromTx tx <> additionalUTxO - in case snd $ observeTx testNetworkId utxo tx of + in case snd $ observeTx testNetworkId serialisedScriptRegistry utxo tx of Just (Init{}) -> transition === Transition.Init Just (Commit{}) -> transition === Transition.Commit Just (CollectCom{}) -> transition === Transition.Collect @@ -37,8 +38,8 @@ spec = prop "Updates UTxO state given transaction part of Head lifecycle" $ forAllBlind genChainStateWithTx $ \(_ctx, st, additionalUTxO, tx, _transition) -> let utxo = getKnownUTxO st <> additionalUTxO - in fst (observeTx testNetworkId utxo tx) =/= utxo + in fst (observeTx testNetworkId serialisedScriptRegistry utxo tx) =/= utxo prop "Does not updates UTxO state given transactions outside of Head lifecycle" $ forAll genSequenceOfSimplePaymentTransactions $ \(utxo, txs) -> - fst (observeAll testNetworkId utxo txs) === utxo + fst (observeAll testNetworkId serialisedScriptRegistry utxo txs) === utxo diff --git a/hydra-node/bench/tx-cost/Main.hs b/hydra-node/bench/tx-cost/Main.hs index 17d62cc5c36..c27caecb762 100644 --- a/hydra-node/bench/tx-cost/Main.hs +++ b/hydra-node/bench/tx-cost/Main.hs @@ -6,6 +6,7 @@ import Hydra.Cardano.Api (Coin (..), serialiseToRawBytesHexText) import Hydra.Contract (ScriptInfo (..), scriptInfo) import Hydra.Ledger.Cardano.Evaluate (maxCpu, maxMem, maxTxSize) import Hydra.Plutus.Orphans () +import Hydra.SerialisedScriptRegistry (serialisedScriptRegistry) import Options.Applicative ( Parser, ParserInfo, @@ -171,7 +172,7 @@ scriptSizes = , headScriptSize , depositScriptHash , depositScriptSize - } = scriptInfo + } = scriptInfo serialisedScriptRegistry genFromSeed :: Gen a -> Int -> a genFromSeed (MkGen g) seed = g (mkQCGen seed) 30 diff --git a/hydra-node/src/Hydra/Chain/Direct/Handlers.hs b/hydra-node/src/Hydra/Chain/Direct/Handlers.hs index ac65fd07512..d32698e1bdd 100644 --- a/hydra-node/src/Hydra/Chain/Direct/Handlers.hs +++ b/hydra-node/src/Hydra/Chain/Direct/Handlers.hs @@ -80,6 +80,7 @@ import Hydra.Chain.Direct.Wallet ( import Hydra.Ledger.Cardano (adjustUTxO, fromChainSlot) import Hydra.Logging (Tracer, traceWith) import Hydra.Plutus.Extras (posixToUTCTime) +import Hydra.SerialisedScriptRegistry (serialisedScriptRegistry) import Hydra.Tx ( CommitBlueprintTx (..), HeadParameters (..), @@ -305,7 +306,7 @@ chainSyncHandler tracer callback getTimeHandle ctx localChainState = maybeObserveSomeTx point tx = atomically $ do ChainStateAt{spendableUTxO} <- getLatest - let observation = observeHeadTx networkId spendableUTxO tx + let observation = observeHeadTx networkId serialisedScriptRegistry spendableUTxO tx case convertObservation observation of Nothing -> pure Nothing Just observedTx -> do diff --git a/hydra-node/src/Hydra/Chain/Direct/State.hs b/hydra-node/src/Hydra/Chain/Direct/State.hs index 302de9f1195..f2eb3fb11c9 100644 --- a/hydra-node/src/Hydra/Chain/Direct/State.hs +++ b/hydra-node/src/Hydra/Chain/Direct/State.hs @@ -85,6 +85,7 @@ import Hydra.Ledger.Cardano.Evaluate (genPointInTimeBefore, genValidityBoundsFro import Hydra.Ledger.Cardano.Time (slotNoFromUTCTime) import Hydra.Plutus (commitValidatorScript, depositValidatorScript, initialValidatorScript) import Hydra.Plutus.Extras (posixToUTCTime) +import Hydra.SerialisedScriptRegistry (serialisedScriptRegistry) import Hydra.Tx ( CommitBlueprintTx (..), ConfirmedSnapshot (..), @@ -778,7 +779,7 @@ observeInit :: Tx -> Either NotAnInitReason (OnChainTx Tx, InitialState) observeInit _ctx _allVerificationKeys tx = do - observation <- observeInitTx tx + observation <- observeInitTx serialisedScriptRegistry tx pure (toEvent observation, toState observation) where toEvent InitObservation{contestationPeriod, parties, headId, seedTxIn, participants} = @@ -813,7 +814,7 @@ observeCommit :: Maybe (OnChainTx Tx, InitialState) observeCommit ctx st tx = do let utxo = getKnownUTxO st - observation <- observeCommitTx networkId utxo tx + observation <- observeCommitTx networkId serialisedScriptRegistry utxo tx let CommitObservation{commitOutput, party, committed, headId = commitHeadId} = observation guard $ commitHeadId == headId let event = OnCommitTx{headId, party, committed} @@ -844,7 +845,7 @@ observeCollect :: Maybe (OnChainTx Tx, OpenState) observeCollect st tx = do let utxo = getKnownUTxO st - observation <- observeCollectComTx utxo tx + observation <- observeCollectComTx serialisedScriptRegistry utxo tx let CollectComObservation{threadOutput = threadOutput, headId = collectComHeadId, utxoHash} = observation guard (headId == collectComHeadId) -- REVIEW: is it enough to pass here just the 'openThreadUTxO' or we need also @@ -874,7 +875,7 @@ observeClose :: Maybe (OnChainTx Tx, ClosedState) observeClose st tx = do let utxo = getKnownUTxO st - observation <- observeCloseTx utxo tx + observation <- observeCloseTx serialisedScriptRegistry utxo tx let CloseObservation{threadOutput, headId = closeObservationHeadId, snapshotNumber} = observation guard (headId == closeObservationHeadId) let ClosedThreadOutput{closedContestationDeadline} = threadOutput @@ -1155,7 +1156,7 @@ genRecoverTx :: genRecoverTx = do (_, _, depositedUTxO, txDeposit) <- genDepositTx maximumNumberOfParties let DepositObservation{deposited, deadline} = - fromJust $ observeDepositTx testNetworkId txDeposit + fromJust $ observeDepositTx testNetworkId serialisedScriptRegistry txDeposit let slotNo = slotNoFromUTCTime systemStart slotLength (posixToUTCTime deadline) slotNo' <- arbitrary let tx = recoverTx (getTxId $ getTxBody txDeposit) deposited (slotNo + slotNo') @@ -1165,7 +1166,7 @@ genIncrementTx :: Int -> Gen (ChainContext, OpenState, UTxO, Tx) genIncrementTx numParties = do (ctx, st@OpenState{headId}, utxo, txDeposit) <- genDepositTx numParties cctx <- pickChainContext ctx - let DepositObservation{deposited, depositTxId, deadline} = fromJust $ observeDepositTx (ctxNetworkId ctx) txDeposit + let DepositObservation{deposited, depositTxId, deadline} = fromJust $ observeDepositTx (ctxNetworkId ctx) serialisedScriptRegistry txDeposit let openUTxO = getKnownUTxO st let version = 0 snapshot <- genConfirmedSnapshot headId version 1 openUTxO (Just deposited) Nothing (ctxHydraSigningKeys ctx) diff --git a/hydra-node/src/Hydra/Chain/Direct/Tx.hs b/hydra-node/src/Hydra/Chain/Direct/Tx.hs index b1bdc9c29ed..4f65b411430 100644 --- a/hydra-node/src/Hydra/Chain/Direct/Tx.hs +++ b/hydra-node/src/Hydra/Chain/Direct/Tx.hs @@ -20,7 +20,6 @@ import Data.ByteString qualified as BS import GHC.IsList (IsList (..)) import Hydra.Contract.Commit qualified as Commit import Hydra.Contract.Deposit qualified as Deposit -import Hydra.Contract.Head qualified as Head import Hydra.Contract.HeadState qualified as Head import Hydra.Contract.HeadTokens qualified as HeadTokens import Hydra.Data.ContestationPeriod qualified as OnChain @@ -28,6 +27,7 @@ import Hydra.Data.Party qualified as OnChain import Hydra.Plutus (commitValidatorScript, depositValidatorScript, initialValidatorScript) import Hydra.Plutus.Extras (posixToUTCTime) import Hydra.Plutus.Orphans () +import Hydra.SerialisedScriptRegistry (SerialisedScriptRegistry (..)) import Hydra.Tx ( HeadId (..), HeadSeed (..), @@ -88,20 +88,20 @@ data HeadObservation deriving stock (Eq, Show, Generic) -- | Observe any Hydra head transaction. -observeHeadTx :: NetworkId -> UTxO -> Tx -> HeadObservation -observeHeadTx networkId utxo tx = +observeHeadTx :: NetworkId -> SerialisedScriptRegistry -> UTxO -> Tx -> HeadObservation +observeHeadTx networkId serializedScripts utxo tx = fromMaybe NoHeadTx $ - either (const Nothing) (Just . Init) (observeInitTx tx) - <|> Abort <$> observeAbortTx utxo tx - <|> Commit <$> observeCommitTx networkId utxo tx - <|> CollectCom <$> observeCollectComTx utxo tx - <|> Deposit <$> observeDepositTx networkId tx - <|> Recover <$> observeRecoverTx networkId utxo tx - <|> Increment <$> observeIncrementTx utxo tx - <|> Decrement <$> observeDecrementTx utxo tx - <|> Close <$> observeCloseTx utxo tx - <|> Contest <$> observeContestTx utxo tx - <|> Fanout <$> observeFanoutTx utxo tx + either (const Nothing) (Just . Init) (observeInitTx serializedScripts tx) + <|> Abort <$> observeAbortTx serializedScripts utxo tx + <|> Commit <$> observeCommitTx networkId serializedScripts utxo tx + <|> CollectCom <$> observeCollectComTx serializedScripts utxo tx + <|> Deposit <$> observeDepositTx networkId serializedScripts tx + <|> Recover <$> observeRecoverTx networkId serializedScripts utxo tx + <|> Increment <$> observeIncrementTx serializedScripts utxo tx + <|> Decrement <$> observeDecrementTx serializedScripts utxo tx + <|> Close <$> observeCloseTx serializedScripts utxo tx + <|> Contest <$> observeContestTx serializedScripts utxo tx + <|> Fanout <$> observeFanoutTx serializedScripts utxo tx -- | Data which can be observed from an `initTx`. data InitObservation = InitObservation @@ -129,9 +129,10 @@ data NotAnInitReason -- | Identify a init tx by checking the output value for holding tokens that are -- valid head tokens (checked by seed + policy). observeInitTx :: + SerialisedScriptRegistry -> Tx -> Either NotAnInitReason InitObservation -observeInitTx tx = do +observeInitTx SerialisedScriptRegistry{initialScriptValidator, headScriptValidator} tx = do -- XXX: Lots of redundant information here (ix, headOut, headState) <- maybeLeft NoHeadOutput $ @@ -171,7 +172,7 @@ observeInitTx tx = do guard $ isScriptTxOut headScript out (ix,out,) <$> (fromScriptData =<< txOutScriptData out) - headScript = fromPlutusScript @PlutusScriptV3 Head.validatorScript + headScript = fromPlutusScript @PlutusScriptV3 headScriptValidator indexedOutputs = zip [0 ..] (txOuts' tx) @@ -184,7 +185,7 @@ observeInitTx tx = do isInitial = isScriptTxOut initialScript - initialScript = fromPlutusScript @PlutusScriptV3 initialValidatorScript + initialScript = fromPlutusScript @PlutusScriptV3 initialScriptValidator mintedTokenNames pid = [ assetName @@ -212,12 +213,13 @@ data CommitObservation = CommitObservation -- - Reconstruct the committed UTxO from both values (tx input and output). observeCommitTx :: NetworkId -> + SerialisedScriptRegistry -> -- | A UTxO set to lookup tx inputs. Should at least contain the input -- spending from νInitial. UTxO -> Tx -> Maybe CommitObservation -observeCommitTx networkId utxo tx = do +observeCommitTx networkId SerialisedScriptRegistry{initialScriptValidator, commitScriptValidator} utxo tx = do -- NOTE: Instead checking to spend from initial we could be looking at the -- seed: -- @@ -262,11 +264,11 @@ observeCommitTx networkId utxo tx = do initialAddress = mkScriptAddress @PlutusScriptV3 networkId initialScript - initialScript = fromPlutusScript @PlutusScriptV3 initialValidatorScript + initialScript = fromPlutusScript @PlutusScriptV3 initialScriptValidator commitAddress = mkScriptAddress networkId commitScript - commitScript = fromPlutusScript @PlutusScriptV3 commitValidatorScript + commitScript = fromPlutusScript @PlutusScriptV3 commitScriptValidator data CollectComObservation = CollectComObservation { threadOutput :: OpenThreadOutput @@ -278,11 +280,12 @@ data CollectComObservation = CollectComObservation -- | Identify a collectCom tx by lookup up the input spending the Head output -- and decoding its redeemer. observeCollectComTx :: + SerialisedScriptRegistry -> -- | A UTxO set to lookup tx inputs UTxO -> Tx -> Maybe CollectComObservation -observeCollectComTx utxo tx = do +observeCollectComTx SerialisedScriptRegistry{headScriptValidator} utxo tx = do let inputUTxO = resolveInputsUTxO utxo tx (headInput, headOutput) <- findTxOutByScript @PlutusScriptV3 inputUTxO headScript redeemer <- findRedeemerSpending tx headInput @@ -307,7 +310,7 @@ observeCollectComTx utxo tx = do } _ -> Nothing where - headScript = fromPlutusScript Head.validatorScript + headScript = fromPlutusScript headScriptValidator decodeUtxoHash datum = case fromScriptData datum of Just (Head.Open Head.OpenDatum{utxoHash}) -> Just $ fromBuiltin utxoHash @@ -321,10 +324,11 @@ data IncrementObservation = IncrementObservation deriving stock (Show, Eq, Generic) observeIncrementTx :: + SerialisedScriptRegistry -> UTxO -> Tx -> Maybe IncrementObservation -observeIncrementTx utxo tx = do +observeIncrementTx SerialisedScriptRegistry{headScriptValidator, depositScriptValidator} utxo tx = do let inputUTxO = resolveInputsUTxO utxo tx (headInput, headOutput) <- findTxOutByScript @PlutusScriptV3 inputUTxO headScript (TxIn depositTxId _, depositOutput) <- findTxOutByScript @PlutusScriptV3 utxo depositScript @@ -350,8 +354,8 @@ observeIncrementTx utxo tx = do _ -> Nothing _ -> Nothing where - depositScript = fromPlutusScript depositValidatorScript - headScript = fromPlutusScript Head.validatorScript + depositScript = fromPlutusScript depositScriptValidator + headScript = fromPlutusScript headScriptValidator data DecrementObservation = DecrementObservation { headId :: HeadId @@ -361,10 +365,11 @@ data DecrementObservation = DecrementObservation deriving stock (Show, Eq, Generic) observeDecrementTx :: + SerialisedScriptRegistry -> UTxO -> Tx -> Maybe DecrementObservation -observeDecrementTx utxo tx = do +observeDecrementTx SerialisedScriptRegistry{headScriptValidator} utxo tx = do let inputUTxO = resolveInputsUTxO utxo tx (headInput, headOutput) <- findTxOutByScript @PlutusScriptV3 inputUTxO headScript redeemer <- findRedeemerSpending tx headInput @@ -389,7 +394,7 @@ observeDecrementTx utxo tx = do _ -> Nothing _ -> Nothing where - headScript = fromPlutusScript Head.validatorScript + headScript = fromPlutusScript headScriptValidator data CloseObservation = CloseObservation { threadOutput :: ClosedThreadOutput @@ -401,11 +406,12 @@ data CloseObservation = CloseObservation -- | Identify a close tx by lookup up the input spending the Head output and -- decoding its redeemer. observeCloseTx :: + SerialisedScriptRegistry -> -- | A UTxO set to lookup tx inputs UTxO -> Tx -> Maybe CloseObservation -observeCloseTx utxo tx = do +observeCloseTx SerialisedScriptRegistry{headScriptValidator} utxo tx = do let inputUTxO = resolveInputsUTxO utxo tx (headInput, headOutput) <- findTxOutByScript @PlutusScriptV3 inputUTxO headScript redeemer <- findRedeemerSpending tx headInput @@ -434,7 +440,7 @@ observeCloseTx utxo tx = do } _ -> Nothing where - headScript = fromPlutusScript Head.validatorScript + headScript = fromPlutusScript headScriptValidator data ContestObservation = ContestObservation { contestedThreadOutput :: (TxIn, TxOut CtxUTxO) @@ -448,11 +454,12 @@ data ContestObservation = ContestObservation -- | Identify a close tx by lookup up the input spending the Head output and -- decoding its redeemer. observeContestTx :: + SerialisedScriptRegistry -> -- | A UTxO set to lookup tx inputs UTxO -> Tx -> Maybe ContestObservation -observeContestTx utxo tx = do +observeContestTx SerialisedScriptRegistry{headScriptValidator} utxo tx = do let inputUTxO = resolveInputsUTxO utxo tx (headInput, headOutput) <- findTxOutByScript @PlutusScriptV3 inputUTxO headScript redeemer <- findRedeemerSpending tx headInput @@ -474,7 +481,7 @@ observeContestTx utxo tx = do } _ -> Nothing where - headScript = fromPlutusScript Head.validatorScript + headScript = fromPlutusScript headScriptValidator decodeDatum headDatum = case fromScriptData headDatum of @@ -487,11 +494,12 @@ newtype FanoutObservation = FanoutObservation {headId :: HeadId} deriving stock -- | Identify a fanout tx by lookup up the input spending the Head output and -- decoding its redeemer. observeFanoutTx :: + SerialisedScriptRegistry -> -- | A UTxO set to lookup tx inputs UTxO -> Tx -> Maybe FanoutObservation -observeFanoutTx utxo tx = do +observeFanoutTx SerialisedScriptRegistry{headScriptValidator} utxo tx = do let inputUTxO = resolveInputsUTxO utxo tx (headInput, headOutput) <- findTxOutByScript @PlutusScriptV3 inputUTxO headScript headId <- findStateToken headOutput @@ -500,18 +508,19 @@ observeFanoutTx utxo tx = do Head.Fanout{} -> pure FanoutObservation{headId} _ -> Nothing where - headScript = fromPlutusScript Head.validatorScript + headScript = fromPlutusScript headScriptValidator newtype AbortObservation = AbortObservation {headId :: HeadId} deriving stock (Eq, Show, Generic) -- | Identify an abort tx by looking up the input spending the Head output and -- decoding its redeemer. observeAbortTx :: + SerialisedScriptRegistry -> -- | A UTxO set to lookup tx inputs UTxO -> Tx -> Maybe AbortObservation -observeAbortTx utxo tx = do +observeAbortTx SerialisedScriptRegistry{headScriptValidator} utxo tx = do let inputUTxO = resolveInputsUTxO utxo tx (headInput, headOutput) <- findTxOutByScript @PlutusScriptV3 inputUTxO headScript headId <- findStateToken headOutput @@ -519,7 +528,7 @@ observeAbortTx utxo tx = do Head.Abort -> pure $ AbortObservation headId _ -> Nothing where - headScript = fromPlutusScript Head.validatorScript + headScript = fromPlutusScript headScriptValidator -- * Cardano specific identifiers diff --git a/hydra-node/src/Hydra/Options.hs b/hydra-node/src/Hydra/Options.hs index 8cff84c5d02..78564fd3da5 100644 --- a/hydra-node/src/Hydra/Options.hs +++ b/hydra-node/src/Hydra/Options.hs @@ -38,6 +38,7 @@ import Hydra.Contract qualified as Contract import Hydra.Ledger.Cardano () import Hydra.Logging (Verbosity (..)) import Hydra.Network (Host, NodeId (NodeId), PortNumber, readHost, readPort) +import Hydra.SerialisedScriptRegistry (serialisedScriptRegistry) import Hydra.Tx.ContestationPeriod (ContestationPeriod (UnsafeContestationPeriod), fromNominalDiffTime) import Hydra.Version (embeddedRevision, gitRevision, unknownVersion) import Options.Applicative ( @@ -760,7 +761,7 @@ hydraNodeCommand = scriptInfo = infoOption - (decodeUtf8 $ encodePretty Contract.scriptInfo) + (decodeUtf8 $ encodePretty (Contract.scriptInfo serialisedScriptRegistry)) (long "script-info" <> help "Dump script info as JSON") hydraNodeVersion :: Version diff --git a/hydra-node/test/Hydra/Chain/Direct/StateSpec.hs b/hydra-node/test/Hydra/Chain/Direct/StateSpec.hs index 607cebd5aeb..4f012f587b9 100644 --- a/hydra-node/test/Hydra/Chain/Direct/StateSpec.hs +++ b/hydra-node/test/Hydra/Chain/Direct/StateSpec.hs @@ -112,6 +112,7 @@ import Hydra.Ledger.Cardano.Evaluate ( ) import Hydra.Ledger.Cardano.Time (slotNoFromUTCTime) import Hydra.Plutus (initialValidatorScript) +import Hydra.SerialisedScriptRegistry (serialisedScriptRegistry) import Hydra.Tx.Contest (ClosedThreadOutput (closedContesters)) import Hydra.Tx.ContestationPeriod (toNominalDiffTime) import Hydra.Tx.Deposit (DepositObservation (..), observeDepositTx) @@ -183,7 +184,7 @@ spec = parallel $ do let utxo = UTxO.singleton (seedInput, seedTxOut) let (tx', utxo') = applyMutation mutation (tx, utxo) - originalIsObserved = property $ isRight (observeInitTx tx) + originalIsObserved = property $ isRight (observeInitTx serialisedScriptRegistry tx) -- We expected mutated transaction to still be valid, but not observed. mutatedIsValid = property $ @@ -194,7 +195,7 @@ spec = parallel $ do | otherwise -> False mutatedIsNotObserved = - observeInitTx tx' === Left expected + observeInitTx serialisedScriptRegistry tx' === Left expected pure $ conjoin @@ -224,7 +225,7 @@ spec = parallel $ do mutation <- pick $ genCommitTxMutation utxo tx let (tx', utxo') = applyMutation mutation (tx, utxo) - originalIsObserved = property $ isJust $ observeCommitTx testNetworkId utxo tx + originalIsObserved = property $ isJust $ observeCommitTx testNetworkId serialisedScriptRegistry utxo tx -- We expected mutated transaction to still be valid, but not observed. mutatedIsValid = @@ -235,7 +236,7 @@ spec = parallel $ do | otherwise -> property False & counterexample (show ok) mutatedIsNotObserved = - isNothing $ observeCommitTx testNetworkId utxo' tx' + isNothing $ observeCommitTx testNetworkId serialisedScriptRegistry utxo' tx' pure $ conjoin @@ -332,7 +333,7 @@ spec = parallel $ do prop "observes deposit" $ forAllDeposit $ \utxo tx -> - case observeDepositTx testNetworkId tx of + case observeDepositTx testNetworkId serialisedScriptRegistry tx of Just DepositObservation{} -> property True Nothing -> False & counterexample ("observeDepositTx ignored transaction: " <> renderTxWithUTxO utxo tx) @@ -343,7 +344,7 @@ spec = parallel $ do prop "observes recover" $ forAllRecover $ \utxo tx -> - case observeRecoverTx testNetworkId utxo tx of + case observeRecoverTx testNetworkId serialisedScriptRegistry utxo tx of Just RecoverObservation{} -> property True Nothing -> False & counterexample ("observeRecoverTx ignored transaction: " <> renderTxWithUTxO utxo tx) @@ -358,7 +359,7 @@ spec = parallel $ do prop "observes distributed outputs" $ forAllDecrement' $ \toDistribute utxo tx -> - case observeDecrementTx utxo tx of + case observeDecrementTx serialisedScriptRegistry utxo tx of Just DecrementObservation{distributedOutputs} -> distributedOutputs === toDistribute Nothing -> @@ -451,7 +452,7 @@ prop_observeAnyTx = genericCoverTable [transition] $ do let expectedHeadId = chainStateHeadId st utxo = getKnownUTxO st <> getKnownUTxO otherSt <> additionalUTxO <> additionalUTxO' - case observeHeadTx (networkId ctx) utxo tx of + case observeHeadTx (networkId ctx) serialisedScriptRegistry utxo tx of NoHeadTx -> False & counterexample ("observeHeadTx ignored transaction: " <> renderTxWithUTxO utxo tx) -- NOTE: we don't have the generated headId easily accessible in the initial state diff --git a/hydra-node/test/Hydra/Chain/Direct/TxSpec.hs b/hydra-node/test/Hydra/Chain/Direct/TxSpec.hs index 40ed3140548..14aa35faa61 100644 --- a/hydra-node/test/Hydra/Chain/Direct/TxSpec.hs +++ b/hydra-node/test/Hydra/Chain/Direct/TxSpec.hs @@ -46,6 +46,7 @@ import Hydra.Contract.Dummy (dummyValidatorScript) import Hydra.Contract.HeadTokens (headPolicyId) import Hydra.Ledger.Cardano.Builder (addTxInsSpending, unsafeBuildTransaction) import Hydra.Ledger.Cardano.Evaluate (propTransactionEvaluates) +import Hydra.SerialisedScriptRegistry (serialisedScriptRegistry) import Hydra.Tx.BlueprintTx (CommitBlueprintTx (..)) import Hydra.Tx.Commit (commitTx) import Hydra.Tx.HeadId (headIdToCurrencySymbol, mkHeadId) @@ -114,7 +115,7 @@ spec = genericCoverTable [transition] $ counterexample (show transition) $ let utxo = getKnownUTxO st <> additionalUTxO - in case observeHeadTx testNetworkId utxo tx of + in case observeHeadTx testNetworkId serialisedScriptRegistry utxo tx of NoHeadTx -> property False Init{} -> transition === Transition.Init Abort{} -> transition === Transition.Abort diff --git a/hydra-node/test/Hydra/Chain/Direct/TxTraceSpec.hs b/hydra-node/test/Hydra/Chain/Direct/TxTraceSpec.hs index c36635b6914..0eac5160961 100644 --- a/hydra-node/test/Hydra/Chain/Direct/TxTraceSpec.hs +++ b/hydra-node/test/Hydra/Chain/Direct/TxTraceSpec.hs @@ -52,6 +52,7 @@ import Hydra.Chain.Direct.Tx qualified as Tx import Hydra.Contract.HeadState qualified as Head import Hydra.Ledger.Cardano (Tx, adjustUTxO) import Hydra.Ledger.Cardano.Evaluate (evaluateTx) +import Hydra.SerialisedScriptRegistry (serialisedScriptRegistry) import Hydra.Tx (CommitBlueprintTx (..)) import Hydra.Tx.ContestationPeriod qualified as CP import Hydra.Tx.Crypto (MultiSignature, aggregate, sign) @@ -458,8 +459,7 @@ instance StateModel Model where && (if snapshot.version == currentVersion then snapshot.toCommit == mempty && snapshot.toDecommit == mempty else snapshot.toCommit /= mempty || snapshot.toDecommit /= mempty) && ( if snapshot.number == 0 then snapshot.inHead == initialUTxOInHead - else - snapshot.version `elem` (currentVersion : [currentVersion - 1 | currentVersion > 0]) + else snapshot.version `elem` (currentVersion : [currentVersion - 1 | currentVersion > 0]) ) where Model{utxoInHead = initialUTxOInHead} = initialState @@ -508,8 +508,7 @@ instance StateModel Model where && (if snapshot.version == currentVersion then snapshot.toCommit == mempty && snapshot.toDecommit == mempty else snapshot.toCommit /= mempty || snapshot.toDecommit /= mempty) && ( if snapshot.number == 0 then snapshot.inHead == initialUTxOInHead - else - snapshot.version `elem` (currentVersion : [currentVersion - 1 | currentVersion > 0]) + else snapshot.version `elem` (currentVersion : [currentVersion - 1 | currentVersion > 0]) ) where Model{utxoInHead = initialUTxOInHead} = initialState @@ -701,7 +700,7 @@ performTx action result = Deposit{} -> (Just . getTxId . getTxBody $ tx, adjustUTxO tx utxo) _ -> (depositTxId, adjustUTxO tx utxo) put adjusted - let observation = observeHeadTx Fixture.testNetworkId utxo tx + let observation = observeHeadTx Fixture.testNetworkId serialisedScriptRegistry utxo tx pure TxResult { constructedTx = Right tx diff --git a/hydra-plutus/exe/inspect-script/Main.hs b/hydra-plutus/exe/inspect-script/Main.hs index 56dbc710f30..8fb962a2eb5 100644 --- a/hydra-plutus/exe/inspect-script/Main.hs +++ b/hydra-plutus/exe/inspect-script/Main.hs @@ -14,6 +14,7 @@ import Hydra.Contract.HeadState as Head import Hydra.Contract.HeadTokens qualified as HeadTokens import Hydra.Contract.Initial as Initial import Hydra.Plutus (initialValidatorScript) +import Hydra.SerialisedScriptRegistry (serialisedScriptRegistry) import PlutusLedgerApi.V3 (Data, SerialisedScript, toData) import PlutusTx (getPlc) import PlutusTx.Code (CompiledCode) @@ -26,7 +27,7 @@ import Prettyprinter.Render.Text (renderStrict) main :: IO () main = do putTextLn "Script info:" - putLBSLn $ encodePretty scriptInfo + putLBSLn $ encodePretty (scriptInfo serialisedScriptRegistry) putTextLn "Serialise scripts:" writeScripts scripts diff --git a/hydra-plutus/hydra-plutus.cabal b/hydra-plutus/hydra-plutus.cabal index 50fe0ac73d1..7f57139c0b1 100644 --- a/hydra-plutus/hydra-plutus.cabal +++ b/hydra-plutus/hydra-plutus.cabal @@ -62,6 +62,7 @@ library Hydra.Data.ContestationPeriod Hydra.Data.Party Hydra.Plutus + Hydra.SerialisedScriptRegistry hs-source-dirs: src build-depends: @@ -69,6 +70,7 @@ library , base , base16-bytestring , bytestring + , cborg , file-embed , hydra-cardano-api , hydra-plutus-extras diff --git a/hydra-plutus/src/Hydra/Contract.hs b/hydra-plutus/src/Hydra/Contract.hs index 85333b23fcd..d05450b8d64 100644 --- a/hydra-plutus/src/Hydra/Contract.hs +++ b/hydra-plutus/src/Hydra/Contract.hs @@ -14,9 +14,9 @@ import Hydra.Cardano.Api ( pattern PlutusScript, ) import Hydra.Cardano.Api.Prelude qualified as Api -import Hydra.Contract.Head qualified as Head import Hydra.Contract.HeadTokens qualified as HeadTokens import Hydra.Plutus (commitValidatorScript, depositValidatorScript, initialValidatorScript) +import Hydra.SerialisedScriptRegistry (SerialisedScriptRegistry (..)) import PlutusLedgerApi.V3 (TxId (..), TxOutRef (..), toBuiltin) -- | Information about relevant Hydra scripts. @@ -39,21 +39,28 @@ data ScriptInfo = ScriptInfo -- | Gather 'ScriptInfo' from the current Hydra scripts. This is useful to -- determine changes in between version of 'hydra-plutus'. -scriptInfo :: ScriptInfo -scriptInfo = +scriptInfo :: SerialisedScriptRegistry -> ScriptInfo +scriptInfo serialisedScriptRegistry = ScriptInfo { mintingScriptHash = plutusScriptHash $ HeadTokens.mintingPolicyScript defaultOutRef , mintingScriptSize = scriptSize $ HeadTokens.mintingPolicyScript defaultOutRef - , initialScriptHash = hashScript $ Api.PlutusScript PlutusScriptV3 $ fromPlutusScript initialValidatorScript - , initialScriptSize = scriptSize initialValidatorScript - , commitScriptHash = hashScript $ Api.PlutusScript PlutusScriptV3 $ fromPlutusScript commitValidatorScript - , commitScriptSize = scriptSize commitValidatorScript - , headScriptHash = plutusScriptHash Head.validatorScript - , headScriptSize = scriptSize Head.validatorScript - , depositScriptHash = hashScript $ Api.PlutusScript PlutusScriptV3 $ fromPlutusScript depositValidatorScript - , depositScriptSize = scriptSize depositValidatorScript + , initialScriptHash = hashScript $ Api.PlutusScript PlutusScriptV3 $ fromPlutusScript initialScriptValidator + , initialScriptSize = scriptSize initialScriptValidator + , commitScriptHash = hashScript $ Api.PlutusScript PlutusScriptV3 $ fromPlutusScript commitScriptValidator + , commitScriptSize = scriptSize commitScriptValidator + , headScriptHash = plutusScriptHash headScriptValidator + , headScriptSize = scriptSize headScriptValidator + , depositScriptHash = hashScript $ Api.PlutusScript PlutusScriptV3 $ fromPlutusScript depositScriptValidator + , depositScriptSize = scriptSize depositScriptValidator } where + SerialisedScriptRegistry + { initialScriptValidator + , commitScriptValidator + , headScriptValidator + , depositScriptValidator + } = serialisedScriptRegistry + plutusScriptHash = hashScript . PlutusScript . fromPlutusScript diff --git a/hydra-plutus/src/Hydra/SerialisedScriptRegistry.hs b/hydra-plutus/src/Hydra/SerialisedScriptRegistry.hs new file mode 100644 index 00000000000..171437f5485 --- /dev/null +++ b/hydra-plutus/src/Hydra/SerialisedScriptRegistry.hs @@ -0,0 +1,45 @@ +module Hydra.SerialisedScriptRegistry where + +import Hydra.Prelude + +import Codec.CBOR.Read qualified as CBOR +import Data.ByteString.Base16 qualified as Base16 + +import Data.ByteString.Lazy qualified as LBS +import Data.ByteString.Short qualified as SBS +import Hydra.Contract.Head qualified as Head +import Hydra.Plutus (commitValidatorScript, depositValidatorScript, initialValidatorScript) +import PlutusLedgerApi.Common (SerialisedScript) + +data SerialisedScriptRegistry = SerialisedScriptRegistry + { initialScriptValidator :: SerialisedScript + , commitScriptValidator :: SerialisedScript + , headScriptValidator :: SerialisedScript + , depositScriptValidator :: SerialisedScript + } + deriving stock (Eq, Show) + +serialisedScriptRegistry :: SerialisedScriptRegistry +serialisedScriptRegistry = + SerialisedScriptRegistry + { initialScriptValidator = initialValidatorScript + , commitScriptValidator = commitValidatorScript + , headScriptValidator = Head.validatorScript + , depositScriptValidator = depositValidatorScript + } + +-- XXX: used to parse Aiken `compiledCode`. +serialisedScriptFromText :: Text -> SerialisedScript +serialisedScriptFromText base16Text = + case Base16.decode base16Bytes of + Left e -> error $ "Failed to decode initial validator: " <> show e + Right bytes -> toShort bytes + where + base16Bytes = encodeUtf8 base16Text + +-- XXX: used to parse Plutus `cborHex`. +cborHexToSerialisedScript :: ByteString -> SerialisedScript +cborHexToSerialisedScript cborHex = either (error . show) SBS.toShort $ do + bytes <- Base16.decode cborHex + (_, a) <- first show $ CBOR.deserialiseFromBytes @ByteString fromCBOR (LBS.fromStrict bytes) + pure a diff --git a/hydra-tx/src/Hydra/Tx/Deposit.hs b/hydra-tx/src/Hydra/Tx/Deposit.hs index 88913b65e0a..dd13120ed92 100644 --- a/hydra-tx/src/Hydra/Tx/Deposit.hs +++ b/hydra-tx/src/Hydra/Tx/Deposit.hs @@ -13,6 +13,7 @@ import Hydra.Contract.Commit qualified as Commit import Hydra.Contract.Deposit qualified as Deposit import Hydra.Plutus (depositValidatorScript) import Hydra.Plutus.Extras.Time (posixFromUTCTime) +import Hydra.SerialisedScriptRegistry (SerialisedScriptRegistry (..)) import Hydra.Tx (CommitBlueprintTx (..), HeadId, fromCurrencySymbol, headIdToCurrencySymbol) import Hydra.Tx.Utils (addMetadata, mkHydraHeadV1TxName) import PlutusLedgerApi.V3 (POSIXTime) @@ -76,11 +77,12 @@ data DepositObservation = DepositObservation observeDepositTx :: NetworkId -> + SerialisedScriptRegistry -> Tx -> Maybe DepositObservation -observeDepositTx networkId tx = do +observeDepositTx networkId SerialisedScriptRegistry{depositScriptValidator} tx = do -- TODO: could just use the first output and fail otherwise - (TxIn depositTxId _, depositOut) <- findTxOutByAddress (depositAddress networkId) tx + (TxIn depositTxId _, depositOut) <- findTxOutByAddress depositAddr tx (headId, deposited, deadline) <- observeDepositTxOut (networkIdToNetwork networkId) (toCtxUTxOTxOut depositOut) if all (`elem` txIns' tx) (UTxO.inputSet deposited) then @@ -92,8 +94,15 @@ observeDepositTx networkId tx = do , deadline } else Nothing + where + depositScript = fromPlutusScript depositScriptValidator + + depositAddr = mkScriptAddress @PlutusScriptV3 networkId depositScript -observeDepositTxOut :: Network -> TxOut CtxUTxO -> Maybe (HeadId, UTxO, POSIXTime) +observeDepositTxOut :: + Network -> + TxOut CtxUTxO -> + Maybe (HeadId, UTxO, POSIXTime) observeDepositTxOut network depositOut = do dat <- case txOutDatum depositOut of TxOutDatumInline d -> pure d diff --git a/hydra-tx/src/Hydra/Tx/Recover.hs b/hydra-tx/src/Hydra/Tx/Recover.hs index a18f03c6daa..41e2be18ef6 100644 --- a/hydra-tx/src/Hydra/Tx/Recover.hs +++ b/hydra-tx/src/Hydra/Tx/Recover.hs @@ -10,6 +10,7 @@ import Hydra.Ledger.Cardano.Builder ( unsafeBuildTransaction, ) import Hydra.Plutus (depositValidatorScript) +import Hydra.SerialisedScriptRegistry (SerialisedScriptRegistry (..)) import Hydra.Tx (HeadId, mkHeadId) import Hydra.Tx.Utils (mkHydraHeadV1TxName) @@ -52,10 +53,11 @@ data RecoverObservation = RecoverObservation observeRecoverTx :: NetworkId -> + SerialisedScriptRegistry -> UTxO -> Tx -> Maybe RecoverObservation -observeRecoverTx networkId utxo tx = do +observeRecoverTx networkId SerialisedScriptRegistry{depositScriptValidator} utxo tx = do let inputUTxO = resolveInputsUTxO utxo tx (TxIn depositTxId _, depositOut) <- findTxOutByScript @PlutusScriptV3 inputUTxO depositScript dat <- txOutScriptData $ toTxContext depositOut @@ -77,4 +79,4 @@ observeRecoverTx networkId utxo tx = do ) else Nothing where - depositScript = fromPlutusScript depositValidatorScript + depositScript = fromPlutusScript depositScriptValidator diff --git a/hydra-tx/src/Hydra/Tx/ScriptRegistry.hs b/hydra-tx/src/Hydra/Tx/ScriptRegistry.hs index 8f9f5247fe4..c3cfc4d035a 100644 --- a/hydra-tx/src/Hydra/Tx/ScriptRegistry.hs +++ b/hydra-tx/src/Hydra/Tx/ScriptRegistry.hs @@ -4,20 +4,11 @@ module Hydra.Tx.ScriptRegistry where import Hydra.Prelude -import Cardano.Api.UTxO (UTxO) import Cardano.Api.UTxO qualified as UTxO import Data.Map qualified as Map -import Hydra.Cardano.Api ( - CtxUTxO, - ScriptHash, - TxIn (..), - TxOut, - hashScriptInAnyLang, - txOutReferenceScript, - pattern ReferenceScript, - pattern ReferenceScriptNone, - ) +import Hydra.Cardano.Api import Hydra.Contract (ScriptInfo (..), scriptInfo) +import Hydra.SerialisedScriptRegistry (serialisedScriptRegistry) -- | Hydra scripts published as reference scripts at these UTxO. data ScriptRegistry = ScriptRegistry @@ -70,7 +61,7 @@ newScriptRegistry = { initialScriptHash , commitScriptHash , headScriptHash - } = scriptInfo + } = scriptInfo serialisedScriptRegistry -- | Get the UTxO that corresponds to a script registry. --