|
| 1 | +{-# LANGUAGE DeriveAnyClass #-} |
| 2 | + |
| 3 | +-- | Controls a Mithril signer service. |
| 4 | +module Mithril.Signer where |
| 5 | + |
| 6 | +import CardanoNode (RunningNode) |
| 7 | +import Control.Tracer (Tracer, traceWith) |
| 8 | +import qualified Data.ByteString as BS |
| 9 | +import Hydra.Prelude |
| 10 | +import qualified Paths_mithril_end_to_end as Pkg |
| 11 | +import System.Directory (doesFileExist) |
| 12 | +import System.Environment (getEnvironment) |
| 13 | +import System.FilePath ((</>)) |
| 14 | +import System.Process (CreateProcess (..), StdStream (UseHandle), proc, withCreateProcess) |
| 15 | +import Test.Hydra.Prelude (checkProcessHasNotDied, failure) |
| 16 | + |
| 17 | +data SignerLog |
| 18 | + = StartingSigner FilePath |
| 19 | + | SignerStarted |
| 20 | + deriving stock (Eq, Show, Generic) |
| 21 | + deriving anyclass (ToJSON, FromJSON) |
| 22 | + |
| 23 | +data Signer = Signer |
| 24 | + { workDirectory :: FilePath, |
| 25 | + aggregatorEndpoint :: Text |
| 26 | + } |
| 27 | + deriving stock (Eq, Show, Generic) |
| 28 | + |
| 29 | +-- TODO: starts a signer daemon that checks snapshots, sign them and send the signature |
| 30 | +-- to the 'Aggregator' server listening at 'aggregatorPort', for the given running node |
| 31 | +withSigner :: FilePath -> Tracer IO SignerLog -> Int -> RunningNode -> (Signer -> IO a) -> IO a |
| 32 | +withSigner workDirectory tracer aggregatorPort _cardanoNode action = do |
| 33 | + process <- signerProcess (Just workDirectory) aggregatorEndpoint |
| 34 | + traceWith tracer (StartingSigner workDirectory) |
| 35 | + withFile logFile WriteMode $ \out -> |
| 36 | + withCreateProcess process {std_out = UseHandle out, std_err = UseHandle out} $ \_stdin _stdout _stderr processHandle -> |
| 37 | + ( race |
| 38 | + (checkProcessHasNotDied "mithril-signer" processHandle) |
| 39 | + (traceWith tracer SignerStarted >> action (Signer {workDirectory, aggregatorEndpoint})) |
| 40 | + >>= \case |
| 41 | + Left _ -> error "should never happen" |
| 42 | + Right a -> pure a |
| 43 | + ) |
| 44 | + `onException` (BS.readFile logFile >>= BS.putStr) |
| 45 | + where |
| 46 | + aggregatorEndpoint = "http://localhost:" <> show aggregatorPort <> "/aggregator" |
| 47 | + logFile = workDirectory </> "signer.log" |
| 48 | + |
| 49 | +signerProcess :: Maybe FilePath -> Text -> IO CreateProcess |
| 50 | +signerProcess cwd aggregatorEndpoint = do |
| 51 | + binDir <- Pkg.getBinDir |
| 52 | + baseEnv <- getEnvironment |
| 53 | + let signer = binDir </> "mithril-signer" |
| 54 | + env = |
| 55 | + Just $ |
| 56 | + [ ("AGGREGATOR_ENDPOINT", toString aggregatorEndpoint), |
| 57 | + ("NETWORK", "testnet"), |
| 58 | + ("PARTY_ID", "0"), |
| 59 | + ("RUN_INTERVAL", "2000"), |
| 60 | + ("DB_DIRECTORY", "db"), |
| 61 | + ("STAKE_STORE_DIRECTORY", "./store/stakes") |
| 62 | + ] |
| 63 | + <> baseEnv |
| 64 | + |
| 65 | + unlessM (doesFileExist signer) $ failure $ "cannot find mithril-signer executable in expected location (" <> binDir <> ")" |
| 66 | + pure $ (proc signer ["-vvv"]) {cwd, env} |
0 commit comments