-
Notifications
You must be signed in to change notification settings - Fork 87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Spike: Event sourced persistence #963
Conversation
Transactions CostsSizes and execution budgets for Hydra protocol transactions. Note that unlisted parameters are currently using
Script summary
Cost of Init Transaction
Cost of Commit TransactionThis is using ada-only outputs for better comparability.
Cost of CollectCom Transaction
Cost of Close Transaction
Cost of Contest Transaction
Cost of Abort TransactionSome variation because of random mixture of still initial and already committed outputs.
Cost of FanOut TransactionInvolves spending head output and burning head tokens. Uses ada-only UTxO for better comparability.
|
93635b6
to
7ee7ab0
Compare
b940daf
to
1fc3704
Compare
abbbc82
to
a0d5f74
Compare
loadAll persistence >>= \case | ||
[] -> do | ||
traceWith tracer CreatedState | ||
pure $ Idle IdleState{chainState = initialChainState} | ||
Just headState -> do | ||
events -> do | ||
traceWith tracer LoadedState | ||
let paramsMismatch = checkParamsAgainstExistingState headState env | ||
let | ||
initialState = Idle IdleState{chainState = initialChainState} | ||
headState = foldl' updateHeadState initialState events | ||
paramsMismatch = checkParamsAgainstExistingState headState env |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should move to Node.hs
) | ||
|
||
-- save altered node state | ||
let alice = deriveParty hydraSKey |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could re-write this test:
- Start the node with one configuration and persistency
- Initialize a head
- Start the node with a different configuration and same persistency
…ead state This is in order to delay the computation to the next state after persisting the produced events. Also removed headId from most events types as it is not necessary. Derive instances for HeadStateEvent. Added RolledBack HeadStateEvent. Now the update function produces a list of events for the node to process.
…d persist all HeadStateEvents incrementally.
It needs the next head state in order to produce the SnapshotEmited event.
As it was depending on altering the persisted state to trigger the error. Now we need to generate a list of events that leads to some invalid state, that we can run with miss-matching configuration.
> Add track tx and untrack tx head state events.
- Remove previous from ChainStateAt - Rollback now requires to load all persisted events, in order to know from which chain state it should continue processing - Persisted events remain untouched
…rocess - add new Event 'OffChainEvent' + this will carry the event 'EmitSn' - add new Effect 'OffChainEffect' to 'HeadLogic' + this will carry the action 'ReqEmitSn' - update 'onOpenNetworkReqTx' and 'onOpenNetworkAckSn' to publish 'OffChainEffect RqEmitSn' on success. - update the 'Node.processEffect' function to handle the new effect and put the 'EmitSn' into the queue for it to be processed. - add matching to 'HeadLogic.update' function to publish 'SnapshotEmited', when in 'OpenState', we receive an 'EmitSn' action.
- Added new prependEvent handler to EventQueue. - This is used by the Node, when handling OffChainEffect, to EmitSn. - This allows EmitSn to be process immediately. - For that we needed to update the event ids of the rest of the enqueued events for succ.
- Ignore invalid events instead of throwing an error - Simplify AckSnConfirmed head state event
- This removes the dependency on HeadLogic in the Chain module.
a0d5f74
to
84dd48f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rollback tv point events = do | ||
let maybeChainState = | ||
events | ||
& find | ||
( \ChainStateAt{recordedAt} -> | ||
case recordedAt of | ||
Just recordPoint | recordPoint <= point -> True | ||
_ -> False | ||
) | ||
-- TODO: using the same as defined in Direct module due to cyclic dependnecy. | ||
let initialChainState = ChainStateAt{chainState = Idle, recordedAt = Nothing} | ||
let rolledBack = fromMaybe initialChainState maybeChainState | ||
-- REVIEW: what should we do with persisted events? prune? replace? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would rather keep the previous state in memory and not explore the file content to do the rollback.
} | ||
(_, RolledBack{rolledBackChainState}) -> | ||
setChainState rolledBackChainState st | ||
_ -> st |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function should be complete: an event should always be applicable. The decision to do something or not has already been taken in the other update
function and now it's just about applying an event which already happened and can not be wrong.
@@ -368,7 +387,7 @@ instance Arbitrary (TxIdType tx) => Arbitrary (RequirementFailure tx) where | |||
data Outcome tx | |||
= NoOutcome | |||
| Effects {effects :: [Effect tx]} | |||
| NewState {headState :: HeadState tx} | |||
| NewState {events :: [HeadStateEvent tx]} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This type should only carry one event. If we really need several events, we can still Combined
stuff.
We should name it differently also.
SeenSnapshot tx -> | ||
Outcome tx | ||
emitSnapshot env params chs seenSnapshot = | ||
case newSn env params chs of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We must challenge this function newSn
because it's using an already update state and this has some nasty implications.
Also note that it means we would need to update the spec maybe.
@@ -382,6 +401,214 @@ deriving instance (IsTx tx, IsChainState tx) => FromJSON (Outcome tx) | |||
instance (IsTx tx, Arbitrary (ChainStateType tx)) => Arbitrary (Outcome tx) where | |||
arbitrary = genericArbitrary | |||
|
|||
data HeadStateEvent tx |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we use the events returned by the update function to create the effects and stop returning them?
Fixes #913
🏖️ The head logic now produces a list of events as part of its outcome during
update
.🏖️ The node now applies a transition function to update the current state (in memory) while processing events.
🏖️ After every processed event, the node will persist it incrementally on disk.
🏖️ The node, upon start, will recover the head state from the persisted events.
🏖️ The below image summarize the transition function
updateHeadState
🐻 Proposal: Removed the previous reference from
ChainStateAt
.We are expecting to address this as part of this story.
🐯 Proposal: Re-model
emitSnapshot
as a new internal effect/event process.ReqTx
andAckSn
handling, and it carries the action ofReqEmitSn
.EmitSn
) is being produced by the Node during the new effect processing, and is expected to be handled by the HeadLogic only when inOpenState
.