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

Run benchmarks on mock chain #229

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
docker:
strategy:
matrix:
target: [ hydra-node, hydra-tui ]
target: [ hydra-node, hydra-tui, mock-chain ]

runs-on: ubuntu-latest
steps:
Expand Down
14 changes: 14 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ COPY . .

RUN nix-build -A hydra-node -o hydra-node-result release.nix > hydra-node.drv
RUN nix-build -A hydra-tui -o hydra-tui-result release.nix > hydra-tui.drv
RUN nix-build -A mock-chain -o mock-chain-result release.nix > mock-chain.drv

RUN nix-store --export $(nix-store -qR $(cat hydra-node.drv)) > hydra-node.closure
RUN nix-store --export $(nix-store -qR $(cat hydra-tui.drv)) > hydra-tui.closure
RUN nix-store --export $(nix-store -qR $(cat mock-chain.drv)) > mock-chain.closure

# ------------------------------------------------------------------- HYDRA-NODE

Expand All @@ -43,3 +45,15 @@ RUN nix-store --import < hydra-tui.closure && nix-env -i $(cat hydra-tui.drv)

STOPSIGNAL SIGINT
ENTRYPOINT ["hydra-tui"]

# ------------------------------------------------------------------- MOCK-CHAIN

FROM nixos/nix:2.3.11 as mock-chain

COPY --from=build /build/mock-chain.drv mock-chain.drv
COPY --from=build /build/mock-chain.closure mock-chain.closure

RUN nix-store --import < mock-chain.closure && nix-env -i $(cat mock-chain.drv)

STOPSIGNAL SIGINT
ENTRYPOINT ["mock-chain"]
22 changes: 13 additions & 9 deletions hydra-cluster/bench/Bench/EndToEnd.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ import CardanoClient (
submit,
waitForTransaction,
)
import CardanoCluster (defaultNetworkId, newNodeConfig, withBFTNode)
import CardanoNode (RunningNode (..))
import CardanoCluster (defaultNetworkId)
import Control.Lens (to, (^?))
import Control.Monad.Class.MonadAsync (mapConcurrently)
import Control.Monad.Class.MonadSTM (
Expand All @@ -40,13 +39,13 @@ import Data.Scientific (Scientific)
import Data.Set ((\\))
import qualified Data.Set as Set
import Data.Time (UTCTime (UTCTime), nominalDiffTimeToSeconds, utctDayTime)
import Hydra.Cardano.Api (Tx, TxId, UTxO, getVerificationKey)
import Hydra.Cardano.Api (Tx, TxId, TxIn (TxIn), TxIx (TxIx), UTxO, UTxO' (UTxO), getVerificationKey, toUTxOContext, txOuts')
import Hydra.Generator (Dataset (..))
import Hydra.Ledger (txId)
import Hydra.Logging (withTracerOutputTo)
import Hydra.Party (deriveParty, generateKey)
import HydraNode (
EndToEndLog (..),
ChainConnection (ConnectToMockChain),
HydraClient,
hydraNodeId,
input,
Expand All @@ -56,6 +55,7 @@ import HydraNode (
waitForNodesConnected,
waitMatch,
withHydraCluster,
withMockChain,
withNewClient,
)
import System.Directory (findExecutable)
Expand All @@ -69,7 +69,7 @@ import System.Process (
)
import Text.Printf (printf)
import Text.Regex.TDFA (getAllTextMatches, (=~))
import Prelude (read)
import Prelude (head, read)

aliceSk, bobSk, carolSk :: SignKeyDSIGN MockDSIGN
aliceSk = 10
Expand Down Expand Up @@ -97,17 +97,21 @@ bench timeoutSeconds workDir dataset clusterSize =
let cardanoKeys = map (\Dataset{signingKey} -> (getVerificationKey signingKey, signingKey)) dataset
let hydraKeys = generateKey <$> [1 .. toInteger (length cardanoKeys)]
let parties = Set.fromList (deriveParty <$> hydraKeys)
config <- newNodeConfig workDir
withOSStats workDir $
withBFTNode (contramap FromCluster tracer) config (fst <$> cardanoKeys) $ \(RunningNode _ nodeSocket) -> do
withHydraCluster tracer workDir nodeSocket 1 cardanoKeys hydraKeys $ \(leader :| followers) -> do
withMockChain $ \ports -> do
withHydraCluster tracer workDir (ConnectToMockChain ports) cardanoKeys $ \(leader :| followers) -> do
let nodes = leader : followers
waitForNodesConnected tracer nodes

initialUTxOs <- createUTxOToCommit dataset nodeSocket
let initialUTxOs =
UTxO . uncurry Map.singleton
<$> zip
((`TxIn` TxIx 0) . txId . fundingTransaction <$> dataset)
(toUTxOContext . Prelude.head . txOuts' . fundingTransaction <$> dataset)

let contestationPeriod = 10 :: Natural
send leader $ input "Init" ["contestationPeriod" .= contestationPeriod]
let parties = Set.fromList $ map (deriveParty . generateKey) [1 .. fromIntegral clusterSize]
waitFor tracer (fromIntegral $ 10 * clusterSize) nodes $
output "ReadyToCommit" ["parties" .= parties]

Expand Down
2 changes: 1 addition & 1 deletion hydra-cluster/bench/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ benchOptions =
( fullDesc
<> progDesc
"Starts a cluster of Hydra nodes interconnected through a network and \
\ talking to a local cardano devnet, generates an initial UTxO set and a bunch \
\ talking to mock-chain, generates an initial UTxO set and a bunch \
\ of valid transactions, and send those transactions to the cluster as \
\ fast as possible.\n \
\ Arguments can control various parameters of the run, like number of nodes, \
Expand Down
6 changes: 4 additions & 2 deletions hydra-cluster/hydra-cluster.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,8 @@ test-suite integration

build-tool-depends:
hspec-discover:hspec-discover -any, hydra-node:hydra-node -any,
cardano-node:cardano-node -any, cardano-cli:cardano-cli -any
hydra-node:mock-chain -any, cardano-node:cardano-node -any,
cardano-cli:cardano-cli -any

ghc-options: -threaded -rtsopts

Expand Down Expand Up @@ -284,6 +285,7 @@ benchmark bench-e2e
, time

build-tool-depends:
hydra-node:hydra-node -any, cardano-node:cardano-node -any
hydra-node:hydra-node -any, hydra-node:mock-chain -any,
cardano-node:cardano-node -any, cardano-cli:cardano-cli -any

ghc-options: -threaded -rtsopts
69 changes: 53 additions & 16 deletions hydra-cluster/src/HydraNode.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

module HydraNode (
HydraClient (..),
ChainConnection (..),
withHydraNode,
send,
input,
Expand All @@ -13,6 +14,7 @@ module HydraNode (
getMetrics,
queryNode,
defaultArguments,
withMockChain,
hydraNodeProcess,
module System.Process,
waitForNodesConnected,
Expand Down Expand Up @@ -59,6 +61,7 @@ import System.Process (
)
import System.Timeout (timeout)
import Test.Hydra.Prelude (checkProcessHasNotDied, failAfter, failure, withFile')
import Test.Network.Ports (randomUnusedTCPPorts)
import qualified Prelude

data HydraClient = HydraClient
Expand Down Expand Up @@ -185,20 +188,22 @@ data EndToEndLog
| FromCluster ClusterLog
deriving (Eq, Show, Generic, ToJSON, FromJSON, ToObject)

-- XXX: The two lists need to be of same length. Also the verification keys can
-- be derived from the signing keys.
data ChainConnection
= ConnectToCardanoNode FilePath
| ConnectToMockChain (Int, Int, Int)

withHydraCluster ::
Tracer IO EndToEndLog ->
FilePath ->
FilePath ->
ChainConnection ->
-- | First node id
Int ->
-- | NOTE: This decides on the size of the cluster!
[(VerificationKey PaymentKey, SigningKey PaymentKey)] ->
[Hydra.SigningKey] ->
(NonEmpty HydraClient -> IO ()) ->
IO ()
withHydraCluster tracer workDir nodeSocket firstNodeId allKeys hydraKeys action = do
withHydraCluster tracer workDir chainConnection firstNodeId allKeys hydraKeys action = do
-- We have been bitten by this in the past
when (clusterSize == 0) $
error "Cannot run a cluster with 0 number of nodes"
Expand Down Expand Up @@ -226,7 +231,7 @@ withHydraCluster tracer workDir nodeSocket firstNodeId allKeys hydraKeys action
cardanoSKey
cardanoVKeys
workDir
nodeSocket
chainConnection
nodeId
hydraSKey
hydraVKeys
Expand All @@ -240,25 +245,27 @@ withHydraNode ::
String ->
[String] ->
FilePath ->
FilePath ->
ChainConnection ->
Int ->
SignKeyDSIGN alg ->
[VerKeyDSIGN alg] ->
[Int] ->
(HydraClient -> IO ()) ->
IO ()
withHydraNode tracer cardanoSKeyPath cardanoVKeysPaths workDir nodeSocket hydraNodeId hydraSKey hydraVKeys allNodeIds action = do
withHydraNode tracer cardanoSKeyPath cardanoVKeysPaths workDir chainConnection hydraNodeId hydraSKey hydraVKeys allNodeIds action = do
withFile' (workDir </> show hydraNodeId) $ \out -> do
withSystemTempDirectory "hydra-node" $ \dir -> do
let hydraSKeyPath = dir </> (show hydraNodeId <> ".sk")
BS.writeFile hydraSKeyPath (rawSerialiseSignKeyDSIGN hydraSKey)
hydraVKeysPaths <- forM (zip [1 ..] hydraVKeys) $ \(i :: Int, vKey) -> do
let filepath = dir </> (show i <> ".vk")
filepath <$ BS.writeFile filepath (rawSerialiseVerKeyDSIGN vKey)
let p =
(hydraNodeProcess $ defaultArguments hydraNodeId cardanoSKeyPath cardanoVKeysPaths hydraSKeyPath hydraVKeysPaths nodeSocket allNodeIds)
let args = defaultArguments hydraNodeId cardanoSKeyPath cardanoVKeysPaths hydraSKeyPath hydraVKeysPaths chainConnection allNodeIds
p =
(hydraNodeProcess $ args)
{ std_out = UseHandle out
}
print args
withCreateProcess p $
\_stdin _stdout _stderr processHandle -> do
race_
Expand Down Expand Up @@ -300,10 +307,10 @@ defaultArguments ::
[FilePath] ->
FilePath ->
[FilePath] ->
FilePath ->
ChainConnection ->
[Int] ->
[String]
defaultArguments nodeId cardanoSKey cardanoVKeys hydraSKey hydraVKeys nodeSocket allNodeIds =
defaultArguments nodeId cardanoSKey cardanoVKeys hydraSKey hydraVKeys chainConnection allNodeIds =
[ "--node-id"
, show nodeId
, "--host"
Expand All @@ -318,14 +325,27 @@ defaultArguments nodeId cardanoSKey cardanoVKeys hydraSKey hydraVKeys nodeSocket
, show (6000 + nodeId)
, "--hydra-signing-key"
, hydraSKey
, "--cardano-signing-key"
, cardanoSKey
]
<> concat [["--peer", "127.0.0.1:" <> show (5000 + i)] | i <- allNodeIds, i /= nodeId]
<> concat [["--hydra-verification-key", vKey] | vKey <- hydraVKeys]
<> concat [["--cardano-verification-key", vKey] | vKey <- cardanoVKeys]
<> ["--network-magic", "42"]
<> ["--node-socket", nodeSocket]
<> chainConnectionArguments
where
chainConnectionArguments = case chainConnection of
(ConnectToCardanoNode nodeSocket) ->
[ "--network-magic"
, "42"
, "--node-socket"
, nodeSocket
, "--cardano-signing-key"
, cardanoSKey
]
<> concat [["--cardano-verification-key", vKey] | vKey <- cardanoVKeys]
(ConnectToMockChain (sync, catchUp, post)) ->
[ "--mock-chain-host"
, "127.0.0.1"
, "--mock-chain-ports"
, "(" <> show sync <> "," <> show catchUp <> "," <> show post <> ")"
]

waitForNodesConnected :: HasCallStack => Tracer IO EndToEndLog -> [HydraClient] -> IO ()
waitForNodesConnected tracer clients =
Expand All @@ -346,3 +366,20 @@ waitForNodesConnected tracer clients =
]
)
(filter (/= hydraNodeId) allNodeIds)

withMockChain :: ((Int, Int, Int) -> IO ()) -> IO ()
withMockChain action = do
[sync, catchUp, post] <- randomUnusedTCPPorts 3
withCreateProcess (proc "mock-chain" (arguments sync catchUp post)) $
\_in _out _err processHandle -> do
race_ (checkProcessHasNotDied "mock-chain" processHandle) (action (sync, catchUp, post))
where
arguments s c p =
[ "--quiet"
, "--sync-address"
, "tcp://127.0.0.1:" <> show s
, "--catch-up-address"
, "tcp://127.0.0.1:" <> show c
, "--post-address"
, "tcp://127.0.0.1:" <> show p
]
11 changes: 6 additions & 5 deletions hydra-cluster/test/Test/EndToEndSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import Hydra.Logging (Tracer, showLogsOnFailure)
import Hydra.Party (Party, deriveParty)
import qualified Hydra.Party as Party
import HydraNode (
ChainConnection (ConnectToCardanoNode),
EndToEndLog (..),
getMetrics,
hydraNodeProcess,
Expand Down Expand Up @@ -118,8 +119,8 @@ spec = around showLogsOnFailure $
(aliceVkPath, aliceSkPath) <- writeKeysFor tmpDir Alice
(_, bobSkPath) <- writeKeysFor tmpDir Bob
pparams <- queryProtocolParameters defaultNetworkId nodeSocket
withHydraNode tracer aliceSkPath [] tmpDir nodeSocket 1 aliceSk [] allNodeIds $ \n1 ->
withHydraNode tracer bobSkPath [aliceVkPath] tmpDir nodeSocket 2 bobSk [aliceVk] allNodeIds $ \n2 -> do
withHydraNode tracer aliceSkPath [] tmpDir (ConnectToCardanoNode nodeSocket) 1 aliceSk [] allNodeIds $ \n1 ->
withHydraNode tracer bobSkPath [aliceVkPath] tmpDir (ConnectToCardanoNode nodeSocket) 2 bobSk [aliceVk] allNodeIds $ \n2 -> do
postSeedPayment defaultNetworkId pparams availableInitialFunds nodeSocket aliceCardanoSk 100_000_000
postSeedPayment defaultNetworkId pparams availableInitialFunds nodeSocket bobCardanoSk 100_000_000

Expand Down Expand Up @@ -169,9 +170,9 @@ spec = around showLogsOnFailure $
(carolVkPath, carolSkPath) <- writeKeysFor tmpDir Carol
pparams <- queryProtocolParameters defaultNetworkId nodeSocket
failAfter 20 $
withHydraNode tracer aliceSkPath [bobVkPath, carolVkPath] tmpDir nodeSocket 1 aliceSk [bobVk, carolVk] allNodeIds $ \n1 ->
withHydraNode tracer bobSkPath [aliceVkPath, carolVkPath] tmpDir nodeSocket 2 bobSk [aliceVk, carolVk] allNodeIds $ \_ ->
withHydraNode tracer carolSkPath [aliceVkPath, bobVkPath] tmpDir nodeSocket 3 carolSk [aliceVk, bobVk] allNodeIds $ \_ -> do
withHydraNode tracer aliceSkPath [bobVkPath, carolVkPath] tmpDir (ConnectToCardanoNode nodeSocket) 1 aliceSk [bobVk, carolVk] allNodeIds $ \n1 ->
withHydraNode tracer bobSkPath [aliceVkPath, carolVkPath] tmpDir (ConnectToCardanoNode nodeSocket) 2 bobSk [aliceVk, carolVk] allNodeIds $ \_ ->
withHydraNode tracer carolSkPath [aliceVkPath, bobVkPath] tmpDir (ConnectToCardanoNode nodeSocket) 3 carolSk [aliceVk, bobVk] allNodeIds $ \_ -> do
postSeedPayment defaultNetworkId pparams availableInitialFunds nodeSocket aliceCardanoSk 100_000_000
waitForNodesConnected tracer [n1]
send n1 $ input "Init" ["contestationPeriod" .= int 10]
Expand Down
35 changes: 18 additions & 17 deletions hydra-node/exe/hydra-node/Main.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE TypeApplications #-}

module Main where

Expand All @@ -9,6 +8,7 @@ import Hydra.API.Server (withAPIServer)
import Hydra.Chain (Chain, ChainCallback)
import Hydra.Chain.Direct (withDirectChain)
import Hydra.Chain.Direct.Util (readKeyPair, readVerificationKey)
import Hydra.Chain.ZeroMQ (withMockChain)
import Hydra.HeadLogic (Environment (..), Event (..))
import Hydra.Ledger.Cardano (Tx)
import qualified Hydra.Ledger.Cardano as Ledger
Expand Down Expand Up @@ -51,22 +51,23 @@ withChain ::
ChainConfig ->
(Chain Tx IO -> IO ()) ->
IO ()
withChain tracer party callback config action = do
keyPair@(vk, _) <- readKeyPair cardanoSigningKey
otherCardanoKeys <- mapM readVerificationKey cardanoVerificationKeys
withIOManager $ \iocp -> do
withDirectChain
(contramap DirectChain tracer)
networkMagic
iocp
nodeSocket
keyPair
party
(vk : otherCardanoKeys)
callback
action
where
DirectChainConfig{networkMagic, nodeSocket, cardanoSigningKey, cardanoVerificationKeys} = config
withChain tracer party callback config action = case config of
MockChainConfig mockChain ->
withMockChain (contramap MockChain tracer) mockChain callback action
DirectChainConfig{networkMagic, nodeSocket, cardanoSigningKey, cardanoVerificationKeys} -> do
keyPair@(vk, _) <- readKeyPair cardanoSigningKey
otherCardanoKeys <- mapM readVerificationKey cardanoVerificationKeys
withIOManager $ \iocp -> do
withDirectChain
(contramap DirectChain tracer)
networkMagic
iocp
nodeSocket
keyPair
party
(vk : otherCardanoKeys)
callback
action

identifyNode :: Options -> Options
identifyNode opt@Options{verbosity = Verbose "HydraNode", nodeId} = opt{verbosity = Verbose $ "HydraNode-" <> show nodeId}
Expand Down
Loading