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

Async nameservice interact #179

Merged
merged 35 commits into from
Jan 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
243d621
Init hs-abci-test-utils
IvantheTricourne Dec 12, 2019
2b4f8f2
import packages and use correct default extensions
IvantheTricourne Dec 12, 2019
f66e856
use directory module hierarchy
IvantheTricourne Dec 12, 2019
2a6b3c3
update project files with new utils lib
IvantheTricourne Dec 12, 2019
5eca207
nameservice tests passing
IvantheTricourne Dec 12, 2019
b1e7680
use utils in ss
IvantheTricourne Dec 12, 2019
ffa8c9a
use new user module in nameservice tests
IvantheTricourne Dec 12, 2019
7c00708
delete special msg encoder
IvantheTricourne Dec 12, 2019
12d2319
use user util module in simple storage tests
IvantheTricourne Dec 13, 2019
e17127d
move response checkers to utils library
IvantheTricourne Dec 13, 2019
05bfd1d
move request runners to new request module
IvantheTricourne Dec 13, 2019
e04471e
Update readme
IvantheTricourne Dec 16, 2019
74b2788
Merge branch 'master' of github.com:f-o-a-m/hs-abci into hs-abci-test…
IvantheTricourne Jan 2, 2020
776d1ed
Add interact exe to nameservice
IvantheTricourne Jan 2, 2020
04270a7
Add basic main for interact
IvantheTricourne Jan 2, 2020
298656f
add random name generator
IvantheTricourne Jan 2, 2020
eba7e74
Clean up action type signatures
IvantheTricourne Jan 2, 2020
d4b0713
Async actionBlock
IvantheTricourne Jan 6, 2020
aaf03e2
Merge branch 'master' of github.com:f-o-a-m/hs-abci into async-namese…
IvantheTricourne Jan 6, 2020
38822b3
unused
IvantheTricourne Jan 6, 2020
19174c7
unused from merge
IvantheTricourne Jan 6, 2020
a3dbb8f
kind of works
IvantheTricourne Jan 6, 2020
77799c5
fix concurrency
IvantheTricourne Jan 6, 2020
6816106
WIP
IvantheTricourne Jan 7, 2020
38ad832
Merge branch 'master' of github.com:f-o-a-m/hs-abci into async-namese…
IvantheTricourne Jan 13, 2020
1ecf3fa
Merge branch 'master' of github.com:f-o-a-m/hs-abci into async-namese…
IvantheTricourne Jan 14, 2020
25d75f8
Fix actions + lower default concurrency var value
IvantheTricourne Jan 14, 2020
14d4c0f
Off by one error: allow transfer to 0 an account
IvantheTricourne Jan 15, 2020
ccd357b
Update script to generate random users for each thread
IvantheTricourne Jan 15, 2020
2dc1d34
Merge branch 'master' of github.com:f-o-a-m/hs-abci into async-namese…
IvantheTricourne Jan 27, 2020
1c65af4
wip: compile with master changes
IvantheTricourne Jan 27, 2020
63572a3
buyName
IvantheTricourne Jan 27, 2020
4e5c3a1
createName
IvantheTricourne Jan 27, 2020
39ef3aa
deleteName
IvantheTricourne Jan 27, 2020
a317a17
Works again
IvantheTricourne Jan 27, 2020
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
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
STATS_PORT ?= 9200
INTERACT_THREAD_COUNT ?= 5

export

Expand Down Expand Up @@ -84,6 +85,10 @@ test-simple-storage: install ## Run the test suite for the simple-storage exampl
test-nameservice: install ## Run the test suite for the nameservice example application
stack test nameservice:nameservice-test

interact-nameservice: install ## Run nameservice interaction script
INTERACT_THREAD_COUNT=$(INTERACT_THREAD_COUNT) \
stack exec interact

test-tutorial: install ## Make sure the tutorial builds
stack test nameservice:tutorial

Expand Down
193 changes: 193 additions & 0 deletions hs-abci-examples/nameservice/interact/Interact.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
module Interact
( actionBlock
, makeRandomUsers
) where

import Control.Monad (replicateM, void)
import Control.Monad.Reader (ReaderT, runReaderT)
import Data.Char (isHexDigit)
import Data.Default.Class (def)
import Data.Proxy
import Data.String (fromString)
import Data.String.Conversions (cs)
import Data.Text (Text)
import qualified Faker.Lorem as Lorem
import qualified Faker.Name as Name
import qualified Faker.Utils as Utils
import Nameservice.Application
import qualified Nameservice.Modules.Nameservice as N
import qualified Nameservice.Modules.Token as T
import qualified Network.Tendermint.Client as RPC
import Servant.API ((:<|>) (..))
import Tendermint.SDK.Application.Module (AppQueryRouter (QApi),
AppTxRouter (TApi))
import Tendermint.SDK.BaseApp.Errors (AppError (..))
import Tendermint.SDK.BaseApp.Query (QueryArgs (..),
QueryResult (..))
import qualified Tendermint.SDK.Modules.Auth as Auth
import Tendermint.SDK.Types.Address (Address)
import Tendermint.Utils.Client (ClientConfig (..),
EmptyTxClient (..),
HasQueryClient (..),
HasTxClient (..),
QueryClientResponse (..),
Signer (..),
TxClientResponse (..),
TxOpts (..),
defaultClientTxOpts)
import Tendermint.Utils.ClientUtils (assertTx, rpcConfig)
import Tendermint.Utils.User (makeSignerFromUser,
makeUser)
import Test.RandomStrings (onlyWith, randomASCII,
randomString)

--------------------------------------------------------------------------------
-- Actions
--------------------------------------------------------------------------------

faucetAccount :: Signer -> T.Amount -> IO ()
faucetAccount s@(Signer addr _) amount =
runAction_ s faucet $ T.FaucetAccount addr amount

createName :: Signer -> N.Name -> Text -> IO ()
createName s name val = buyName s name val 0

buyName :: Signer -> N.Name -> Text -> T.Amount -> IO ()
buyName s@(Signer addr _) name newVal amount =
runAction_ s buy $ N.BuyName amount name newVal addr

deleteName :: Signer -> N.Name -> IO ()
deleteName s@(Signer addr _) name =
runAction_ s delete $ N.DeleteName addr name

setName :: Signer -> N.Name -> Text -> IO ()
setName s@(Signer addr _) name val =
runAction_ s set $ N.SetName name addr val

runAction_
:: Signer
-> (TxOpts -> msg -> TxClientM (TxClientResponse () ()))
-> msg
-> IO ()
runAction_ s f = void . assertTx . runTxClientM . f (TxOpts 0 s)

actionBlock :: (Signer, Signer) -> IO ()
actionBlock (s1, s2) = do
name <- genName
genCVal <- genWords
genBVal <- genWords
genBAmt <- genAmount
genSVal <- genWords
faucetAccount s2 genBAmt
createName s1 name genCVal
buyName s2 name genBVal genBAmt
setName s2 name genSVal
deleteName s2 name

--------------------------------------------------------------------------------
-- Users
--------------------------------------------------------------------------------

makeRandomUsers :: IO (Signer, Signer)
makeRandomUsers = do
str1 <- randomString (onlyWith isHexDigit randomASCII) 64
str2 <- randomString (onlyWith isHexDigit randomASCII) 64
return $ (makeSignerFromUser . makeUser $ str1
,makeSignerFromUser . makeUser $ str2
)

--------------------------------------------------------------------------------
-- Query Client
--------------------------------------------------------------------------------

getAccount
:: QueryArgs Address
-> RPC.TendermintM (QueryClientResponse Auth.Account)

_ :<|> _ :<|> getAccount =
genClientQ (Proxy :: Proxy m) queryApiP def
where
queryApiP :: Proxy (QApi NameserviceModules)
queryApiP = Proxy

--------------------------------------------------------------------------------
-- Tx Client
--------------------------------------------------------------------------------

txClientConfig :: ClientConfig
txClientConfig =
let getNonce addr = do
resp <- RPC.runTendermintM rpcConfig $ getAccount $
QueryArgs
{ queryArgsHeight = -1
, queryArgsProve = False
, queryArgsData = addr
}
case resp of
QueryError e ->
if appErrorCode e == 2
then pure 0
else error $ "Unknown nonce error: " <> show (appErrorMessage e)
QueryResponse QueryResult {queryResultData} ->
pure $ Auth.accountNonce queryResultData

in ClientConfig
{ clientGetNonce = getNonce
, clientRPC = rpcConfig
}

type TxClientM = ReaderT ClientConfig IO

runTxClientM :: TxClientM a -> IO a
runTxClientM m = runReaderT m txClientConfig

-- Nameservice Client
buy
:: TxOpts
-> N.BuyName
-> TxClientM (TxClientResponse () ())

set
:: TxOpts
-> N.SetName
-> TxClientM (TxClientResponse () ())

delete
:: TxOpts
-> N.DeleteName
-> TxClientM (TxClientResponse () ())

-- Token Client
faucet
:: TxOpts
-> T.FaucetAccount
-> TxClientM (TxClientResponse () ())

(buy :<|> set :<|> delete) :<|>
(_ :<|> _ :<|> faucet) :<|>
EmptyTxClient =
genClientT (Proxy @TxClientM) txApiP defaultClientTxOpts
where
txApiP :: Proxy (TApi NameserviceModules)
txApiP = Proxy


--------------------------------------------------------------------------------
-- Generation
--------------------------------------------------------------------------------

genWords :: IO Text
genWords = do
numWords <- Utils.randomNum (1, 10)
ws <- replicateM numWords Lorem.word
return . cs . unwords $ ws

genName :: IO N.Name
genName = do
name <- Name.name
return . fromString $ name

genAmount :: IO T.Amount
genAmount = do
genAmt <- Utils.randomNum (1, 1000)
return . fromInteger . toInteger $ genAmt
17 changes: 17 additions & 0 deletions hs-abci-examples/nameservice/interact/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module Main where

import Control.Concurrent.Async (forConcurrently_)
import Control.Monad (forever, replicateM)
import Data.Maybe (maybe)
import Interact
import System.Environment (lookupEnv)
import Text.Read (read)

main :: IO ()
main = do
mThreads <- lookupEnv "INTERACT_THREAD_COUNT"
let threads = maybe 1 read mThreads :: Int
usersForThreads <- replicateM threads makeRandomUsers
putStrLn $ "Running nameservice interaction with #threads: " <> show threads
forever $ forConcurrently_ [0..(threads-1)] $ \i ->
actionBlock $ usersForThreads !! i
24 changes: 24 additions & 0 deletions hs-abci-examples/nameservice/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,30 @@ executables:
- proto3-suite
- proto3-wire

interact:
main: Main.hs
source-dirs: interact
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
- -Werror
- -Wall
dependencies:
- async
- base
- data-default-class
- faker
- mtl
- nameservice
- hs-abci-sdk
- hs-abci-test-utils
- hs-tendermint-client
- random-strings
- servant
- string-conversions
- text

tests:
tutorial:
main: README.lhs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module Nameservice.Modules.Nameservice.Types where
import Control.Lens (iso)
import Data.Aeson as A
import Data.Bifunctor (first)
import Data.String (IsString (..))
import Data.String.Conversions (cs)
import Data.Text (Text)
import qualified Data.Text.Lazy as TL
Expand Down Expand Up @@ -33,6 +34,8 @@ instance Primitive Name where
primType _ = DotProto.String
instance HasDefault Name
instance MessageField Name
instance IsString Name where
fromString = Name . fromString

instance BaseApp.FromQueryData Name

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ transfer
transfer addr1 amount addr2 = do
-- check if addr1 has amt
addr1Bal <- getBalance addr1
if addr1Bal > amount
if addr1Bal >= amount
then do
addr2Bal <- getBalance addr2
let newBalance1 = addr1Bal - amount
Expand Down
4 changes: 4 additions & 0 deletions stack.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ packages:
- ./hs-iavl-client

extra-deps:
- async-2.2.2
- faker-0.0.0.2
- gimlh-0.1.3.0
- random-strings-0.1.1.0
- proto-lens-runtime-0.5.0.0
- proto-lens-setup-0.4.0.2
- lens-labels-0.3.0.1
Expand Down
28 changes: 28 additions & 0 deletions stack.yaml.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,34 @@
# https://docs.haskellstack.org/en/stable/lock_files

packages:
- completed:
hackage: async-2.2.2@sha256:ed46f0f5be36cf8a3e3aebc6827d015e1f3bf9615c245e057b9e9bd35faddd21,2895
pantry-tree:
size: 501
sha256: dab5a4c2126fbce3f4a7c15ccf66e60de61d3eccae071f4bfbad036087399f32
original:
hackage: async-2.2.2
- completed:
hackage: faker-0.0.0.2@sha256:e181a9dba8022098d2cca9822b6a616a28d3013ee978076b7c7cd18b6e15c8eb,980
pantry-tree:
size: 792
sha256: d1fd5fcf4175f259b84f9036ab8d53d23457eb1ab9eab163dce83e8a8d7fca65
original:
hackage: faker-0.0.0.2
- completed:
hackage: gimlh-0.1.3.0@sha256:0cb3513ec36b7f935956b68875de40a05e934cf75499918e1db533b7d32dfc46,747
pantry-tree:
size: 201
sha256: 106e63ee076f0339ae5e15c599f5eb15d1e663f1f2303417000f26c9514f24c6
original:
hackage: gimlh-0.1.3.0
- completed:
hackage: random-strings-0.1.1.0@sha256:935a7a23dab45411960df77636a29b44ce42b89eeb15f2b1e809d771491fa677,2517
pantry-tree:
size: 663
sha256: 5a382966fdd8d5220b5791f3bff6db00d2ea29235e2716dadd52461b8a8beb97
original:
hackage: random-strings-0.1.1.0
- completed:
hackage: proto-lens-runtime-0.5.0.0@sha256:cb39cf13ce4f7dac5414f94a7afe0adc9b831312e6b60588a23bd816accc385f,3132
pantry-tree:
Expand Down