Skip to content

Commit

Permalink
Check commits are spending from vInitial in observeCommitTx
Browse files Browse the repository at this point in the history
This ensures that the commit tx is part of the Head protocol (because
the validators must have ran).
  • Loading branch information
ch1bo committed Nov 10, 2023
1 parent 09bdcd0 commit e92dedf
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 10 deletions.
3 changes: 2 additions & 1 deletion hydra-node/src/Hydra/Chain/Direct/State.hs
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,8 @@ observeCommit ::
Tx ->
Maybe (OnChainTx Tx, InitialState)
observeCommit ctx st tx = do
observation <- observeCommitTx networkId tx
let utxo = getKnownUTxO st
observation <- observeCommitTx networkId utxo tx
let CommitObservation{commitOutput, party, committed} = observation
let event = OnCommitTx{party, committed}
let st' =
Expand Down
28 changes: 21 additions & 7 deletions hydra-node/src/Hydra/Chain/Direct/Tx.hs
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,7 @@ observeHeadTx networkId utxo tx =
fromMaybe NoHeadTx $
either (const Nothing) (Just . Init) (observeRawInitTx networkId tx)
<|> Abort <$> observeAbortTx utxo tx
<|> Commit <$> observeCommitTx networkId tx
<|> Commit <$> observeCommitTx networkId utxo tx
<|> CollectCom <$> observeCollectComTx utxo tx
<|> Close <$> observeCloseTx utxo tx
<|> Contest <$> observeContestTx utxo tx
Expand Down Expand Up @@ -851,22 +851,27 @@ observeInitTx cardanoKeys expectedCP party otherParties rawTx = do
data CommitObservation = CommitObservation
{ commitOutput :: UTxOWithScript
, party :: Party
-- ^ Hydra participant who committed the UTxO.
, committed :: UTxO
, headId :: HeadId
}

-- | Identify a commit tx by:
--
-- - Check that its spending from the init validator,
-- - Find the outputs which pays to the commit validator,
-- - Using the datum of that output, deserialize the committed output,
-- - Reconstruct the committed UTxO from both values (tx input and output).
-- - TODO: Need to ensure this is a head protocol transaction.
observeCommitTx ::
NetworkId ->
-- | A UTxO set to lookup tx inputs. Should at least contain the input
-- spending from νInitial.
UTxO ->
Tx ->
Maybe CommitObservation
observeCommitTx networkId tx = do
-- FIXME: Strategy to observe without looking at resolved inputs (utxo):
observeCommitTx networkId utxo tx = do
-- FIXME: Instead checking to spend from initial we could be looking at the
-- seed:
--
-- - We must check that participation token in output satisfies
-- policyId = hash(mu_head(seed))
Expand All @@ -880,6 +885,9 @@ observeCommitTx networkId tx = do
--
-- Right now we only have the headId in the datum, so we use that in place of
-- the seed -> THIS CAN NOT BE TRUSTED.

guard isSpendingFromInitial

(commitIn, commitOut) <- findTxOutByAddress commitAddress tx
dat <- txOutScriptData commitOut
(onChainParty, onChainCommits, headId) :: Commit.DatumType <- fromScriptData dat
Expand All @@ -889,9 +897,6 @@ observeCommitTx networkId tx = do
-- the commit into the datum (+ changing the hashing strategy of
-- collect/fanout)
committed <- do
-- TODO: We could simplify this by just using the datum. However, we would
-- need to ensure the commit is belonging to a head / is rightful. By just
-- looking for some known initials we achieve this (a bit complicated) now.
committedUTxO <- traverse (Commit.deserializeCommit (networkIdToNetwork networkId)) onChainCommits
pure . UTxO.fromPairs $ committedUTxO

Expand All @@ -903,6 +908,15 @@ observeCommitTx networkId tx = do
, headId = mkHeadId $ fromPlutusCurrencySymbol headId
}
where
isSpendingFromInitial :: Bool
isSpendingFromInitial = do
let resolvedInputs = mapMaybe (`UTxO.resolve` utxo) $ txIns' tx
any (\o -> txOutAddress o == initialAddress) resolvedInputs

initialAddress = mkScriptAddress @PlutusScriptV2 networkId initialScript

initialScript = fromPlutusScript Initial.validatorScript

commitAddress = mkScriptAddress @PlutusScriptV2 networkId commitScript

commitScript = fromPlutusScript Commit.validatorScript
Expand Down
4 changes: 2 additions & 2 deletions hydra-node/test/Hydra/Chain/Direct/StateSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ spec = parallel $ do
mutation <- pick $ genCommitTxMutation utxo tx
let (tx', utxo') = applyMutation mutation (tx, utxo)

originalIsObserved = property $ isJust $ observeCommitTx testNetworkId tx
originalIsObserved = property $ isJust $ observeCommitTx testNetworkId utxo tx

-- We expected mutated transaction to still be valid, but not observed.
mutatedIsValid =
Expand All @@ -227,7 +227,7 @@ spec = parallel $ do
| otherwise -> property False & counterexample (show ok)

mutatedIsNotObserved =
isNothing $ observeCommitTx testNetworkId tx'
isNothing $ observeCommitTx testNetworkId utxo' tx'

pure $
conjoin
Expand Down

0 comments on commit e92dedf

Please sign in to comment.