@@ -29,8 +29,17 @@ import Hydra.Cardano.Api.Pretty (renderTxWithUTxO)
29
29
import Hydra.Chain.Direct.Contract.Mutation (addParticipationTokens )
30
30
import Hydra.Chain.Direct.Fixture qualified as Fixture
31
31
import Hydra.Chain.Direct.ScriptRegistry (ScriptRegistry , genScriptRegistry , registryUTxO )
32
- import Hydra.Chain.Direct.State (ChainContext (.. ), close , contest , decrement , fanout )
33
- import Hydra.Chain.Direct.Tx (FanoutTxError , HeadObservation , headIdToCurrencySymbol , mkHeadId , mkHeadOutput , observeHeadTx )
32
+ import Hydra.Chain.Direct.State (ChainContext (.. ), DecrementTxError , close , contest , decrement , fanout )
33
+ import Hydra.Chain.Direct.Tx (
34
+ CloseTxError ,
35
+ ContestTxError ,
36
+ FanoutTxError ,
37
+ HeadObservation (NoHeadTx ),
38
+ headIdToCurrencySymbol ,
39
+ mkHeadId ,
40
+ mkHeadOutput ,
41
+ observeHeadTx ,
42
+ )
34
43
import Hydra.Chain.Direct.Tx qualified as Tx
35
44
import Hydra.ContestationPeriod qualified as CP
36
45
import Hydra.Contract.HeadState qualified as Head
@@ -183,8 +192,11 @@ data State
183
192
data Actor = Alice | Bob | Carol
184
193
deriving (Show , Eq )
185
194
195
+ -- | Result of constructing and performing a transaction. Notably there are
196
+ -- three stages to this which can fail: construction, validation, and
197
+ -- observation. Results from all stages are needed to express post-conditions.
186
198
data TxResult = TxResult
187
- { tx :: Either String Tx
199
+ { constructedTx :: Either String Tx
188
200
, validationError :: Maybe String
189
201
, observation :: HeadObservation
190
202
}
@@ -270,6 +282,8 @@ instance StateModel Model where
270
282
]
271
283
Final -> pure $ Some Stop
272
284
285
+ -- Determine actions we want to perform and expect to work. If this is False,
286
+ -- validFailingAction is checked too.
273
287
precondition :: Model -> Action Model a -> Bool
274
288
precondition Model {headState, latestSnapshot, alreadyContested, utxoInHead} = \ case
275
289
Stop -> headState /= Final
@@ -291,6 +305,9 @@ instance StateModel Model where
291
305
headState == Closed
292
306
&& snapshotUTxO snapshot == utxoInHead
293
307
308
+ -- Determine actions we want to perform and want to see failing. If this is
309
+ -- False, the action is discarded (e.g. it's invalid or we don't want to see
310
+ -- it tried to perform).
294
311
validFailingAction :: Model -> Action Model a -> Bool
295
312
validFailingAction Model {headState, latestSnapshot, alreadyContested, utxoInHead} = \ case
296
313
Decrement {snapshot} ->
@@ -377,9 +394,7 @@ instance RunModel Model AppM where
377
394
Contest {actor, snapshot} ->
378
395
performTx =<< newContestTx actor (confirmedSnapshot snapshot)
379
396
Fanout {snapshot} -> do
380
- newFanoutTx Alice snapshot >>= \ case
381
- Left err -> pure $ TxResult {tx = Left (show err), validationError = Nothing , observation = Tx. NoHeadTx }
382
- Right tx -> performTx tx
397
+ performTx =<< newFanoutTx Alice snapshot
383
398
Stop -> pure ()
384
399
385
400
postcondition (modelBefore, modelAfter) action _lookup result = runPostconditionM' $ do
@@ -399,8 +414,8 @@ instance RunModel Model AppM where
399
414
_ -> fail " Expected Contest"
400
415
Fanout {snapshot} -> do
401
416
case result of
402
- TxResult {tx = Left err} -> fail $ " Failed to construct transaction: " <> err
403
- TxResult {tx = Right tx} -> do
417
+ TxResult {constructedTx = Left err} -> fail $ " Failed to construct transaction: " <> err
418
+ TxResult {constructedTx = Right tx} -> do
404
419
-- NOTE: Sort `[TxOut]` by the address and values. We want to make
405
420
-- sure that the fanout outputs match what we had in the open Head
406
421
-- exactly.
@@ -432,20 +447,27 @@ instance RunModel Model AppM where
432
447
-- | Perform a transaction by evaluating and observing it. This updates the
433
448
-- 'UTxO' in the 'AppM' if a transaction is valid and produces a 'TxResult' that
434
449
-- can be used to assert expected success / failure.
435
- performTx :: Tx -> AppM TxResult
436
- performTx tx = do
437
- utxo <- get
438
- let validationError = getValidationError tx utxo
439
- when (isNothing validationError) $ do
440
- put $ adjustUTxO tx utxo
441
- pure
442
- TxResult
443
- { -- TODO: this is wonky since there could be validation errors but we
444
- -- set the tx as Right?
445
- tx = Right tx
446
- , validationError
447
- , observation = observeHeadTx Fixture. testNetworkId utxo tx
448
- }
450
+ performTx :: Show err => Either err Tx -> AppM TxResult
451
+ performTx = \ case
452
+ Left err ->
453
+ pure
454
+ TxResult
455
+ { constructedTx = Left $ show err
456
+ , validationError = Nothing
457
+ , observation = NoHeadTx
458
+ }
459
+ Right tx -> do
460
+ utxo <- get
461
+ let validationError = getValidationError tx utxo
462
+ when (isNothing validationError) $ do
463
+ put $ adjustUTxO tx utxo
464
+ let observation = observeHeadTx Fixture. testNetworkId utxo tx
465
+ pure
466
+ TxResult
467
+ { constructedTx = Right tx
468
+ , validationError
469
+ , observation
470
+ }
449
471
450
472
getValidationError :: Tx -> UTxO -> Maybe String
451
473
getValidationError tx utxo =
@@ -547,10 +569,10 @@ openHeadUTxO =
547
569
}
548
570
549
571
-- | Creates a decrement transaction using given utxo and given snapshot.
550
- newDecrementTx :: HasCallStack => Actor -> (Snapshot Tx , MultiSignature (Snapshot Tx )) -> AppM Tx
572
+ newDecrementTx :: Actor -> (Snapshot Tx , MultiSignature (Snapshot Tx )) -> AppM ( Either DecrementTxError Tx )
551
573
newDecrementTx actor (snapshot, signatures) = do
552
574
spendableUTxO <- get
553
- either (failure . show ) pure $
575
+ pure $
554
576
decrement
555
577
(actorChainContext actor)
556
578
(mkHeadId Fixture. testPolicyId)
@@ -563,10 +585,10 @@ newDecrementTx actor (snapshot, signatures) = do
563
585
-- NOTE: This uses fixtures for headId, parties (alice, bob, carol),
564
586
-- contestation period and also claims to close at time 0 resulting in a
565
587
-- contestation deadline of 0 + cperiod.
566
- newCloseTx :: HasCallStack => Actor -> ConfirmedSnapshot Tx -> AppM Tx
588
+ newCloseTx :: Actor -> ConfirmedSnapshot Tx -> AppM ( Either CloseTxError Tx )
567
589
newCloseTx actor snapshot = do
568
590
spendableUTxO <- get
569
- either (failure . show ) pure $
591
+ pure $
570
592
close
571
593
(actorChainContext actor)
572
594
spendableUTxO
@@ -583,10 +605,10 @@ newCloseTx actor snapshot = do
583
605
-- | Creates a contest transaction using given utxo and contesting with given
584
606
-- snapshot. NOTE: This uses fixtures for headId, contestation period and also
585
607
-- claims to contest at time 0.
586
- newContestTx :: HasCallStack => Actor -> ConfirmedSnapshot Tx -> AppM Tx
608
+ newContestTx :: Actor -> ConfirmedSnapshot Tx -> AppM ( Either ContestTxError Tx )
587
609
newContestTx actor snapshot = do
588
610
spendableUTxO <- get
589
- either (failure . show ) pure $
611
+ pure $
590
612
contest
591
613
(actorChainContext actor)
592
614
spendableUTxO
0 commit comments