Skip to content

Commit

Permalink
Add commitUTxO to CoordinatedHeadState and more logic on ReqSn
Browse files Browse the repository at this point in the history
Introduce waitOnApplicableCommit as well
Signed-off-by: Sasha Bogicevic <[email protected]>
  • Loading branch information
v0d1ch committed Sep 11, 2024
1 parent 37b00c5 commit 5f22c64
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 41 deletions.
138 changes: 97 additions & 41 deletions hydra-node/src/Hydra/HeadLogic.hs
Original file line number Diff line number Diff line change
Expand Up @@ -415,44 +415,45 @@ onOpenNetworkReqSn env ledger st otherParty sv sn requestedTxIds mDecommitTx mIn
waitNoSnapshotInFlight $
-- Spec: wait v = v̂
waitOnSnapshotVersion $
requireApplicableDecommitTx $ \(activeUTxO, mUtxoToDecommit) ->
-- Resolve transactions by-id
waitResolvableTxs $ \requestedTxs -> do
-- Spec: require 𝑈_active ◦ Treq ≠ ⊥
-- 𝑈 ← 𝑈_active ◦ Treq
requireApplyTxs activeUTxO requestedTxs $ \u -> do
-- Spec: ŝ ← ̅S.s + 1
-- NOTE: confSn == seenSn == sn here
let nextSnapshot =
Snapshot
{ headId
, version = version
, number = sn
, confirmed = requestedTxIds
, utxo = u
, utxoToCommit = mIncrementUTxO
, utxoToDecommit = mUtxoToDecommit
requireApplicableDecommitTx $ \(activeUTxOAfterDecommit, mUtxoToDecommit) ->
requireApplicableCommit activeUTxOAfterDecommit $ \(activeUTxO, mUtxoToCommit) ->
-- Resolve transactions by-id
waitResolvableTxs $ \requestedTxs -> do
-- Spec: require 𝑈_active ◦ Treq ≠ ⊥
-- 𝑈 ← 𝑈_active ◦ Treq
requireApplyTxs activeUTxO requestedTxs $ \u -> do
-- Spec: ŝ ← ̅S.s + 1
-- NOTE: confSn == seenSn == sn here
let nextSnapshot =
Snapshot
{ headId
, version = version
, number = sn
, confirmed = requestedTxIds
, utxo = u
, utxoToCommit = mUtxoToCommit
, utxoToDecommit = mUtxoToDecommit
}
-- Spec: η ← combine(𝑈)
-- σᵢ ← MS-Sign(kₕˢⁱᵍ, (cid‖v‖ŝ‖η‖ηω))
let snapshotSignature = sign signingKey nextSnapshot
-- Spec: multicast (ackSn, ŝ, σᵢ)
(cause (NetworkEffect $ AckSn snapshotSignature sn) <>) $ do
-- Spec: ̂Σ ← ∅
-- L̂ ← 𝑈
-- 𝑋 ← T
-- T̂ ← ∅
-- for tx ∈ 𝑋 : L̂ ◦ tx ≠ ⊥
-- T̂ ← T̂ ⋃ {tx}
-- L̂ ← L̂ ◦ tx
let (newLocalTxs, newLocalUTxO) = pruneTransactions u
newState
SnapshotRequested
{ snapshot = nextSnapshot
, requestedTxIds
, newLocalUTxO
, newLocalTxs
}
-- Spec: η ← combine(𝑈)
-- σᵢ ← MS-Sign(kₕˢⁱᵍ, (cid‖v‖ŝ‖η‖ηω))
let snapshotSignature = sign signingKey nextSnapshot
-- Spec: multicast (ackSn, ŝ, σᵢ)
(cause (NetworkEffect $ AckSn snapshotSignature sn) <>) $ do
-- Spec: ̂Σ ← ∅
-- L̂ ← 𝑈
-- 𝑋 ← T
-- T̂ ← ∅
-- for tx ∈ 𝑋 : L̂ ◦ tx ≠ ⊥
-- T̂ ← T̂ ⋃ {tx}
-- L̂ ← L̂ ◦ tx
let (newLocalTxs, newLocalUTxO) = pruneTransactions u
newState
SnapshotRequested
{ snapshot = nextSnapshot
, requestedTxIds
, newLocalUTxO
, newLocalTxs
}
where
requireReqSn continue
| sv /= version =
Expand Down Expand Up @@ -481,6 +482,19 @@ onOpenNetworkReqSn env ledger st otherParty sv sn requestedTxIds mDecommitTx mIn
[] -> continue $ mapMaybe (`Map.lookup` allTxs) requestedTxIds
unseen -> wait $ WaitOnTxs unseen

requireApplicableCommit activeUTxOAfterDecommit cont =
case mIncrementUTxO of
Nothing -> cont (activeUTxOAfterDecommit, Nothing)
Just utxo ->
if sv == confVersion && isJust confUTxOToCommit
then
if confUTxOToCommit == Just utxo
then cont (activeUTxOAfterDecommit, confUTxOToCommit)
else Error $ RequireFailed ReqSnCommitNotSettled
else do
let activeUTxOAfterCommit = activeUTxOAfterDecommit <> utxo
cont (activeUTxOAfterCommit, Just utxo)

requireApplicableDecommitTx cont =
case mDecommitTx of
Nothing -> cont (confirmedUTxO, Nothing)
Expand Down Expand Up @@ -540,6 +554,10 @@ onOpenNetworkReqSn env ledger st otherParty sv sn requestedTxIds mDecommitTx mIn

Snapshot{version = confVersion} = getSnapshot confirmedSnapshot

confUTxOToCommit = case confirmedSnapshot of
InitialSnapshot{} -> Nothing
ConfirmedSnapshot{snapshot = Snapshot{utxoToCommit}} -> utxoToCommit

confUTxOToDecommit = case confirmedSnapshot of
InitialSnapshot{} -> Nothing
ConfirmedSnapshot{snapshot = Snapshot{utxoToDecommit}} -> utxoToDecommit
Expand Down Expand Up @@ -858,10 +876,21 @@ onOpenChainDepositTx ::
Outcome tx
onOpenChainDepositTx env st utxo =
waitOnUnresolvedDecommit $
if not snapshotInFlight && isLeader parameters party nextSn
then cause (NetworkEffect $ ReqSn version nextSn (txId <$> localTxs) Nothing (Just utxo))
else noop
waitOnUnresolvedCommit $
if not snapshotInFlight && isLeader parameters party nextSn
then
newState CommitRecorded{commitUTxO = utxo, newLocalUTxO = localUTxO <> utxo}
<> cause (NetworkEffect $ ReqSn version nextSn (txId <$> (localTxs <> [txSpendingUTxO utxo])) Nothing (Just utxo))
else noop
where
waitOnUnresolvedCommit cont =
case commitUTxO of
Nothing -> cont
Just unresolvedCommitUTxO ->
if Just unresolvedCommitUTxO == commitUTxO
then cont
else wait $ WaitOnUnresolvedCommit{commitUTxO = unresolvedCommitUTxO}

waitOnUnresolvedDecommit cont =
case decommitTx of
Nothing -> cont
Expand All @@ -871,7 +900,7 @@ onOpenChainDepositTx env st utxo =

Environment{party} = env

CoordinatedHeadState{localTxs, confirmedSnapshot, seenSnapshot, version, decommitTx} = coordinatedHeadState
CoordinatedHeadState{localTxs, confirmedSnapshot, seenSnapshot, version, decommitTx, localUTxO, commitUTxO} = coordinatedHeadState

Snapshot{number = confirmedSn} = getSnapshot confirmedSnapshot

Expand Down Expand Up @@ -1260,6 +1289,18 @@ aggregate st = \case
where
CoordinatedHeadState{localTxs} = coordinatedHeadState
_otherState -> st
CommitRecorded{commitUTxO, newLocalUTxO} -> case st of
Open
os@OpenState{coordinatedHeadState} ->
Open
os
{ coordinatedHeadState =
coordinatedHeadState
{ localUTxO = newLocalUTxO
, commitUTxO = Just commitUTxO
}
}
_otherState -> st
DecommitRecorded{decommitTx, newLocalUTxO} -> case st of
Open
os@OpenState{coordinatedHeadState} ->
Expand Down Expand Up @@ -1371,6 +1412,7 @@ aggregate st = \case
, localTxs = mempty
, confirmedSnapshot = InitialSnapshot{headId, initialUTxO}
, seenSnapshot = NoSeenSnapshot
, commitUTxO = Nothing
, decommitTx = Nothing
, version = 0
}
Expand Down Expand Up @@ -1418,6 +1460,19 @@ aggregate st = \case
}
}
_otherState -> st
CommitFinalized{newVersion} ->
case st of
Open
os@OpenState{coordinatedHeadState} ->
Open
os
{ coordinatedHeadState =
coordinatedHeadState
{ commitUTxO = Nothing
, version = newVersion
}
}
_otherState -> st
DecommitFinalized{newVersion} ->
case st of
Open
Expand Down Expand Up @@ -1469,6 +1524,7 @@ recoverChainStateHistory initialChainState =
HeadAborted{chainState} -> pushNewState chainState history
HeadOpened{chainState} -> pushNewState chainState history
TransactionAppliedToLocalUTxO{} -> history
CommitRecorded{} -> history
DecommitRecorded{} -> history
SnapshotRequestDecided{} -> history
SnapshotRequested{} -> history
Expand Down
1 change: 1 addition & 0 deletions hydra-node/src/Hydra/HeadLogic/Error.hs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ data RequirementFailure tx
| ReqSvNumberInvalid {requestedSv :: SnapshotVersion, lastSeenSv :: SnapshotVersion}
| ReqSnNotLeader {requestedSn :: SnapshotNumber, leader :: Party}
| ReqSnDecommitNotSettled
| ReqSnCommitNotSettled
| InvalidMultisignature {multisig :: Text, vkeys :: [VerificationKey HydraKey]}
| SnapshotAlreadySigned {knownSignatures :: [Party], receivedSignature :: Party}
| AckSnNumberInvalid {requestedSn :: SnapshotNumber, lastSeenSn :: SnapshotNumber}
Expand Down
3 changes: 3 additions & 0 deletions hydra-node/src/Hydra/HeadLogic/Outcome.hs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ data StateChanged tx
{ tx :: tx
, newLocalUTxO :: UTxOType tx
}
| CommitRecorded {commitUTxO :: UTxOType tx, newLocalUTxO :: UTxOType tx}
| DecommitRecorded {decommitTx :: tx, newLocalUTxO :: UTxOType tx}
| SnapshotRequestDecided {snapshotNumber :: SnapshotNumber}
| -- | A snapshot was requested by some party.
Expand All @@ -83,6 +84,7 @@ data StateChanged tx
, newLocalUTxO :: UTxOType tx
, newLocalTxs :: [tx]
}
| CommitFinalized {newVersion :: SnapshotVersion}
| DecommitFinalized {newVersion :: SnapshotVersion}
| PartySignedSnapshot {snapshot :: Snapshot tx, party :: Party, signature :: Signature (Snapshot tx)}
| SnapshotConfirmed {snapshot :: Snapshot tx, signatures :: MultiSignature (Snapshot tx)}
Expand Down Expand Up @@ -177,6 +179,7 @@ data WaitReason tx
| WaitOnTxs {waitingForTxIds :: [TxIdType tx]}
| WaitOnContestationDeadline
| WaitOnNotApplicableDecommitTx {notApplicableReason :: DecommitInvalidReason tx}
| WaitOnUnresolvedCommit {commitUTxO :: UTxOType tx}
| WaitOnUnresolvedDecommit {decommitTx :: tx}
deriving stock (Generic)

Expand Down
2 changes: 2 additions & 0 deletions hydra-node/src/Hydra/HeadLogic/State.hs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ data CoordinatedHeadState tx = CoordinatedHeadState
-- ^ The latest confirmed snapshot. Spec: S̅
, seenSnapshot :: SeenSnapshot tx
-- ^ Last seen snapshot and signatures accumulator. Spec: Û, ŝ and Σ̂
, commitUTxO :: Maybe (UTxOType tx)
-- ^ Pending decommit transaction. Spec: txω
, decommitTx :: Maybe tx
-- ^ Pending decommit transaction. Spec: txω
, version :: SnapshotVersion
Expand Down
2 changes: 2 additions & 0 deletions hydra-node/test/Hydra/HeadLogicSnapshotSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ spec = do
, localTxs = mempty
, confirmedSnapshot = InitialSnapshot testHeadId u0
, seenSnapshot = NoSeenSnapshot
, commitUTxO = Nothing
, decommitTx = Nothing
, version = 0
}
Expand Down Expand Up @@ -205,6 +206,7 @@ prop_singleMemberHeadAlwaysSnapshotOnReqTx sn = monadicST $ do
, localTxs = []
, confirmedSnapshot = sn
, seenSnapshot
, commitUTxO = Nothing
, decommitTx = Nothing
, version
}
Expand Down

0 comments on commit 5f22c64

Please sign in to comment.