Skip to content

Commit 6e7b43a

Browse files
authored
Merge pull request #1196 from input-output-hk/ensemble/stateless-observation-hydra-node
Stateless observation hydra node
2 parents 06feee9 + ead4dab commit 6e7b43a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+23062
-20419
lines changed

CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
As a minor extension, we also keep a semantic version for the `UNRELEASED`
99
changes.
1010

11-
## [0.15.0] - UNRELEASEd
11+
12+
## [0.15.0] - UNRELEASED
13+
14+
- Hydra Direct Chain layer does not maintain state and does not make any logic
15+
decisions. This is now completely responsibility of the HydraLogic layer.
16+
Posting transactions from this layer is now free of any knowledge of L1 keys.
17+
[1196](https://github.com/input-output-hk/hydra/pull/1196)
1218

1319
- **BREAKING** Internal changes to `hydra-cardano-api`:
1420
- Renamed `HasMultiAsset` type class to `IsMaryEraOnwards`. Use
@@ -18,6 +24,7 @@ changes.
1824
- Renamed `HasInlineDatums` type class to `IsBabbageEraOnwards`. Use
1925
`babbageEraOnwards` to produce witnesses for features from babbage onwards.
2026

27+
2128
## [0.14.0] - 2023-12-04
2229

2330
- **BREAKING** Multiple changes to the Hydra Head protocol on-chain:

hydra-cardano-api/src/Hydra/Cardano/Api/Hash.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import Cardano.Ledger.Shelley.Scripts qualified as Ledger
99
import Data.ByteString qualified as BS
1010
import PlutusLedgerApi.V2 qualified as Plutus
1111

12+
-- * Type conversions
13+
1214
-- | Convert a cardano-api 'Hash' into a plutus 'PubKeyHash'
1315
toPlutusKeyHash :: Hash PaymentKey -> Plutus.PubKeyHash
1416
toPlutusKeyHash (PaymentKeyHash vkh) =
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,38 @@
1+
{-# OPTIONS_GHC -Wno-orphans #-}
2+
13
module Hydra.Cardano.Api.PolicyId where
24

35
import Hydra.Cardano.Api.Prelude
46

7+
import Cardano.Ledger.Alonzo.TxInfo qualified as Ledger
58
import Cardano.Ledger.Hashes qualified as Ledger
9+
import Cardano.Ledger.Mary.Value qualified as Ledger
10+
import Hydra.Cardano.Api.ScriptHash ()
11+
import PlutusLedgerApi.V2 (CurrencySymbol, fromBuiltin, unCurrencySymbol)
12+
13+
-- * Orphans
14+
15+
instance Arbitrary PolicyId where
16+
arbitrary = PolicyId <$> arbitrary
17+
18+
-- * Type conversions
619

720
toLedgerScriptHash :: PolicyId -> Ledger.ScriptHash StandardCrypto
821
toLedgerScriptHash (PolicyId scriptHash) = toShelleyScriptHash scriptHash
22+
23+
-- | Convert Cardano api 'PolicyId' to Cardano ledger `PolicyID`.
24+
toLedgerPolicyID :: PolicyId -> Ledger.PolicyID StandardCrypto
25+
toLedgerPolicyID (PolicyId sh) = Ledger.PolicyID (toShelleyScriptHash sh)
26+
27+
-- | Convert Cardano api 'PolicyId' to Plutus `CurrencySymbol`.
28+
toPlutusCurrencySymbol :: PolicyId -> CurrencySymbol
29+
toPlutusCurrencySymbol = Ledger.transPolicyID . toLedgerPolicyID
30+
31+
-- | Convert a plutus 'CurrencySymbol' into a cardano-api 'PolicyId'.
32+
fromPlutusCurrencySymbol :: MonadFail m => CurrencySymbol -> m PolicyId
33+
fromPlutusCurrencySymbol cs =
34+
case deserialiseFromRawBytes AsPolicyId bytes of
35+
Left err -> fail (show err)
36+
Right pid -> pure pid
37+
where
38+
bytes = fromBuiltin $ unCurrencySymbol cs

hydra-cardano-api/src/Hydra/Cardano/Api/ScriptHash.hs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
{-# OPTIONS_GHC -Wno-orphans #-}
2+
13
module Hydra.Cardano.Api.ScriptHash where
24

35
import Hydra.Cardano.Api.Prelude
46

57
import Cardano.Ledger.Credential qualified as Ledger
8+
import Hydra.Cardano.Api.PlutusScript ()
9+
10+
-- * Extras
611

712
-- | Extract the payment part of an address, as a script hash.
813
getPaymentScriptHash :: AddressInEra era -> Maybe ScriptHash
@@ -16,3 +21,10 @@ getPaymentScriptHash = \case
1621
hashScriptInAnyLang :: ScriptInAnyLang -> ScriptHash
1722
hashScriptInAnyLang (ScriptInAnyLang _ script) =
1823
hashScript script
24+
25+
-- * Orphans
26+
27+
instance Arbitrary ScriptHash where
28+
arbitrary = do
29+
plutusScript <- arbitrary
30+
pure $ hashScript (PlutusScript PlutusScriptV2 plutusScript)

hydra-cardano-api/src/Hydra/Cardano/Api/TxBody.hs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,17 @@ module Hydra.Cardano.Api.TxBody where
22

33
import Hydra.Cardano.Api.Prelude
44

5-
import Hydra.Cardano.Api.PlutusScript (fromLedgerScript)
6-
import Hydra.Cardano.Api.PolicyId (toLedgerScriptHash)
7-
import Hydra.Cardano.Api.ScriptData (FromScriptData)
8-
import Hydra.Cardano.Api.TxIn (toLedgerTxIn)
9-
import Hydra.Cardano.Api.Value (toLedgerPolicyID)
10-
115
import Cardano.Ledger.Alonzo.Scripts.Data qualified as Ledger
126
import Cardano.Ledger.Alonzo.TxWits qualified as Ledger
137
import Cardano.Ledger.Babbage.Tx qualified as Ledger
148
import Cardano.Ledger.BaseTypes (strictMaybeToMaybe)
159
import Cardano.Ledger.Core qualified as Ledger
1610
import Data.List (find)
1711
import Data.Map qualified as Map
12+
import Hydra.Cardano.Api.PlutusScript (fromLedgerScript)
13+
import Hydra.Cardano.Api.PolicyId (toLedgerPolicyID, toLedgerScriptHash)
14+
import Hydra.Cardano.Api.ScriptData (FromScriptData)
15+
import Hydra.Cardano.Api.TxIn (toLedgerTxIn)
1816
import PlutusLedgerApi.V2 qualified as Plutus
1917

2018
-- | Find and deserialise from 'ScriptData', a redeemer from the transaction

hydra-cardano-api/src/Hydra/Cardano/Api/TxOut.hs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ findTxOutByAddress address tx =
8686
where
8787
indexedOutputs = zip [mkTxIn tx ix | ix <- [0 ..]] (txOuts' tx)
8888

89+
-- | Find a single script output in some 'UTxO'
8990
findTxOutByScript ::
9091
forall lang.
9192
IsPlutusScriptLanguage lang =>
@@ -102,6 +103,28 @@ findTxOutByScript utxo script =
102103
in scriptHash == scriptHash'
103104
_ ->
104105
False
106+
107+
-- | Predicate to find or filter 'TxOut' which are governed by some script. This
108+
-- is better than comparing the full address as it does not require a network
109+
-- discriminator.
110+
isScriptTxOut ::
111+
forall lang ctx era.
112+
IsPlutusScriptLanguage lang =>
113+
PlutusScript lang ->
114+
TxOut ctx era ->
115+
Bool
116+
isScriptTxOut script txOut =
117+
case address of
118+
(AddressInEra (ShelleyAddressInEra _) (ShelleyAddress _ (Ledger.ScriptHashObj sh) _)) ->
119+
scriptHash == sh
120+
_ -> False
121+
where
122+
scriptHash = toShelleyScriptHash $ hashScript $ PlutusScript version script
123+
124+
version = plutusScriptVersion @lang
125+
126+
(TxOut address _ _ _) = txOut
127+
105128
-- * Type Conversions
106129

107130
-- | Convert a cardano-ledger 'TxOut' into a cardano-api 'TxOut'
@@ -122,14 +145,13 @@ fromPlutusTxOut ::
122145
(IsMaryEraOnwards era, IsAlonzoEraOnwards era, IsBabbageEraOnwards era, IsShelleyBasedEra era) =>
123146
Network ->
124147
Plutus.TxOut ->
125-
TxOut CtxUTxO era
126-
fromPlutusTxOut network out =
127-
TxOut addressInEra value datum ReferenceScriptNone
148+
Maybe (TxOut CtxUTxO era)
149+
fromPlutusTxOut network out = do
150+
value <- TxOutValue maryEraOnwards <$> fromPlutusValue plutusValue
151+
pure $ TxOut addressInEra value datum ReferenceScriptNone
128152
where
129153
addressInEra = fromPlutusAddress network plutusAddress
130154

131-
value = TxOutValue maryEraOnwards $ fromPlutusValue plutusValue
132-
133155
datum = case plutusDatum of
134156
NoOutputDatum -> TxOutDatumNone
135157
OutputDatumHash (Plutus.DatumHash hashBytes) ->

hydra-cardano-api/src/Hydra/Cardano/Api/UTxO.hs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module Hydra.Cardano.Api.UTxO where
22

33
import Hydra.Cardano.Api.Prelude
44
import Hydra.Cardano.Api.TxId (toLedgerTxId)
5-
import Hydra.Cardano.Api.TxIn (fromLedgerTxIn, toLedgerTxIn)
5+
import Hydra.Cardano.Api.TxIn (fromLedgerTxIn, toLedgerTxIn, txIns')
66
import Hydra.Cardano.Api.TxOut (fromLedgerTxOut, toLedgerTxOut)
77

88
import Cardano.Api.UTxO qualified as UTxO
@@ -12,6 +12,7 @@ import Cardano.Ledger.Shelley.UTxO qualified as Ledger
1212
import Cardano.Ledger.TxIn qualified as Ledger
1313
import Data.Foldable (toList)
1414
import Data.Map qualified as Map
15+
import Data.Maybe (mapMaybe)
1516
import Data.String (IsString (..))
1617
import Data.Text qualified as Text
1718

@@ -32,6 +33,12 @@ utxoFromTx (Tx body@(ShelleyTxBody _ ledgerBody _ _ _ _) _) =
3233
]
3334
in fromLedgerUTxO $ Ledger.UTxO $ Map.fromList $ zip txIns txOuts
3435

36+
-- | Resolve tx inputs in a given UTxO
37+
resolveInputsUTxO :: UTxO -> Tx Era -> UTxO
38+
resolveInputsUTxO utxo tx =
39+
UTxO.fromPairs $
40+
mapMaybe (\txIn -> (txIn,) <$> UTxO.resolve txIn utxo) (txIns' tx)
41+
3542
-- * Type Conversions
3643

3744
toLedgerUTxO :: UTxO -> Ledger.UTxO LedgerEra

hydra-cardano-api/src/Hydra/Cardano/Api/Value.hs

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ import Data.Word (Word64)
1010
import Hydra.Cardano.Api.CtxUTxO (ToUTxOContext (..))
1111
import Hydra.Cardano.Api.Hash (unsafeScriptHashFromBytes)
1212
import Hydra.Cardano.Api.MaryEraOnwards (maryEraOnwards)
13+
import Hydra.Cardano.Api.PolicyId (fromPlutusCurrencySymbol)
1314
import PlutusLedgerApi.V1.Value (flattenValue)
14-
import PlutusLedgerApi.V2 (CurrencySymbol, adaSymbol, adaToken, fromBuiltin, unCurrencySymbol, unTokenName)
15+
import PlutusLedgerApi.V2 (adaSymbol, adaToken, fromBuiltin, unTokenName)
1516
import PlutusLedgerApi.V2 qualified as Plutus
1617

1718
-- * Extras
@@ -82,13 +83,16 @@ toLedgerValue =
8283
toMaryValue
8384

8485
-- | Convert a plutus 'Value' into a cardano-api 'Value'.
85-
fromPlutusValue :: Plutus.Value -> Value
86-
fromPlutusValue plutusValue =
87-
valueFromList $ map convertAsset $ flattenValue plutusValue
86+
fromPlutusValue :: Plutus.Value -> Maybe Value
87+
fromPlutusValue plutusValue = do
88+
fmap valueFromList . mapM convertAsset $ flattenValue plutusValue
8889
where
8990
convertAsset (cs, tk, i)
90-
| cs == adaSymbol && tk == adaToken = (AdaAssetId, Quantity i)
91-
| otherwise = (AssetId (fromPlutusCurrencySymbol cs) (toAssetName tk), Quantity i)
91+
| cs == adaSymbol && tk == adaToken =
92+
pure (AdaAssetId, Quantity i)
93+
| otherwise = do
94+
pid <- fromPlutusCurrencySymbol cs
95+
pure (AssetId pid (toAssetName tk), Quantity i)
9296

9397
toAssetName :: Plutus.TokenName -> AssetName
9498
toAssetName = AssetName . fromBuiltin . unTokenName
@@ -97,15 +101,3 @@ fromPlutusValue plutusValue =
97101
toPlutusValue :: Value -> Plutus.Value
98102
toPlutusValue =
99103
Ledger.transValue . toLedgerValue
100-
101-
-- | Convert Cardano api 'PolicyId' to Plutus `CurrencySymbol`.
102-
toPlutusCurrencySymbol :: PolicyId -> CurrencySymbol
103-
toPlutusCurrencySymbol = Ledger.transPolicyID . toLedgerPolicyID
104-
105-
-- | Convert a plutus 'CurrencySymbol' into a cardano-api 'PolicyId'.
106-
fromPlutusCurrencySymbol :: CurrencySymbol -> PolicyId
107-
fromPlutusCurrencySymbol = PolicyId . unsafeScriptHashFromBytes . fromBuiltin . unCurrencySymbol
108-
109-
-- | Convert Cardano api 'PolicyId' to Cardano ledger `PolicyID`.
110-
toLedgerPolicyID :: PolicyId -> Ledger.PolicyID StandardCrypto
111-
toLedgerPolicyID (PolicyId sh) = Ledger.PolicyID (toShelleyScriptHash sh)

hydra-chain-observer/hydra-chain-observer.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cabal-version: 2.2
22
name: hydra-chain-observer
3-
version: 0.14.0
3+
version: 0.15.0
44
synopsis: Hydra Chain Observer
55
author: IOG
66
copyright: 2023 IOG

hydra-chain-observer/src/Hydra/ChainObserver.hs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import Hydra.Prelude
77
import Hydra.Cardano.Api (
88
Block (..),
99
BlockInMode (..),
10-
CardanoEra (..),
1110
CardanoMode,
1211
ChainPoint,
1312
ChainSyncClient,
@@ -36,8 +35,7 @@ import Hydra.Chain.Direct.Tx (
3635
ContestObservation (..),
3736
FanoutObservation (..),
3837
HeadObservation (..),
39-
RawInitObservation (..),
40-
mkHeadId,
38+
InitObservation (..),
4139
observeHeadTx,
4240
)
4341
import Hydra.ChainObserver.Options (Options (..), hydraChainObserverOptions)
@@ -169,7 +167,7 @@ observeTx networkId utxo tx =
169167
let utxo' = adjustUTxO tx utxo
170168
in case observeHeadTx networkId utxo tx of
171169
NoHeadTx -> (utxo, Nothing)
172-
Init RawInitObservation{headId} -> (utxo', pure $ HeadInitTx{headId = mkHeadId headId})
170+
Init InitObservation{headId} -> (utxo', pure $ HeadInitTx{headId})
173171
Commit CommitObservation{headId} -> (utxo', pure $ HeadCommitTx{headId})
174172
CollectCom CollectComObservation{headId} -> (utxo', pure $ HeadCollectComTx{headId})
175173
Close CloseObservation{headId} -> (utxo', pure $ HeadCloseTx{headId})

0 commit comments

Comments
 (0)