Skip to content
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

Ensemble/192/fanout deadline #359

Merged
24 commits merged into from
May 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ab7815a
Set Fanout tx lower bound and check it's above contestation deadline
abailly May 18, 2022
25fad00
Do not adjust fanout lower bound
abailly May 18, 2022
551fad2
Use protocol version 6 in hydra-cluster
ch1bo May 19, 2022
3bd4d47
Rename TimeHandle functions to be consistent
ch1bo May 19, 2022
c0c546f
Add grace period before posting fanout tx
abailly May 19, 2022
3bfadfe
Increase grace periods and timeouts to make it pass
ch1bo May 19, 2022
a083f83
Change our expectation on the e2e test
ch1bo May 20, 2022
f91d090
Add a remainingContestationPeriod to OnCloseTx
ch1bo May 20, 2022
eca0b47
Fake computing remaining period upstream
abailly May 20, 2022
0a3412b
Calculate remainingContestationPeriod in Hydra.Chain.Direct
ch1bo May 20, 2022
262dfa8
Add function to convert UTCTime -> POSIXTime in hydra-plutus
KtorZ May 20, 2022
e1faf9f
Update nix cache fqdn
abailly May 23, 2022
f6e2115
Fix compilation errors following change in OnCloseTx
abailly May 23, 2022
c22e397
Check conversion from plutus time preserves ordering
abailly May 23, 2022
1ebf51a
Fix values used in QC's cover function
abailly May 23, 2022
409da6d
Handle special case in test for observing OnCloseTx
abailly May 23, 2022
b76d376
Add missing fields in the Log's schema
abailly May 23, 2022
ff15ebf
Replace the use of DiffTime w/ NominalDiffTime
abailly May 23, 2022
fc319a7
Simplify computation of remaining contestation period
abailly May 23, 2022
cbecdd4
Fix time transformation and remaining deadline
abailly May 23, 2022
6384a99
Add a small margin to remaining period to prevent tx to fail
abailly May 23, 2022
3ea667a
Fix benchmark compilation
abailly May 23, 2022
dacf520
Increase wait time in TUISpec
abailly May 23, 2022
76be788
Simplify property for comparing time
abailly May 24, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ jobs:
with:
skip_adding_nixpkgs_channel: true
extra_nix_config: |
trusted-public-keys = iohk.cachix.org-1:DpRUyj7h7V830dp/i6Nti+NEO2/nhblbov/8MW7Rqoo= hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
substituters = https://cache.nixos.org https://hydra.iohk.io https://iohk.cachix.org
trusted-public-keys = iohk.cachix.org-1:DpRUyj7h7V830dp/i6Nti+NEO2/nhblbov/8MW7Rqoo= cache.iog.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
substituters = https://cache.nixos.org https://cache.iog.io https://iohk.cachix.org

- name: Cachix cache of nix derivations
uses: cachix/cachix-action@v10
Expand Down Expand Up @@ -136,8 +136,8 @@ jobs:
with:
skip_adding_nixpkgs_channel: true
extra_nix_config: |
trusted-public-keys = iohk.cachix.org-1:DpRUyj7h7V830dp/i6Nti+NEO2/nhblbov/8MW7Rqoo= hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
substituters = https://cache.nixos.org https://hydra.iohk.io https://iohk.cachix.org
trusted-public-keys = iohk.cachix.org-1:DpRUyj7h7V830dp/i6Nti+NEO2/nhblbov/8MW7Rqoo= cache.iog.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
substituters = https://cache.nixos.org https://cache.iog.io https://iohk.cachix.org

- name: Cachix cache of nix derivations
uses: cachix/cachix-action@v10
Expand Down
2 changes: 1 addition & 1 deletion hydra-cluster/config/genesis-shelley.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"poolDeposit": 0,
"protocolVersion": {
"minor": 0,
"major": 0
"major": 6
},
"minUTxOValue": 0,
"decentralisationParam": 1,
Expand Down
9 changes: 7 additions & 2 deletions hydra-cluster/test/Test/DirectChainSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import Hydra.Cardano.Api (
ChainPoint (..),
lovelaceToValue,
txOutValue,
unSlotNo,
unsafeDeserialiseFromRawBytesBase16,
)
import Hydra.Chain (
Expand All @@ -40,6 +41,7 @@ import Hydra.Chain (
import Hydra.Chain.Direct (
DirectChainLog,
IntersectionNotFoundException,
closeGraceTime,
withDirectChain,
withIOManager,
)
Expand Down Expand Up @@ -192,8 +194,8 @@ spec = around showLogsOnFailure $ do
withDirectChain (contramap (FromDirectChain "alice") tracer) defaultNetworkId iocp nodeSocket aliceKeys alice cardanoKeys Nothing (putMVar alicesCallback) $ \Chain{postTx} -> do
seedFromFaucet_ defaultNetworkId node aliceCardanoVk 100_000_000 Fuel

postTx $ InitTx $ HeadParameters 100 [alice]
alicesCallback `observesInTime` OnInitTx 100 [alice]
postTx $ InitTx $ HeadParameters 1 [alice]
alicesCallback `observesInTime` OnInitTx 1 [alice]

someUTxO <- seedFromFaucet defaultNetworkId node aliceCardanoVk 1_000_000 Normal
postTx $ CommitTx alice someUTxO
Expand Down Expand Up @@ -222,6 +224,9 @@ spec = around showLogsOnFailure $ do
_ ->
False

-- TODO: compute from chain parameters
-- contestation period + closeGraceTime * slot length
threadDelay $ 1 + (fromIntegral (unSlotNo closeGraceTime) * 0.1)
postTx $
FanoutTx
{ utxo = someUTxO
Expand Down
10 changes: 8 additions & 2 deletions hydra-cluster/test/Test/EndToEndSpec.hs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{-# LANGUAGE TypeApplications #-}
{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}

module Test.EndToEndSpec where
Expand Down Expand Up @@ -34,7 +35,9 @@ import Hydra.Cardano.Api (
lovelaceToValue,
mkVkAddress,
serialiseAddress,
unSlotNo,
)
import Hydra.Chain.Direct (closeGraceTime)
import Hydra.Crypto (deriveVerificationKey, generateSigningKey)
import qualified Hydra.Crypto as Hydra
import Hydra.Ledger (txId)
Expand Down Expand Up @@ -273,7 +276,8 @@ initAndClose tracer clusterIx node@(RunningNode _ nodeSocket) = do
seedFromFaucet_ defaultNetworkId node bobCardanoVk 100_000_000 Fuel
seedFromFaucet_ defaultNetworkId node carolCardanoVk 100_000_000 Fuel

let contestationPeriod = 10 :: Natural
let contestationPeriod = 2

send n1 $ input "Init" ["contestationPeriod" .= contestationPeriod]
waitFor tracer 10 [n1, n2, n3] $
output "ReadyToCommit" ["parties" .= Set.fromList [alice, bob, carol]]
Expand Down Expand Up @@ -341,7 +345,9 @@ initAndClose tracer clusterIx node@(RunningNode _ nodeSocket) = do
snapshotNumber <- v ^? key "snapshotNumber"
guard $ snapshotNumber == toJSON expectedSnapshotNumber

waitFor tracer (contestationPeriod + 3) [n1] $
-- NOTE: We expect the head to be finalized after the contestation period
-- and some three secs later, plus the closeGraceTime * slotLength
waitFor tracer (truncate $ contestationPeriod + (fromIntegral @_ @Double (unSlotNo closeGraceTime) * 0.1) + 3) [n1] $
output "HeadIsFinalized" ["utxo" .= newUTxO]

case fromJSON $ toJSON newUTxO of
Expand Down
2 changes: 1 addition & 1 deletion hydra-cluster/test/Test/LogFilterSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ spec = parallel $ do
filtered = encode $ mapMaybe filterLog jsonLogs
sizeRatio = fromIntegral (LBS.length filtered) * (100.0 :: Double) / fromIntegral (LBS.length bytes)
in LBS.length filtered < LBS.length bytes && sizeRatio > 0
& cover 0.9 (sizeRatio < 10.0) "reduces size by 90%"
& cover 40 (sizeRatio < 10.0) "reduces size by 90%"
& tabulate "Ratios" [show (floor (sizeRatio / 10) * 10 :: Int) <> " %"]
& checkCoverage
5 changes: 3 additions & 2 deletions hydra-node/exe/tx-cost/TxCost.hs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ import Hydra.Ledger.Cardano (
genTxIn,
simplifyUTxO,
)
import Hydra.Ledger.Cardano.Evaluate (evaluateTx, pparams)
import Hydra.Ledger.Cardano.Evaluate (evaluateTx, genPointInTime, pparams)
import Plutus.Orphans ()
import Test.QuickCheck (generate, sublistOf, vectorOf)

Expand Down Expand Up @@ -164,7 +164,8 @@ computeFanOutCost = do
ctx <- genHydraContext 3
let utxo = genSimpleUTxOOfSize numOutputs `generateWith` 42
(_, stClosed) <- genStClosed ctx utxo
pure (fanout utxo stClosed, getKnownUTxO stClosed)
pointInTime <- genPointInTime
pure (fanout utxo pointInTime stClosed, getKnownUTxO stClosed)

genSimpleUTxOOfSize :: Int -> Gen UTxO
genSimpleUTxOOfSize numUTxO =
Expand Down
4 changes: 4 additions & 0 deletions hydra-node/json-schemas/logs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -891,13 +891,17 @@ definitions:
required:
- tag
- snapshotNumber
- remainingContestationPeriod
properties:
tag:
type: string
enum: ["OnCloseTx"]
snapshotNumber:
type: integer
minimum: 0
remainingContestationPeriod:
type: integer
minimum: 0
- title: OnContestTx
type: object
additionalProperties: false
Expand Down
11 changes: 8 additions & 3 deletions hydra-node/src/Hydra/Chain.hs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import Hydra.Snapshot (ConfirmedSnapshot, SnapshotNumber)

-- | Contains the head's parameters as established in the initial transaction.
data HeadParameters = HeadParameters
{ contestationPeriod :: DiffTime
{ contestationPeriod :: NominalDiffTime
, parties :: [Party] -- NOTE(SN): The order of this list is important for leader selection.
}
deriving stock (Eq, Show, Generic)
Expand All @@ -34,7 +34,7 @@ data HeadParameters = HeadParameters
instance Arbitrary HeadParameters where
arbitrary = genericArbitrary

type ContestationPeriod = DiffTime
type ContestationPeriod = NominalDiffTime

-- | Data type used to post transactions on chain. It holds everything to
-- construct corresponding Head protocol transactions.
Expand Down Expand Up @@ -82,7 +82,12 @@ data OnChainTx tx
| OnCommitTx {party :: Party, committed :: UTxOType tx}
| OnAbortTx
| OnCollectComTx
| OnCloseTx {snapshotNumber :: SnapshotNumber}
| OnCloseTx
{ snapshotNumber :: SnapshotNumber
, -- | The remaining contestation period in wall clock time calculated
-- from the actual upper bound of the close transaction observed.
remainingContestationPeriod :: NominalDiffTime
}
| OnContestTx {snapshotNumber :: SnapshotNumber}
| OnFanoutTx
deriving (Generic)
Expand Down
68 changes: 41 additions & 27 deletions hydra-node/src/Hydra/Chain/Direct.hs
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,14 @@ import Hydra.Chain.Direct.State (
commit,
contest,
fanout,
getContestationDeadline,
getKnownUTxO,
idleOnChainHeadState,
initialize,
observeSomeTx,
reifyState,
)
import Hydra.Chain.Direct.Tx (PointInTime)
import Hydra.Chain.Direct.Util (
Block,
Era,
Expand All @@ -122,6 +124,7 @@ import Hydra.Chain.Direct.Wallet (
getTxId,
withTinyWallet,
)
import Hydra.Data.ContestationPeriod (posixToUTCTime)
import Hydra.Logging (Tracer, traceWith)
import Hydra.Party (Party)
import Ouroboros.Consensus.Cardano.Block (EraMismatch, GenTx (..), HardForkApplyTxErr (ApplyTxErrAlonzo), HardForkBlock (BlockAlonzo))
Expand Down Expand Up @@ -163,7 +166,6 @@ import Ouroboros.Network.Protocol.LocalTxSubmission.Client (
SubmitResult (..),
localTxSubmissionClientPeer,
)
import Plutus.V1.Ledger.Api (POSIXTime)
import Test.Cardano.Ledger.Alonzo.Serialisation.Generators ()

withDirectChain ::
Expand Down Expand Up @@ -266,11 +268,11 @@ withDirectChain tracer networkId iocp socketPath keyPair party cardanoKeys point
}

data TimeHandle m = TimeHandle
{ currentSlot :: m SlotNo
, -- | Convert some slot into an absolute point in time.
-- It throws an exception when requesting a `SlotNo` that is
-- more than the current epoch length (5 days at time of writing this comment).
convertSlot :: MonadThrow m => SlotNo -> m POSIXTime
{ -- | Get the current 'PointInTime'
currentPointInTime :: m PointInTime
, -- | Adjust a 'PointInTime' by some number of slots, positively or
-- negatively.
adjustPointInTime :: SlotNo -> PointInTime -> m PointInTime
}

-- | Query ad-hoc epoch, system start and protocol parameters to determine
Expand All @@ -282,14 +284,18 @@ queryTimeHandle networkId socketPath = do
let epochInfo = toEpochInfo eraHistory
pparams <- queryProtocolParameters networkId socketPath
slotNo <- queryTipSlotNo networkId socketPath
let toTime =
slotToPOSIXTime
(toLedgerPParams ShelleyBasedEraAlonzo pparams :: PParams LedgerEra)
epochInfo
systemStart
pure $
TimeHandle
{ currentSlot = pure slotNo
, convertSlot =
slotToPOSIXTime
(toLedgerPParams ShelleyBasedEraAlonzo pparams :: PParams LedgerEra)
epochInfo
systemStart
{ currentPointInTime = (slotNo,) <$> toTime slotNo
, adjustPointInTime = \n (slot, _) -> do
let adjusted = slot + n
time <- toTime adjusted
pure (adjusted, time)
}
where
toEpochInfo :: MonadThrow m => EraHistory CardanoMode -> EpochInfo m
Expand Down Expand Up @@ -382,7 +388,7 @@ data ChainSyncHandler m = ChainSyncHandler

chainSyncHandler ::
forall m.
(MonadSTM m) =>
(MonadSTM m, MonadTime m) =>
-- | Tracer for logging
Tracer m DirectChainLog ->
-- | Chain callback
Expand All @@ -407,7 +413,8 @@ chainSyncHandler tracer callback headState =
onRollForward :: Block -> m ()
onRollForward blk = do
let receivedTxs = toList $ getAlonzoTxs blk
onChainTxs <- reverse <$> atomically (foldM (withNextTx (blockPoint blk)) [] receivedTxs)
now <- getCurrentTime
onChainTxs <- reverse <$> atomically (foldM (withNextTx now (blockPoint blk)) [] receivedTxs)
unless (null receivedTxs) $
traceWith tracer $
ReceivedTxs
Expand All @@ -416,17 +423,26 @@ chainSyncHandler tracer callback headState =
}
mapM_ (callback . Observation) onChainTxs

withNextTx :: Point Block -> [OnChainTx Tx] -> ValidatedTx Era -> STM m [OnChainTx Tx]
withNextTx point observed (fromLedgerTx -> tx) = do
-- NOTE: We pass 'now' or current time because we need it for observing passing of time in the
-- contestation phase.
withNextTx :: UTCTime -> Point Block -> [OnChainTx Tx] -> ValidatedTx Era -> STM m [OnChainTx Tx]
withNextTx now point observed (fromLedgerTx -> tx) = do
st <- readTVar headState
case observeSomeTx tx (currentOnChainHeadState st) of
Just (onChainTx, st') -> do
Just (onChainTx, st'@(SomeOnChainHeadState nextState)) -> do
writeTVar headState $
SomeOnChainHeadStateAt
{ currentOnChainHeadState = st'
, recordedAt = AtPoint (fromConsensusPointHF point) st
}
pure $ onChainTx : observed
-- FIXME: The right thing to do is probably to decouple the observation from the
-- transformation into an `OnChainTx`
let event = case (onChainTx, reifyState nextState) of
(OnCloseTx{snapshotNumber}, TkClosed) ->
let remainingTimeWithBuffer = 1 + diffUTCTime (posixToUTCTime $ getContestationDeadline nextState) now
in OnCloseTx{snapshotNumber, remainingContestationPeriod = remainingTimeWithBuffer}
_ -> onChainTx
pure $ event : observed
Nothing ->
pure observed

Expand Down Expand Up @@ -605,7 +621,6 @@ finalizeTx TinyWallet{sign, getUTxO, coverFee} headState partialTx = do
pure $ sign validatedTx

-- | Hardcoded grace time for close transaction to be valid.
-- TODO: replace/remove with deadline contestation
-- TODO: make it a node configuration parameter
closeGraceTime :: SlotNo
closeGraceTime = 100
Expand All @@ -618,7 +633,8 @@ fromPostChainTx ::
TVar m SomeOnChainHeadStateAt ->
PostChainTx Tx ->
STM m Tx
fromPostChainTx TimeHandle{currentSlot, convertSlot} cardanoKeys wallet someHeadState tx = do
fromPostChainTx TimeHandle{currentPointInTime, adjustPointInTime} cardanoKeys wallet someHeadState tx = do
pointInTime <- currentPointInTime
SomeOnChainHeadState st <- currentOnChainHeadState <$> readTVar someHeadState
case (tx, reifyState st) of
(InitTx params, TkIdle) -> do
Expand All @@ -644,15 +660,13 @@ fromPostChainTx TimeHandle{currentSlot, convertSlot} cardanoKeys wallet someHead
(CollectComTx{}, TkInitialized) -> do
pure (collect st)
(CloseTx{confirmedSnapshot}, TkOpen) -> do
slot <- (+ closeGraceTime) <$> currentSlot
posixTime <- convertSlot slot
pure (close confirmedSnapshot (slot, posixTime) st)
shifted <- adjustPointInTime closeGraceTime pointInTime
pure (close confirmedSnapshot shifted st)
(ContestTx{confirmedSnapshot}, TkClosed) -> do
slot <- (+ closeGraceTime) <$> currentSlot
posixTime <- convertSlot slot
pure (contest confirmedSnapshot (slot, posixTime) st)
shifted <- adjustPointInTime closeGraceTime pointInTime
pure (contest confirmedSnapshot shifted st)
(FanoutTx{utxo}, TkClosed) ->
pure (fanout utxo st)
pure (fanout utxo pointInTime st)
(_, _) ->
throwIO $ InvalidStateToPost tx

Expand Down
18 changes: 15 additions & 3 deletions hydra-node/src/Hydra/Chain/Direct/Context.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,18 @@ import Hydra.Chain.Direct.State (
collect,
commit,
contest,
fanout,
getContestationDeadline,
idleOnChainHeadState,
initialize,
observeTx,
)
import qualified Hydra.Crypto as Hydra
import Hydra.Ledger.Cardano (genOneUTxOFor, genTxIn, genVerificationKey, renderTx)
import Hydra.Ledger.Cardano (genOneUTxOFor, genTxIn, genUTxO, genVerificationKey, renderTx, simplifyUTxO)
import Hydra.Ledger.Cardano.Evaluate (genPointInTime, slotNoToPOSIXTime)
import Hydra.Party (Party, deriveParty)
import Hydra.Snapshot (ConfirmedSnapshot (..), Snapshot (..), SnapshotNumber, genConfirmedSnapshot, getSnapshot)
import Test.QuickCheck (choose, elements, frequency, suchThat, vector)
import Test.QuickCheck (choose, elements, frequency, resize, suchThat, vector)

-- | Define some 'global' context from which generators can pick
-- values for generation. This allows to write fairly independent generators
Expand All @@ -45,7 +46,7 @@ data HydraContext = HydraContext
{ ctxVerificationKeys :: [VerificationKey PaymentKey]
, ctxHydraSigningKeys :: [Hydra.SigningKey]
, ctxNetworkId :: NetworkId
, ctxContestationPeriod :: DiffTime
, ctxContestationPeriod :: NominalDiffTime
}
deriving (Show)

Expand Down Expand Up @@ -157,6 +158,17 @@ genContestTx numParties = do
slotNoToPOSIXTime slot < getContestationDeadline stClosed
pure (stClosed, contest snapshot pointInTime stClosed)

genFanoutTx :: Int -> Gen (OnChainHeadState 'StClosed, Tx)
genFanoutTx numParties = do
ctx <- genHydraContext numParties
let maxAssetsSupported = 1
utxo <- resize maxAssetsSupported $ simplifyUTxO <$> genUTxO
(_, stClosed) <- genStClosed ctx utxo
pointInTime <-
genPointInTime `suchThat` \(slot, _) ->
slotNoToPOSIXTime slot > getContestationDeadline stClosed
pure (stClosed, fanout utxo pointInTime stClosed)

genStOpen ::
HydraContext ->
Gen (UTxO, OnChainHeadState 'StOpen)
Expand Down
Loading