hbs2/hbs2-peer/app/CLI/RefChan.hs

165 lines
6.3 KiB
Haskell

module CLI.RefChan where
import HBS2.Prelude.Plated
import HBS2.Net.Auth.Credentials
import HBS2.Net.Proto.Definition()
import HBS2.Net.Proto.RefChan
import HBS2.Net.Proto.Types
import HBS2.Net.Messaging.Unix
import HBS2.Data.Types.SignedBox
import HBS2.OrDie
-- FIXME: to-remove-old-rpc
import RPC2
import RPC2.API
import RPC2.Service.Unix
import Options.Applicative
import Data.ByteString qualified as BS
import Data.ByteString.Lazy qualified as LBS
import Lens.Micro.Platform
import Codec.Serialise
import Data.Maybe
import System.Exit
pRefChan :: Parser (IO ())
pRefChan = hsubparser ( command "head" (info pRefChanHead (progDesc "head commands" ))
<> command "propose" (info pRefChanPropose (progDesc "post propose transaction"))
<> command "notify" (info pRefChanNotify (progDesc "post notify message"))
<> command "fetch" (info pRefChanFetch (progDesc "fetch and sync refchan value"))
<> command "get" (info pRefChanGet (progDesc "get refchan value"))
)
pRefChanHead :: Parser (IO ())
pRefChanHead = hsubparser ( command "gen" (info pRefChanHeadGen (progDesc "generate head blob"))
<> command "dump" (info pRefChanHeadDump (progDesc "dump head blob"))
<> command "post" (info pRefChanHeadPost (progDesc "post head transaction"))
<> command "fetch" (info pRefChanHeadFetch (progDesc "fetch head from neighbours"))
<> command "get" (info pRefChanHeadGet (progDesc "get head value"))
)
pRefChanHeadGen :: Parser (IO ())
pRefChanHeadGen = do
kr <- strOption (long "keyring" <> short 'k' <> help "owner credentials")
fn <- optional $ strArgument (metavar "head dsl file")
pure $ do
sc <- BS.readFile kr
creds <- pure (parseCredentials @(Encryption L4Proto) (AsCredFile sc)) `orDie` "bad keyring file"
s <- maybe1 fn getContents readFile
hd <- pure (fromStringMay @(RefChanHeadBlock L4Proto) s) `orDie` "can't generate head block"
let qq = makeSignedBox @L4Proto @(RefChanHeadBlock L4Proto) (view peerSignPk creds) (view peerSignSk creds) hd
LBS.putStr (serialise qq)
pRefChanHeadDump :: Parser (IO ())
pRefChanHeadDump= do
fn <- optional $ strArgument (metavar "refchan head blob")
pure $ do
lbs <- maybe1 fn LBS.getContents LBS.readFile
(_, hdblk) <- pure (unboxSignedBox @(RefChanHeadBlock L4Proto) @L4Proto lbs) `orDie` "can't unbox signed box"
print $ pretty hdblk
-- FIXME: options-duped-with-peer-main
confOpt :: Parser FilePath
confOpt = strOption ( long "config" <> short 'c' <> help "config" )
rpcOpt :: Parser String
rpcOpt = strOption ( short 'r' <> long "rpc"
<> help "addr:port" )
pRpcCommon :: Parser RPCOpt
pRpcCommon = do
RPCOpt <$> optional confOpt
<*> optional rpcOpt
pRefChanHeadPost :: Parser (IO ())
pRefChanHeadPost = do
opts <- pRpcCommon
ref <- strArgument (metavar "HEAD-BLOCK-TREE-HASH")
pure $ withRPC2 @UNIX opts $ \caller -> do
href <- pure (fromStringMay ref) `orDie` "HEAD-BLOCK-TREE-HASH"
-- FIXME: proper-error-handling
void $ callService @RpcRefChanHeadPost caller href
pRefChanHeadFetch :: Parser (IO ())
pRefChanHeadFetch = do
opts <- pRpcCommon
ref <- strArgument (metavar "REFCHAH-HEAD-KEY")
pure $ withRPC2 @UNIX opts $ \caller -> do
href <- pure (fromStringMay ref) `orDie` "invalid REFCHAN-HEAD-REF"
void $ callService @RpcRefChanHeadFetch caller href
pRefChanHeadGet :: Parser (IO ())
pRefChanHeadGet = do
rpc <- pRpcCommon
ref <- strArgument (metavar "REFCHAH-HEAD-KEY")
pure $ withRPC2 @UNIX rpc $ \caller -> do
href <- pure (fromStringMay ref) `orDie` "invalid REFCHAN-HEAD-REF"
callService @RpcRefChanHeadGet caller href >>= \case
Left{} -> exitFailure
Right Nothing -> exitFailure
Right (Just h) -> print (pretty h) >> exitSuccess
pRefChanPropose :: Parser (IO ())
pRefChanPropose = do
opts <- pRpcCommon
kra <- strOption (long "author" <> short 'a' <> help "author credentials")
fn <- optional $ strOption (long "file" <> short 'f' <> help "file")
dry <- optional (flag' True (long "dry" <> short 'n' <> help "only dump transaction")) <&> fromMaybe False
sref <- strArgument (metavar "REFCHAH-KEY")
pure $ withRPC2 @UNIX opts $ \caller -> do
sc <- BS.readFile kra
puk <- pure (fromStringMay @(RefChanId L4Proto) sref) `orDie` "can't parse refchan/public key"
creds <- pure (parseCredentials @(Encryption L4Proto) (AsCredFile sc)) `orDie` "bad keyring file"
lbs <- maybe1 fn LBS.getContents LBS.readFile
let box = makeSignedBox @L4Proto @BS.ByteString (view peerSignPk creds) (view peerSignSk creds) (LBS.toStrict lbs)
if dry then do
LBS.putStr (serialise box)
else do
-- FIXME: proper-error-handling
void $ callService @RpcRefChanPropose caller (puk, box)
pRefChanNotify :: Parser (IO ())
pRefChanNotify = do
opts <- pRpcCommon
kra <- strOption (long "author" <> short 'a' <> help "author credentials")
fn <- optional $ strOption (long "file" <> short 'f' <> help "file")
sref <- strArgument (metavar "REFCHAH-REF")
pure $ withRPC2 @UNIX opts $ \caller -> do
sc <- BS.readFile kra
puk <- pure (fromStringMay @(RefChanId L4Proto) sref) `orDie` "can't parse refchan/public key"
creds <- pure (parseCredentials @(Encryption L4Proto) (AsCredFile sc)) `orDie` "bad keyring file"
lbs <- maybe1 fn LBS.getContents LBS.readFile
let box = makeSignedBox @L4Proto @BS.ByteString (view peerSignPk creds) (view peerSignSk creds) (LBS.toStrict lbs)
void $ callService @RpcRefChanNotify caller (puk, box)
pRefChanGet :: Parser (IO ())
pRefChanGet = do
opts <- pRpcCommon
sref <- strArgument (metavar "REFCHAH-KEY")
pure $ withRPC2 @UNIX opts $ \caller -> do
puk <- pure (fromStringMay @(RefChanId L4Proto) sref) `orDie` "can't parse refchan/public key"
callService @RpcRefChanGet caller puk >>= \case
Left{} -> exitFailure
Right Nothing -> exitFailure
Right (Just h) -> print (pretty h) >> exitSuccess
pRefChanFetch :: Parser (IO ())
pRefChanFetch = do
opts <- pRpcCommon
ref <- strArgument (metavar "REFCHAH-KEY")
pure $ withRPC2 @UNIX opts $ \caller -> do
href <- pure (fromStringMay ref) `orDie` "invalid REFCHAN-HEAD-REF"
void $ callService @RpcRefChanFetch caller href