Skip to content

Commit f59814e

Browse files
committed
[#328] [stbx-protocol] implement transition firing
1 parent 2cb42f5 commit f59814e

File tree

3 files changed

+94
-26
lines changed

3 files changed

+94
-26
lines changed

stbx-protocol/src/Statebox/Protocol.purs

+51-23
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
module Statebox.Protocol where
22

33
import Prelude
4-
import Data.Either (Either(..))
4+
import Data.Either (Either(..), either)
55
import Data.Either.Nested (type (\/))
66
import Data.Lens ((^?))
77
import Data.Maybe (Maybe(..), maybe)
88

9+
import Data.Petrinet.Representation.Marking (emptyMarking)
910
import Statebox.Core.Lenses (_firingExecution)
10-
1111
import Statebox.Core.Transaction (FiringTx, HashStr, HashTx, InitialTx, TxId, TxSum(..), WiringTx, evalTxSum, isInitialTx, isUberRootHash)
12-
-- import Statebox.Protocol.Fire (fire)
12+
import Statebox.Protocol.Fire (fire)
1313
import Statebox.Protocol.Store (getTransaction, putTransaction, getExecutionState, updateExecutionState) as Store
1414
import Statebox.Protocol.Store (StoreActions)
1515

@@ -20,25 +20,37 @@ data ProcessError
2020
= NoUberRoot
2121

2222
-- | The previous transaction of a root (initial) transaction should be an über-root.
23-
| InitialPreviousShouldBeUberRoot TxId
23+
| InitialPreviousShouldBeUberRoot TxId
2424

2525
-- | The previous transaction of a `Wiring` transaction should be a root (initial) transaction.
26-
| WiringPreviousShouldBeInitial TxId
26+
| WiringPreviousShouldBeInitial TxId
2727

2828
-- | If an execution already exists, we cannot store it again.
29-
| FiringInitialShouldBeCreatedOnlyOnce TxId
29+
| FiringInitialShouldBeCreatedOnlyOnce TxId
3030

3131
-- | The previous transaction of an initial transaction ('execution transaction') should exist.
32-
| FiringInitialShouldHavePrevious TxId
32+
| FiringInitialShouldHavePrevious TxId
3333

3434
-- | The previous transaction of an initial transaction ('execution transaction') should be a `Wiring`.
35-
| FiringInitialPreviousShouldBeWiring TxId
35+
| FiringInitialPreviousShouldBeWiring TxId
36+
37+
-- | The first transition fired should be initial.
38+
| FiringInitialTransitionShouldBeInitial TxId
3639

3740
-- | A normal firing should refer to an existing execution.
38-
| FiringNormalShouldHaveExistingExecution TxId ExecutionId
41+
| FiringNormalShouldHaveExistingExecution TxId ExecutionId
3942

4043
-- | The previous transaction of a normal firing should match the current execution state.
41-
| FiringNormalPreviousShouldMatchCurrentState TxId ExecutionId
44+
| FiringNormalPreviousShouldMatchCurrentState TxId ExecutionId
45+
46+
-- | The execution of a firing should refer to an existing wiring.
47+
| FiringNormalExecutionShouldPointToExistingWiring TxId ExecutionId
48+
49+
-- | The wiring of the execution of a normal firing should be a `Wiring`.
50+
| FiringNormalExecutionWiringShouldBeAWiring TxId ExecutionId
51+
52+
-- | The fired transition should be enabled.
53+
| FiringNormalTransitionShouldBeEnabled TxId ExecutionId
4254

4355
processTxSum :: HashTx -> StoreActions (ProcessError \/ Unit)
4456
processTxSum hashTx = case hashTx.tx of
@@ -95,16 +107,19 @@ processInitialFiringTx hash firingTx = do
95107
-- previous not found
96108
Nothing -> pure $ Left $ FiringInitialShouldHavePrevious hash
97109
-- previous found
98-
Just previous -> do
110+
Just previous ->
99111
evalTxSum
100112
(const $ pure $ Left $ FiringInitialPreviousShouldBeWiring hash)
101113
(const $ pure $ Left $ FiringInitialPreviousShouldBeWiring hash)
102-
(\wiringTx -> map Right $ do
103-
-- let firedTransition = fire firingTx
104-
Store.putTransaction hash $ FiringTxInj firingTx
105-
Store.updateExecutionState hash $ { lastFiring: hash
106-
, wiring: firingTx.previous
107-
}
114+
(\wiringTx -> either
115+
(const $ pure $ Left $ FiringInitialTransitionShouldBeInitial hash)
116+
(\newMarking -> map Right $ do
117+
Store.putTransaction hash $ FiringTxInj firingTx
118+
Store.updateExecutionState hash $ { lastFiring: hash
119+
, wiring: firingTx.previous
120+
, marking: newMarking
121+
})
122+
(fire wiringTx.wiring firingTx.firing emptyMarking)
108123
)
109124
(const $ pure $ Left $ FiringInitialPreviousShouldBeWiring hash)
110125
previous
@@ -119,10 +134,23 @@ processNormalFiringTx hash firingTx executionHash = do
119134
Just execution -> do
120135
-- check if the previous transaction corresponds to the current state of the execution
121136
if firingTx.previous == execution.lastFiring
122-
then map Right $ do
123-
-- fire transition
124-
Store.putTransaction hash $ FiringTxInj firingTx
125-
Store.updateExecutionState executionHash { lastFiring: hash
126-
, wiring: execution.wiring
127-
}
137+
then do
138+
maybeWiring <- Store.getTransaction execution.wiring
139+
case maybeWiring of
140+
Nothing -> pure $ Left $ FiringNormalExecutionShouldPointToExistingWiring hash executionHash
141+
Just transaction ->
142+
evalTxSum
143+
(const $ pure $ Left $ FiringNormalExecutionWiringShouldBeAWiring hash executionHash)
144+
(const $ pure $ Left $ FiringNormalExecutionWiringShouldBeAWiring hash executionHash)
145+
(\wiringTx -> either
146+
(const $ pure $ Left $ FiringNormalTransitionShouldBeEnabled hash executionHash)
147+
(\newMarking -> map Right $ do
148+
Store.putTransaction hash $ FiringTxInj firingTx
149+
Store.updateExecutionState executionHash { lastFiring: hash
150+
, wiring: execution.wiring
151+
, marking: newMarking
152+
})
153+
(fire wiringTx.wiring firingTx.firing execution.marking))
154+
(const $ pure $ Left $ FiringNormalExecutionWiringShouldBeAWiring hash executionHash)
155+
transaction
128156
else pure $ Left $ FiringNormalPreviousShouldMatchCurrentState hash executionHash
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
module Statebox.Protocol.ExecutionState where
22

33
import Statebox.Core.Transaction (TxId)
4+
import View.Petrinet.Model (Marking)
45

56
type ExecutionState =
67
{ lastFiring :: TxId
78
, wiring :: TxId
9+
, marking :: Marking
810
}
+41-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,44 @@
11
module Statebox.Protocol.Fire where
22

3-
import Statebox.Core.Transaction (FiringTx)
3+
import Prelude
4+
import Data.Array (index)
5+
import Data.Either (Either(..), either)
6+
import Data.Either.Nested (type (\/))
7+
import Data.Maybe (maybe)
8+
import Data.NonEmpty (head)
49

5-
-- fire :: ∀ a . FiringTx -> a
6-
-- fire = ?fire
10+
import Data.Petrinet.Representation.Dict (fireAtMarking)
11+
import Statebox.Core.Transition (gluedTokens)
12+
import Statebox.Core.Types (Firing, Wiring)
13+
import Statebox.Core.WiringTree (LinearizationError, fromWiring, linearize)
14+
import View.Petrinet.Model (Marking)
15+
16+
data FiringError
17+
18+
-- | The wiring does not describe a valid wiring tree.
19+
= FireInvalidWiringTree
20+
21+
-- | The linerization of the wiring tree failed with a LinerizationError
22+
| FireLinerizationError LinearizationError
23+
24+
-- | The path of the firing describing
25+
| FireTransitionIndexOutOfBounds
26+
27+
-- | The selected transition is not enabled
28+
| FireTransitionNotEnabled
29+
30+
fire :: Wiring -> Firing -> Marking -> FiringError \/ Marking
31+
fire wiring firing marking = maybe
32+
(Left FireInvalidWiringTree)
33+
(\wiringTree ->
34+
either
35+
(Left <<< FireLinerizationError)
36+
(\gluedTransitions ->
37+
let transitionIndex = head firing.path
38+
in maybe
39+
(Left FireTransitionIndexOutOfBounds)
40+
(\gluedTransition ->
41+
Right $ fireAtMarking marking $ gluedTokens gluedTransition)
42+
(index gluedTransitions transitionIndex))
43+
(linearize wiringTree))
44+
(fromWiring wiring)

0 commit comments

Comments
 (0)