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

go-kosu: RPC numberPosters and totalOrders #224

Merged
merged 3 commits into from Aug 22, 2019
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -54,7 +54,7 @@ func NewAppWithConfig(db db.DB, cfg *config.Config) *App {
}

app := &App{
store: cosmos.NewStore(db, new(cosmos.ProtoCodec)),
store: cosmos.NewStore(db, store.DefaultCodec),
Config: cfg,
log: logger.With("module", "app"),
}
@@ -4,13 +4,13 @@ import (
"context"
"errors"

"github.com/gogo/protobuf/proto"
"github.com/tendermint/tendermint/libs/pubsub/query"
"github.com/tendermint/tendermint/rpc/client"
rpctypes "github.com/tendermint/tendermint/rpc/core/types"
tmtypes "github.com/tendermint/tendermint/types"

"go-kosu/abci/types"
"go-kosu/store"
)

var (
@@ -23,12 +23,13 @@ var (
type Client struct {
client.Client
key []byte
cdc store.Codec
}

// NewClient returns a new Client type.
// Key is the private key used to sign transactions.
func NewClient(c client.Client, key []byte) *Client {
return &Client{Client: c, key: key}
return &Client{Client: c, key: key, cdc: store.DefaultCodec}
}

// NewHTTPClient calls NewClient using a HTTPClient as ABCClient
@@ -121,7 +122,7 @@ func (c *Client) Unsubscribe(ctx context.Context, query string) error {
// QueryRoundInfo performs a ABCIQuery to "/roundinfo"
func (c *Client) QueryRoundInfo() (*types.RoundInfo, error) {
var pb types.RoundInfo
if err := c.query("/chain/key", []byte("roundinfo"), &pb); err != nil {
if err := c.Query("/chain/key", []byte("roundinfo"), &pb); err != nil {
return nil, err
}

@@ -131,7 +132,7 @@ func (c *Client) QueryRoundInfo() (*types.RoundInfo, error) {
// QueryConsensusParams performs a ABCI Query to "/consensusparams"
func (c *Client) QueryConsensusParams() (*types.ConsensusParams, error) {
var pb types.ConsensusParams
if err := c.query("/chain/key", []byte("consensusparams"), &pb); err != nil {
if err := c.Query("/chain/key", []byte("consensusparams"), &pb); err != nil {
return nil, err
}

@@ -141,7 +142,7 @@ func (c *Client) QueryConsensusParams() (*types.ConsensusParams, error) {
// QueryPoster performs a ABCI Query to "/posters/<addr>"
func (c *Client) QueryPoster(addr string) (*types.Poster, error) {
var pb types.Poster
if err := c.query("/poster/key", []byte(addr), &pb); err != nil {
if err := c.Query("/poster/key", []byte(addr), &pb); err != nil {
return nil, err
}

@@ -151,14 +152,26 @@ func (c *Client) QueryPoster(addr string) (*types.Poster, error) {
// QueryValidator performs a ABCI Query to "/validator/<addr>"
func (c *Client) QueryValidator(addr string) (*types.Validator, error) {
var pb types.Validator
if err := c.query("/validator/key", []byte(addr), &pb); err != nil {
if err := c.Query("/validator/key", []byte(addr), &pb); err != nil {
return nil, err
}

return &pb, nil
}

func (c *Client) query(path string, data []byte, pb proto.Message) error {
// QueryTotalOrders performs a ABCI Query to "/chain/totalorders"
func (c *Client) QueryTotalOrders() (uint64, error) {
var num uint64
if err := c.Query("/chain/key", []byte("totalorders"), &num); err != nil {
return 0, err
}

return num, nil
}

// Query is a generic query interface.
// It will use the store.DefaultCodec codec to decode the `response.Value`.
func (c *Client) Query(path string, data []byte, v interface{}) error {
out, err := c.ABCIQuery(path, data)
if err != nil {
return err
@@ -173,5 +186,5 @@ func (c *Client) query(path string, data []byte, pb proto.Message) error {
return ErrNotFound
}

return proto.Unmarshal(res.Value, pb)
return c.cdc.Decode(res.Value, v)
}
@@ -62,6 +62,9 @@ func (app *App) deliverOrderTx(tx *types.TransactionOrder) abci.ResponseDeliverT
// begin state modification
poster.Limit--
app.store.SetPoster(posterAddress.String(), *poster)

total := app.store.TotalOrders()
app.store.SetTotalOrders(total + 1)
// end state modification

return abci.ResponseDeliverTx{
@@ -129,6 +129,16 @@ curl -X POST --data '{"jsonrpc":"2.0","method":"kosu_latestHeight", "id": 1}' lo
{ "jsonrpc": "2.0", "id": 1, "result": 260 }
```

### _NumberPosters_

NumberPosters returns the number of poster accounts

_Parameters:_

_Returns:_

- `number` - _uint64_

### _QueryPoster_

QueryPoster returns a poster given its address.
@@ -199,6 +209,16 @@ curl -X POST localhost:14341 \
}
```

### _RemainingLimit_

RemainingLimit returns the sum of all the poster's limit.

_Parameters:_

_Returns:_

- `number` - _uint64_

### _RoundInfo_

RoundInfo returns the current `RoundInfo`.
@@ -224,6 +244,17 @@ curl -X POST localhost:14341 \
{ "jsonrpc": "2.0", "id": 1, "result": { "number": 48, "starts_at": 2613, "ends_at": 2623, "limit": 10 } }
```

### _TotalOrders_

TotalOrders returns the total number of orders in the system.
This number is incremented each time one submits a new valid order

_Parameters:_

_Returns:_

- `number` - _uint64_

### _Validators_

Validators returns the full validator set
@@ -16,62 +16,62 @@ import (
"github.com/tendermint/tendermint/libs/db"
)

func newServerClient(t *testing.T) (*abci.App, *rpc.Client, func()) {
app, closer := tests.StartServer(t, db.NewMemDB())
appClient, err := app.NewClient()
func waitForNewBlock(t *testing.T, client *rpc.Client) {
ch := make(chan interface{})
defer close(ch)

sub, err := client.Subscribe(context.Background(), "kosu", ch, "newBlocks")
require.NoError(t, err)
client := rpc.DialInProc(
NewServer(appClient),
)
defer sub.Unsubscribe()

return app, client, closer
select {
case err := <-sub.Err():
t.Error(err)
case <-ch:
}
}

func TestRPCLatestHeight(t *testing.T) {
_, closer := tests.StartServer(t, db.NewMemDB())
defer closer()
client := rpc.DialInProc(
NewServer(
abci.NewHTTPClient("http://localhost:26657", nil),
),
)

var latest uint64
// Get the initial (prior the first block is mined)
require.NoError(t, client.Call(&latest, "kosu_latestHeight"))
assert.EqualValues(t, 0, latest)

ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
fn := func(_ interface{}) {
// this is invoked when a block is mined
require.NoError(t, client.Call(&latest, "kosu_latestHeight"))
assert.EqualValues(t, 1, latest)
cancel()
func TestRPC(t *testing.T) {
cases := []struct {
name string
run func(*testing.T, *abci.App, *abci.Client, *rpc.Client)
}{
{"LatestHeight", LatestHeight},
{"AddOrders", AddOrders},
{"RebalancePeriod", RebalancePeriod},
{"NewRebalances", NewRebalances},
{"NumberPosters", NumberPosters},
}

ch := make(chan interface{})
defer close(ch)
for _, test := range cases {
t.Run(test.name, func(t *testing.T) {
app, closer := tests.StartServer(t, db.NewMemDB())
defer closer()

sub, err := client.Subscribe(ctx, "kosu", ch, "newBlocks")
defer sub.Unsubscribe()
require.NoError(t, err)
appClient, err := app.NewClient()
require.NoError(t, err)
defer appClient.Stop() // nolint:errcheck

rpcClient := rpc.DialInProc(NewServer(appClient))
defer rpcClient.Close()

for {
select {
case <-ctx.Done():
return
case err := <-sub.Err():
t.Error(err)
case e := <-ch:
fn(e)
}
test.run(t, app, appClient, rpcClient)
})
}
}

func TestAddOrders(t *testing.T) {
app, client, closer := newServerClient(t)
defer closer()
func LatestHeight(t *testing.T, _ *abci.App, _ *abci.Client, rpcClient *rpc.Client) {
var latest uint64
// Get the initial (prior the first block is mined)
require.NoError(t, rpcClient.Call(&latest, "kosu_latestHeight"))
assert.EqualValues(t, 0, latest)

waitForNewBlock(t, rpcClient)
require.NoError(t, rpcClient.Call(&latest, "kosu_latestHeight"))
assert.EqualValues(t, 1, latest)
}

func AddOrders(t *testing.T, app *abci.App, appClient *abci.Client, rpcClient *rpc.Client) {
// nolint:lll
validTx := &types.TransactionOrder{
SubContract: "0xebe8fdf63db77e3b41b0aec8208c49fa46569606",
@@ -87,18 +87,35 @@ func TestAddOrders(t *testing.T) {
}

// this poster address is generated out of the validTx
app.Store().SetPoster("0x02fbf1aa49bc3b9631e8e96572935a5894879724", types.Poster{
poster := types.Poster{
Balance: types.NewBigIntFromInt(100),
})
Limit: 10,
}
app.Store().SetPoster("0x02fbf1aa49bc3b9631e8e96572935a5894879724", poster)

var remaining uint64
err := rpcClient.Call(&remaining, "kosu_remainingLimit")
require.NoError(t, err)
assert.Equal(t, poster.Limit, remaining)

params := []interface{}{validTx, invalidTx}
result := &AddOrdersResult{}

err := client.Call(result, "kosu_addOrders", params)
err = rpcClient.Call(result, "kosu_addOrders", params)
require.NoError(t, err)

assert.Len(t, result.Accepted, 1)
assert.Len(t, result.Rejected, 1)

waitForNewBlock(t, rpcClient)
var total uint64
err = rpcClient.Call(&total, "kosu_totalOrders")
require.NoError(t, err)
assert.EqualValues(t, 1, total)

err = rpcClient.Call(&remaining, "kosu_remainingLimit")
require.NoError(t, err)
assert.Equal(t, poster.Limit-1, remaining)
}

func newTestRebalanceTx(number, starts uint64) *types.TransactionRebalance {
@@ -111,42 +128,33 @@ func newTestRebalanceTx(number, starts uint64) *types.TransactionRebalance {
}
}

func TestRebalancePeriod(t *testing.T) {
app, rpc, closer := newServerClient(t)
defer closer()

client, err := app.NewClient()
require.NoError(t, err)

func RebalancePeriod(t *testing.T, _ *abci.App, appClient *abci.Client, rpcClient *rpc.Client) {
tx := newTestRebalanceTx(1, 10)
res, err := client.BroadcastTxCommit(tx)
res, err := appClient.BroadcastTxCommit(tx)
require.NoError(t, err)
require.True(t, res.DeliverTx.IsOK())

var result types.RoundInfo
require.NoError(t,
rpc.Call(&result, "kosu_roundInfo"),
rpcClient.Call(&result, "kosu_roundInfo"),
)

assert.Equal(t, tx.RoundInfo.String(), result.String())
}

func TestNewRebalances(t *testing.T) {
app, rpc, closer := newServerClient(t)
defer closer()

func NewRebalances(t *testing.T, app *abci.App, appClient *abci.Client, rpcClient *rpc.Client) {
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
defer cancel()

ch := make(chan *types.TransactionRebalance)
sub, err := rpc.Subscribe(ctx, "kosu", ch, "newRebalances")
sub, err := rpcClient.Subscribe(ctx, "kosu", ch, "newRebalances")
require.NoError(t, err)
defer sub.Unsubscribe()

client, err := app.NewClient()
require.NoError(t, err)

tx := newTestRebalanceTx(1, 10)
res, err := client.BroadcastTxSync(tx)
res, err := appClient.BroadcastTxSync(tx)
require.NoError(t, err)
require.Zero(t, res.Code, res.Log)

@@ -159,3 +167,24 @@ func TestNewRebalances(t *testing.T) {
assert.Equal(t, tx.String(), e.String())
}
}

func NumberPosters(t *testing.T, app *abci.App, _ *abci.Client, rpcClient *rpc.Client) {
addresses := []string{
"0x0000000000000000000000000000000000000001",
"0x0000000000000000000000000000000000000002",
"0x0000000000000000000000000000000000000003",
"0x0000000000000000000000000000000000000004",
}

for _, addr := range addresses {
app.Store().SetPoster(addr, types.Poster{
Balance: types.NewBigIntFromInt(100),
})
}

var num uint64
err := rpcClient.Call(&num, "kosu_numberPosters")
require.NoError(t, err)

assert.EqualValues(t, len(addresses), num)
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.