@@ -17,7 +17,7 @@ import Hydra.Contract.Commit (Commit (..))
17
17
import Hydra.Contract.Commit qualified as Commit
18
18
import Hydra.Contract.HeadError (HeadError (.. ), errorCode )
19
19
import Hydra.Contract.HeadState (Input (.. ), Signature , SnapshotNumber , State (.. ))
20
- import Hydra.Contract.Util (hasST , mustNotMintOrBurn , (===) )
20
+ import Hydra.Contract.Util (hasST , mustBurnAllHeadTokens , mustNotMintOrBurn , (===) )
21
21
import Hydra.Data.ContestationPeriod (ContestationPeriod , addContestationPeriod , milliseconds )
22
22
import Hydra.Data.Party (Party (vkey ))
23
23
import Hydra.Plutus.Extras (ValidatorType , scriptValidatorHash , wrapValidator )
@@ -44,7 +44,7 @@ import PlutusLedgerApi.V2 (
44
44
TxOut (.. ),
45
45
TxOutRef (.. ),
46
46
UpperBound (.. ),
47
- Value (Value , getValue ),
47
+ Value (Value ),
48
48
adaSymbol ,
49
49
adaToken ,
50
50
)
@@ -77,8 +77,8 @@ headValidator oldState input ctx =
77
77
checkClose ctx parties initialUtxoHash signature contestationPeriod headId
78
78
(Closed {parties, snapshotNumber = closedSnapshotNumber, contestationDeadline, contestationPeriod, headId, contesters}, Contest {signature}) ->
79
79
checkContest ctx contestationDeadline contestationPeriod parties closedSnapshotNumber signature contesters headId
80
- (Closed {utxoHash, contestationDeadline}, Fanout {numberOfFanoutOutputs}) ->
81
- checkFanout utxoHash contestationDeadline numberOfFanoutOutputs ctx
80
+ (Closed {parties, utxoHash, contestationDeadline, headId }, Fanout {numberOfFanoutOutputs}) ->
81
+ checkFanout utxoHash contestationDeadline numberOfFanoutOutputs ctx headId parties
82
82
_ ->
83
83
traceError $ (errorCode InvalidHeadStateTransition )
84
84
@@ -96,20 +96,11 @@ checkAbort ::
96
96
[Party ] ->
97
97
Bool
98
98
checkAbort ctx@ ScriptContext {scriptContextTxInfo = txInfo} headCurrencySymbol parties =
99
- mustBurnAllHeadTokens
99
+ mustBurnAllHeadTokens minted headCurrencySymbol parties
100
100
&& mustBeSignedByParticipant ctx headCurrencySymbol
101
101
&& mustReimburseCommittedUTxO
102
102
where
103
- mustBurnAllHeadTokens =
104
- traceIfFalse $ (errorCode BurntTokenNumberMismatch ) $
105
- burntTokens == length parties + 1
106
-
107
- minted = getValue $ txInfoMint txInfo
108
-
109
- burntTokens =
110
- case AssocMap. lookup headCurrencySymbol minted of
111
- Nothing -> 0
112
- Just tokenMap -> negate $ sum tokenMap
103
+ minted = txInfoMint txInfo
113
104
114
105
mustReimburseCommittedUTxO =
115
106
traceIfFalse $ (errorCode ReimbursedOutputsDontMatch ) $
@@ -451,10 +442,16 @@ checkFanout ::
451
442
POSIXTime ->
452
443
Integer ->
453
444
ScriptContext ->
445
+ CurrencySymbol ->
446
+ [Party ] ->
454
447
Bool
455
- checkFanout utxoHash contestationDeadline numberOfFanoutOutputs ScriptContext {scriptContextTxInfo = txInfo} =
456
- hasSameUTxOHash && afterContestationDeadline
448
+ checkFanout utxoHash contestationDeadline numberOfFanoutOutputs ScriptContext {scriptContextTxInfo = txInfo} currencySymbol parties =
449
+ mustBurnAllHeadTokens minted currencySymbol parties
450
+ && hasSameUTxOHash
451
+ && afterContestationDeadline
457
452
where
453
+ minted = txInfoMint txInfo
454
+
458
455
hasSameUTxOHash =
459
456
traceIfFalse $ (errorCode FannedOutUtxoHashNotEqualToClosedUtxoHash ) $
460
457
fannedOutUtxoHash == utxoHash
@@ -556,6 +553,8 @@ getTxOutDatum o =
556
553
557
554
-- | Hash a potentially unordered list of commits by sorting them, concatenating
558
555
-- their 'preSerializedOutput' bytes and creating a SHA2_256 digest over that.
556
+ --
557
+ -- NOTE: See note from `hashTxOuts`.
559
558
hashPreSerializedCommits :: [Commit ] -> BuiltinByteString
560
559
hashPreSerializedCommits commits =
561
560
sha2_256 . foldMap preSerializedOutput $
@@ -565,6 +564,13 @@ hashPreSerializedCommits commits =
565
564
-- | Hash a pre-ordered list of transaction outputs by serializing each
566
565
-- individual 'TxOut', concatenating all bytes together and creating a SHA2_256
567
566
-- digest over that.
567
+ --
568
+ -- NOTE: In general, from asserting that `hash(x || y) = hash (x' || y')` it is
569
+ -- not safe to conclude that `(x,y) = (x', y')` as the same hash could be
570
+ -- obtained by moving one or more bytes from the end of `x` to the beginning of
571
+ -- `y`, but in the context of Hydra validators it seems impossible to exploit
572
+ -- this property without breaking other logic or verification (eg. producing a
573
+ -- valid and meaningful `TxOut`).
568
574
hashTxOuts :: [TxOut ] -> BuiltinByteString
569
575
hashTxOuts =
570
576
sha2_256 . foldMap (Builtins. serialiseData . toBuiltinData)
0 commit comments