Skip to content

Commit 2b6e583

Browse files
committed
Add utxoToDecommit to FanoutTx
This is needed to determine the proper hash of the outputs in the checkFanout validator.
1 parent d33cfa1 commit 2b6e583

File tree

10 files changed

+48
-25
lines changed

10 files changed

+48
-25
lines changed

hydra-node/src/Hydra/Chain.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ data PostChainTx tx
7575
}
7676
| CloseTx {headId :: HeadId, headParameters :: HeadParameters, confirmedSnapshot :: ConfirmedSnapshot tx}
7777
| ContestTx {headId :: HeadId, headParameters :: HeadParameters, confirmedSnapshot :: ConfirmedSnapshot tx}
78-
| FanoutTx {utxo :: UTxOType tx, headSeed :: HeadSeed, contestationDeadline :: UTCTime}
78+
| FanoutTx {utxo :: UTxOType tx, utxoToDecommit :: Maybe (UTxOType tx), headSeed :: HeadSeed, contestationDeadline :: UTCTime}
7979
deriving stock (Generic)
8080

8181
deriving stock instance IsTx tx => Eq (PostChainTx tx)
@@ -93,7 +93,7 @@ instance IsTx tx => Arbitrary (PostChainTx tx) where
9393
DecrementTx <$> shrink headId <*> shrink headParameters <*> shrink snapshot <*> shrink signatures
9494
CloseTx{headId, headParameters, confirmedSnapshot} -> CloseTx <$> shrink headId <*> shrink headParameters <*> shrink confirmedSnapshot
9595
ContestTx{headId, headParameters, confirmedSnapshot} -> ContestTx <$> shrink headId <*> shrink headParameters <*> shrink confirmedSnapshot
96-
FanoutTx{utxo, headSeed, contestationDeadline} -> FanoutTx <$> shrink utxo <*> shrink headSeed <*> shrink contestationDeadline
96+
FanoutTx{utxo, utxoToDecommit, headSeed, contestationDeadline} -> FanoutTx <$> shrink utxo <*> shrink utxoToDecommit <*> shrink headSeed <*> shrink contestationDeadline
9797

9898
-- | Describes transactions as seen on chain. Holds as minimal information as
9999
-- possible to simplify observing the chain.

hydra-node/src/Hydra/Chain/Direct/Handlers.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,13 +396,13 @@ prepareTxToPost timeHandle wallet ctx spendableUTxO tx =
396396
case contest ctx spendableUTxO headId contestationPeriod confirmedSnapshot upperBound of
397397
Left _ -> throwIO (FailedToConstructContestTx @Tx)
398398
Right contestTx -> pure contestTx
399-
FanoutTx{utxo, headSeed, contestationDeadline} -> do
399+
FanoutTx{utxo, utxoToDecommit, headSeed, contestationDeadline} -> do
400400
deadlineSlot <- throwLeft $ slotFromUTCTime contestationDeadline
401401
case headSeedToTxIn headSeed of
402402
Nothing ->
403403
throwIO (InvalidSeed{headSeed} :: PostTxError Tx)
404404
Just seedTxIn ->
405-
case fanout ctx spendableUTxO seedTxIn utxo deadlineSlot of
405+
case fanout ctx spendableUTxO seedTxIn utxo utxoToDecommit deadlineSlot of
406406
Left _ -> throwIO (FailedToConstructFanoutTx @Tx)
407407
Right fanoutTx -> pure fanoutTx
408408
where

hydra-node/src/Hydra/Chain/Direct/State.hs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ close ctx spendableUTxO headId HeadParameters{parties, contestationPeriod} confi
535535
{ snapshotNumber = number
536536
, closeUtxoHash = UTxOHash $ hashUTxO @Tx utxo
537537
, closeUtxoToDecommitHash =
538-
UTxOHash $ maybe (hashUTxO @Tx mempty) (hashUTxO @Tx) utxoToDecommit
538+
UTxOHash $ hashUTxO @Tx $ fromMaybe mempty utxoToDecommit
539539
, signatures
540540
}
541541

@@ -598,19 +598,21 @@ fanout ::
598598
UTxO ->
599599
-- | Seed TxIn
600600
TxIn ->
601-
-- | Snapshot UTxO to fanout
601+
-- | Snapshot UTxO to decommit to fanout
602602
UTxO ->
603+
-- | Snapshot UTxO to fanout
604+
Maybe UTxO ->
603605
-- | Contestation deadline as SlotNo, used to set lower tx validity bound.
604606
SlotNo ->
605607
Either FanoutTxError Tx
606-
fanout ctx spendableUTxO seedTxIn utxo deadlineSlotNo = do
608+
fanout ctx spendableUTxO seedTxIn utxo utxoToDecommit deadlineSlotNo = do
607609
headUTxO <-
608610
UTxO.find (isScriptTxOut headScript) (utxoOfThisHead (headPolicyId seedTxIn) spendableUTxO)
609611
?> CannotFindHeadOutputToFanout
610612

611613
closedThreadUTxO <- checkHeadDatum headUTxO
612614

613-
pure $ fanoutTx scriptRegistry utxo closedThreadUTxO deadlineSlotNo headTokenScript
615+
pure $ fanoutTx scriptRegistry utxo utxoToDecommit closedThreadUTxO deadlineSlotNo headTokenScript
614616
where
615617
headTokenScript = mkHeadTokenScript seedTxIn
616618

@@ -1084,7 +1086,8 @@ genFanoutTx numParties numOutputs = do
10841086
cctx <- pickChainContext ctx
10851087
let deadlineSlotNo = slotNoFromUTCTime systemStart slotLength (getContestationDeadline stClosed)
10861088
spendableUTxO = getKnownUTxO stClosed
1087-
pure (ctx, stClosed, unsafeFanout cctx spendableUTxO seedTxIn toFanout deadlineSlotNo)
1089+
-- TODO: generate UTxO to decommit here too
1090+
pure (ctx, stClosed, unsafeFanout cctx spendableUTxO seedTxIn toFanout Nothing deadlineSlotNo)
10881091

10891092
getContestationDeadline :: ClosedState -> UTCTime
10901093
getContestationDeadline
@@ -1224,11 +1227,13 @@ unsafeFanout ::
12241227
TxIn ->
12251228
-- | Snapshot UTxO to fanout
12261229
UTxO ->
1230+
-- | Snapshot decommit UTxO to fanout
1231+
Maybe UTxO ->
12271232
-- | Contestation deadline as SlotNo, used to set lower tx validity bound.
12281233
SlotNo ->
12291234
Tx
1230-
unsafeFanout ctx spendableUTxO seedTxIn utxo deadlineSlotNo =
1231-
either (error . show) id $ fanout ctx spendableUTxO seedTxIn utxo deadlineSlotNo
1235+
unsafeFanout ctx spendableUTxO seedTxIn utxo utxoToDecommit deadlineSlotNo =
1236+
either (error . show) id $ fanout ctx spendableUTxO seedTxIn utxo utxoToDecommit deadlineSlotNo
12321237

12331238
unsafeObserveInit ::
12341239
HasCallStack =>

hydra-node/src/Hydra/Chain/Direct/Tx.hs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,7 @@ contestTx scriptRegistry vk Snapshot{number, utxo, utxoToDecommit} sig (slotNo,
667667
}
668668
utxoHash = toBuiltin $ hashUTxO @Tx utxo
669669

670-
utxoToDecommitHash = toBuiltin $ hashUTxO @Tx (fromMaybe mempty utxoToDecommit)
670+
utxoToDecommitHash = toBuiltin $ hashUTxO @Tx $ fromMaybe mempty utxoToDecommit
671671

672672
data FanoutTxError
673673
= CannotFindHeadOutputToFanout
@@ -684,19 +684,21 @@ fanoutTx ::
684684
ScriptRegistry ->
685685
-- | Snapshotted UTxO to fanout on layer 1
686686
UTxO ->
687+
-- | Snapshotted decommit UTxO to fanout on layer 1
688+
Maybe UTxO ->
687689
-- | Everything needed to spend the Head state-machine output.
688690
(TxIn, TxOut CtxUTxO) ->
689691
-- | Contestation deadline as SlotNo, used to set lower tx validity bound.
690692
SlotNo ->
691693
-- | Minting Policy script, made from initial seed
692694
PlutusScript ->
693695
Tx
694-
fanoutTx scriptRegistry utxo (headInput, headOutput) deadlineSlotNo headTokenScript =
696+
fanoutTx scriptRegistry utxo utxoToDecommit (headInput, headOutput) deadlineSlotNo headTokenScript =
695697
unsafeBuildTransaction $
696698
emptyTxBody
697699
& addInputs [(headInput, headWitness)]
698700
& addReferenceInputs [headScriptRef]
699-
& addOutputs orderedTxOutsToFanout
701+
& addOutputs orderedTxOutsToFanout -- <> orderedTxOutsToDecommit)
700702
& burnTokens headTokenScript Burn headTokens
701703
& setValidityLowerBound (deadlineSlotNo + 1)
702704
& setTxMetadata (TxMetadataInEra $ mkHydraHeadV1TxName "FanoutTx")
@@ -710,14 +712,23 @@ fanoutTx scriptRegistry utxo (headInput, headOutput) deadlineSlotNo headTokenScr
710712
headScript =
711713
fromPlutusScript @PlutusScriptV2 Head.validatorScript
712714
headRedeemer =
713-
toScriptData (Head.Fanout $ fromIntegral $ length utxo)
715+
toScriptData $
716+
Head.Fanout
717+
{ numberOfFanoutOutputs = fromIntegral $ length utxo
718+
, numberOfDecommitOutputs = fromIntegral $ maybe 0 length utxoToDecommit
719+
}
714720

715721
headTokens =
716722
headTokensFromValue headTokenScript (txOutValue headOutput)
717723

718724
orderedTxOutsToFanout =
719725
toTxContext <$> toList utxo
720726

727+
orderedTxOutsToDecommit =
728+
case utxoToDecommit of
729+
Nothing -> []
730+
Just decommitUTxO -> toTxContext <$> toList decommitUTxO
731+
721732
data AbortTxError
722733
= OverlappingInputs
723734
| CannotFindHeadOutputToAbort

hydra-node/src/Hydra/HeadLogic.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -835,9 +835,9 @@ onClosedClientFanout ::
835835
ClosedState tx ->
836836
Outcome tx
837837
onClosedClientFanout closedState =
838-
cause OnChainEffect{postChainTx = FanoutTx{utxo, headSeed, contestationDeadline}}
838+
cause OnChainEffect{postChainTx = FanoutTx{utxo, utxoToDecommit, headSeed, contestationDeadline}}
839839
where
840-
Snapshot{utxo} = getSnapshot confirmedSnapshot
840+
Snapshot{utxo, utxoToDecommit} = getSnapshot confirmedSnapshot
841841

842842
ClosedState{headSeed, confirmedSnapshot, contestationDeadline} = closedState
843843

hydra-node/test/Hydra/Chain/Direct/Contract/FanOut.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ healthyFanoutTx =
4343
fanoutTx
4444
scriptRegistry
4545
healthyFanoutUTxO
46+
-- TODO: add something to decommit here
47+
Nothing
4648
(headInput, headOutput)
4749
healthySlotNo
4850
headTokenScript

hydra-node/test/Hydra/Chain/Direct/StateSpec.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ prop_canCloseFanoutEveryCollect = monadicST $ do
445445
_ -> fail "not observed close"
446446
-- Fanout
447447
let fanoutUTxO = getKnownUTxO stClosed
448-
let txFanout = unsafeFanout cctx fanoutUTxO seedTxIn initialUTxO (slotNoFromUTCTime systemStart slotLength deadline)
448+
let txFanout = unsafeFanout cctx fanoutUTxO seedTxIn initialUTxO Nothing (slotNoFromUTCTime systemStart slotLength deadline)
449449

450450
-- Properties
451451
let collectFails =

hydra-node/test/Hydra/Chain/Direct/TxTraceSpec.hs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -562,12 +562,14 @@ newContestTx actor snapshot = do
562562
newFanoutTx :: Actor -> ModelSnapshot -> AppM (Either FanoutTxError Tx)
563563
newFanoutTx actor snapshot = do
564564
spendableUTxO <- get
565+
let (snapshot', _) = signedSnapshot snapshot
565566
pure $
566567
fanout
567568
(actorChainContext actor)
568569
spendableUTxO
569570
Fixture.testSeedInput
570-
(snapshotUTxO snapshot)
571+
(utxo snapshot')
572+
(utxoToDecommit snapshot')
571573
deadline
572574
where
573575
CP.UnsafeContestationPeriod contestationPeriod = Fixture.cperiod

hydra-plutus/src/Hydra/Contract/Head.hs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ headValidator oldState input ctx =
7979
checkClose ctx parties initialUtxoHash signature contestationPeriod headId snapshotNumber
8080
(Closed{parties, snapshotNumber = closedSnapshotNumber, contestationDeadline, contestationPeriod, headId, contesters}, Contest{signature}) ->
8181
checkContest ctx contestationDeadline contestationPeriod parties closedSnapshotNumber signature contesters headId
82-
(Closed{parties, utxoHash, contestationDeadline, headId}, Fanout{numberOfFanoutOutputs}) ->
83-
checkFanout utxoHash contestationDeadline numberOfFanoutOutputs ctx headId parties
82+
(Closed{parties, utxoHash, utxoToDecommitHash, contestationDeadline, headId}, Fanout{numberOfFanoutOutputs, numberOfDecommitOutputs}) ->
83+
checkFanout utxoHash utxoToDecommitHash contestationDeadline numberOfFanoutOutputs numberOfDecommitOutputs ctx headId parties
8484
_ ->
8585
traceError $(errorCode InvalidHeadStateTransition)
8686

@@ -483,14 +483,16 @@ checkContest ctx contestationDeadline contestationPeriod parties closedSnapshotN
483483
{-# INLINEABLE checkContest #-}
484484

485485
checkFanout ::
486+
BuiltinByteString ->
486487
BuiltinByteString ->
487488
POSIXTime ->
488489
Integer ->
490+
Integer ->
489491
ScriptContext ->
490492
CurrencySymbol ->
491493
[Party] ->
492494
Bool
493-
checkFanout utxoHash contestationDeadline numberOfFanoutOutputs ScriptContext{scriptContextTxInfo = txInfo} currencySymbol parties =
495+
checkFanout utxoHash utxoToDecommitHash contestationDeadline numberOfFanoutOutputs numberOfDecommitOutputs ScriptContext{scriptContextTxInfo = txInfo} currencySymbol parties =
494496
mustBurnAllHeadTokens minted currencySymbol parties
495497
&& hasSameUTxOHash
496498
&& afterContestationDeadline
@@ -499,10 +501,11 @@ checkFanout utxoHash contestationDeadline numberOfFanoutOutputs ScriptContext{sc
499501

500502
hasSameUTxOHash =
501503
traceIfFalse $(errorCode FannedOutUtxoHashNotEqualToClosedUtxoHash) $
502-
fannedOutUtxoHash == utxoHash
503-
504+
fannedOutUtxoHash == utxoHash -- && decommitUtxoHash == utxoToDecommitHash
504505
fannedOutUtxoHash = hashTxOuts $ take numberOfFanoutOutputs txInfoOutputs
505506

507+
decommitUtxoHash = hashTxOuts $ take numberOfDecommitOutputs $ drop numberOfFanoutOutputs txInfoOutputs
508+
506509
TxInfo{txInfoOutputs} = txInfo
507510

508511
afterContestationDeadline =

hydra-plutus/src/Hydra/Contract/HeadState.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ data Input
6464
{ signature :: [Signature]
6565
}
6666
| Abort
67-
| Fanout {numberOfFanoutOutputs :: Integer}
67+
| Fanout {numberOfFanoutOutputs :: Integer, numberOfDecommitOutputs :: Integer}
6868
deriving stock (Generic, Show)
6969

7070
PlutusTx.unstableMakeIsData ''Input

0 commit comments

Comments
 (0)