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

[Gateway] Implement StakeGateway Message and Add Tests #68

Merged
merged 24 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
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
10 changes: 5 additions & 5 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ jobs:
- name: Install CI dependencies
h5law marked this conversation as resolved.
Show resolved Hide resolved
run: make install_ci_deps

- name: Build
run: ignite chain build --debug --skip-proto
- name: Generate protobufs
run: make proto_regen

- name: Mockgen
- name: Generate mocks
run: make go_mockgen

- name: Mockgen
run: make go_mockgen
- name: Build
run: ignite chain build --debug --skip-proto

- name: Test
run: make go_test
61 changes: 57 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,12 @@ go_test: go_version_check ## Run all go tests

.PHONY: go_mockgen
go_mockgen: ## Use `mockgen` to generate mocks used for testing purposes of all the modules.
go generate ./x/application/types/
go generate ./x/gateway/types/

.PHONY: go_develop
go_develop: proto_regen go_mockgen go_test ## Generate protos, mocks and run all tests

.PHONY: install_ci_deps
install_ci_deps: ## Installs the tools necessary for CI
go install "github.com/golang/mock/[email protected]" && mockgen --version

#############
### TODOS ###
#############
Expand Down Expand Up @@ -206,3 +203,59 @@ gateway2_stake: ## Stake gateway2
.PHONY: gateway3_stake
gateway3_stake: ## Stake gateway3
gateway=gateway3 make gateway_stake

####################
### Applications ###
####################

.PHONY: app_list
app_list: ## List all the staked applications
pocketd --home=$(POCKETD_HOME) q application list-application --node $(POCKET_NODE)

.PHONY: app_stake
app_stake: ## Stake tokens for the application specified (must specify the APP env var)
pocketd --home=$(POCKETD_HOME) tx application stake-application 1000upokt --keyring-backend test --from $(APP) --node $(POCKET_NODE)

.PHONY: app1_stake
app1_stake: ## Stake app1
APP=app1 make app_stake

.PHONY: app2_stake
app2_stake: ## Stake app2
APP=app2 make app_stake

.PHONY: app3_stake
app3_stake: ## Stake app3
APP=app3 make app_stake

################
### Accounts ###
################

.PHONY: acc_balance_query
acc_balance_query: ## Query the balance of the account specified (make acc_balance_query ACC=pokt...)
@echo "~~~ Balances ~~~"
pocketd --home=$(POCKETD_HOME) q bank balances $(ACC) --node $(POCKET_NODE)
@echo "~~~ Spendable Balances ~~~"
@echo "Querying spendable balance for $(ACC)"
pocketd --home=$(POCKETD_HOME) q bank spendable-balances $(ACC) --node $(POCKET_NODE)

.PHONY: acc_balance_query_app_module
acc_balance_query_app_module: ## Query the balance of the network level "application" module
make acc_balance_query ACC=pokt1rl3gjgzexmplmds3tq3r3yk84zlwdl6djzgsvm

.PHONY: acc_balance_query_app1
acc_balance_query_app1: ## Query the balance of app1
make acc_balance_query ACC=pokt1mrqt5f7qh8uxs27cjm9t7v9e74a9vvdnq5jva4

.PHONY: acc_balance_total_supply
acc_balance_total_supply: ## Query the total supply of the network
pocketd --home=$(POCKETD_HOME) q bank total --node $(POCKET_NODE)

######################
### Ignite Helpers ###
######################

.PHONY: ignite_acc_list
ignite_acc_list: ## List all the accounts in LocalNet
ignite account list --keyring-dir=$(POCKETD_HOME) --keyring-backend test --address-prefix $(POCKET_ADDR_PREFIX)
4 changes: 4 additions & 0 deletions cmd/pocketd/cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import (
"pocket/app"
)

// InitSDKConfig initializes the SDK's config with the appropriate parameters
// and prefixes so everything is named appropriately for Pocket Network.
// TODO_DISCUSS: Exporting publically for testing purposes only.
// Consider adding a helper per the discussion here: https://github.com/pokt-network/poktroll/pull/59#discussion_r1357816798
func InitSDKConfig() {
// Set prefixes
accountPubKeyPrefix := app.AccountAddressPrefix + "pub"
Expand Down
2 changes: 0 additions & 2 deletions cmd/pocketd/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/pflag"

// this line is used by starport scaffolding # root/moduleImport
h5law marked this conversation as resolved.
Show resolved Hide resolved

"pocket/app"
appparams "pocket/app/params"
)
Expand Down
3 changes: 3 additions & 0 deletions proto/pocket/gateway/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package pocket.gateway;

option go_package = "pocket/x/gateway/types";

import "cosmos/msg/v1/msg.proto";
import "cosmos_proto/cosmos.proto";
import "cosmos/base/v1beta1/coin.proto";

Expand All @@ -13,6 +14,8 @@ service Msg {
rpc UnstakeGateway (MsgUnstakeGateway) returns (MsgUnstakeGatewayResponse);
}
message MsgStakeGateway {
option (cosmos.msg.v1.signer) = "address"; // https://docs.cosmos.network/main/build/building-modules/messages-and-queries

string address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; // The Bech32 address of the gateway
h5law marked this conversation as resolved.
Show resolved Hide resolved
cosmos.base.v1beta1.Coin stake = 2; // The total amount of uPOKT the gateway is staking. Must be ≥ to the current amount that the gateway has staked (if any)
}
Expand Down
34 changes: 22 additions & 12 deletions testutil/network/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package network

import (
"fmt"
"strconv"
"testing"
"time"

Expand All @@ -17,15 +18,15 @@ import (
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
"github.com/cosmos/cosmos-sdk/testutil/network"
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
cosmostypes "github.com/cosmos/cosmos-sdk/types"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/stretchr/testify/require"

"pocket/app"
"pocket/testutil/nullify"
"pocket/testutil/sample"
"pocket/x/application/types"
app_types "pocket/x/application/types"
gateway_types "pocket/x/gateway/types"
)

type (
Expand Down Expand Up @@ -98,14 +99,14 @@ func DefaultConfig() network.Config {
}
}

// applicationModuleGenesis generates a GenesisState object with a given number of applications.
// DefaultApplicationModuleGenesisState generates a GenesisState object with a given number of applications.
// It returns the populated GenesisState object.
func DefaultApplicationModuleGenesisState(t *testing.T, n int) *types.GenesisState {
func DefaultApplicationModuleGenesisState(t *testing.T, n int) *app_types.GenesisState {
t.Helper()
state := types.DefaultGenesis()
state := app_types.DefaultGenesis()
for i := 0; i < n; i++ {
stake := sdk.NewCoin("upokt", sdk.NewInt(int64(i+1)))
application := types.Application{
application := app_types.Application{
Address: sample.AccAddress(),
Stake: &stake,
}
Expand All @@ -115,16 +116,25 @@ func DefaultApplicationModuleGenesisState(t *testing.T, n int) *types.GenesisSta
return state
}

// HydrateGenesisState adds a given module's GenesisState to the network's genesis state.
func HydrateGenesisState(t *testing.T, cfg *network.Config, moduleGenesisState *types.GenesisState, moduleName string) {
// DefaultGatewayModuleGenesisState generates a GenesisState object with a given number of gateways.
// It returns the populated GenesisState object.
func DefaultGatewayModuleGenesisState(t *testing.T, n int) *gateway_types.GenesisState {
t.Helper()
buf, err := cfg.Codec.MarshalJSON(moduleGenesisState)
require.NoError(t, err)
cfg.GenesisState[moduleName] = buf
state := gateway_types.DefaultGenesis()
for i := 0; i < n; i++ {
stake := sdk.NewCoin("upokt", sdk.NewInt(int64(i)))
gateway := gateway_types.Gateway{
Address: strconv.Itoa(i),
Stake: &stake,
}
nullify.Fill(&gateway)
state.GatewayList = append(state.GatewayList, gateway)
}
return state
}

// Initialize an Account by sending it some funds from the validator in the network to the address provided
func InitAccount(t *testing.T, net *Network, addr cosmostypes.AccAddress) {
func InitAccount(t *testing.T, net *Network, addr sdk.AccAddress) {
t.Helper()
val := net.Validators[0]
ctx := val.ClientCtx
Expand Down
6 changes: 5 additions & 1 deletion x/application/client/cli/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"pocket/cmd/pocketd/cmd"
"pocket/testutil/network"
"pocket/x/application/types"

"github.com/stretchr/testify/require"
)

// Dummy variable to avoid unused import error.
Expand All @@ -24,6 +26,8 @@ func networkWithApplicationObjects(t *testing.T, n int) (*network.Network, []typ
t.Helper()
cfg := network.DefaultConfig()
appGenesisState := network.DefaultApplicationModuleGenesisState(t, n)
network.HydrateGenesisState(t, &cfg, appGenesisState, types.ModuleName)
buf, err := cfg.Codec.MarshalJSON(appGenesisState)
h5law marked this conversation as resolved.
Show resolved Hide resolved
require.NoError(t, err)
cfg.GenesisState[types.ModuleName] = buf
return network.New(t, cfg), appGenesisState.ApplicationList
}
27 changes: 3 additions & 24 deletions x/gateway/client/cli/helpers_test.go
Original file line number Diff line number Diff line change
@@ -1,42 +1,21 @@
package cli_test
h5law marked this conversation as resolved.
Show resolved Hide resolved

import (
"strconv"
"testing"

"pocket/testutil/network"
"pocket/testutil/nullify"
"pocket/x/gateway/types"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/stretchr/testify/require"
)

// networkWithGatewayObjects creates a network with a populated gateway state of n gateway objects
func networkWithGatewayObjects(t *testing.T, n int) (*network.Network, []types.Gateway) {
t.Helper()
cfg := network.DefaultConfig()
state := gatewayModuleGenesis(t, n)
buf, err := cfg.Codec.MarshalJSON(state)
gatewayGenesisState := network.DefaultGatewayModuleGenesisState(t, n)
buf, err := cfg.Codec.MarshalJSON(gatewayGenesisState)
require.NoError(t, err)
cfg.GenesisState[types.ModuleName] = buf
return network.New(t, cfg), state.GatewayList
}

// gatewayModuleGenesis generates a default genesis state for the gateway module and then
// populates it with n gateway objects
func gatewayModuleGenesis(t *testing.T, n int) *types.GenesisState {
t.Helper()
state := types.DefaultGenesis()
for i := 0; i < n; i++ {
stake := sdk.NewCoin("upokt", sdk.NewInt(int64(i)))
gateway := types.Gateway{
Address: strconv.Itoa(i),
Stake: &stake,
}
nullify.Fill(&gateway)
state.GatewayList = append(state.GatewayList, gateway)
}
return state
return network.New(t, cfg), gatewayGenesisState.GatewayList
}
14 changes: 9 additions & 5 deletions x/gateway/client/cli/tx_stake_gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,25 @@ var _ = strconv.Itoa(0)
func CmdStakeGateway() *cobra.Command {
cmd := &cobra.Command{
Use: "stake-gateway [amount]",
h5law marked this conversation as resolved.
Show resolved Hide resolved
Short: "Broadcast message stake-gateway",
Args: cobra.ExactArgs(1),
Short: "Stake an gateway",
Long: `Stake an gateway with the provided parameters. This is a broadcast operation that
will stake the tokens and associate them with the gateway specified by the 'from' address.
Example:
$ pocketd --home=$(POCKETD_HOME) tx gateway stake-gateway 1000upokt --keyring-backend test --from $(GATEWAY) --node $(POCKET_NODE)`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) (err error) {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
stakeAmountString := args[0]
stakeAmount, err := sdk.ParseCoinNormalized(stakeAmountString)
stakeString := args[0]
stake, err := sdk.ParseCoinNormalized(stakeString)
if err != nil {
return err
}
msg := types.NewMsgStakeGateway(
clientCtx.GetFromAddress().String(),
stakeAmount,
stake,
)
if err := msg.ValidateBasic(); err != nil {
return err
Expand Down
19 changes: 11 additions & 8 deletions x/gateway/client/cli/tx_stake_gateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"testing"

"pocket/testutil/network"
"pocket/x/gateway/client/cli"
"pocket/x/gateway/types"

Expand Down Expand Up @@ -49,6 +50,12 @@ func TestCLI_StakeGateway(t *testing.T) {
stakeAmount: "1000upokt",
err: types.ErrGatewayInvalidAddress,
},
{
desc: "stake gateway: missing address",
// address: gatewayAccount.Address.String(),
stakeAmount: "1000upokt",
err: types.ErrGatewayInvalidAddress,
},
{
desc: "stake gateway: invalid stake amount (zero)",
address: gatewayAccount.Address.String(),
Expand Down Expand Up @@ -87,13 +94,7 @@ func TestCLI_StakeGateway(t *testing.T) {
}

// Initialize the Gateway Account by sending it some funds from the validator account that is part of genesis
sendArgs := []string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
}
sendArgs = append(sendArgs, commonArgs...)
amount := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(200)))
_, err := clitestutil.MsgSendExec(ctx, net.Validators[0].Address, gatewayAccount.Address, amount, sendArgs...)
require.NoError(t, err)
network.InitAccount(t, net, gatewayAccount.Address)

// Stake the tests
for _, tt := range tests {
Expand All @@ -116,12 +117,14 @@ func TestCLI_StakeGateway(t *testing.T) {
require.Contains(t, stat.Message(), tt.err.Error())
return
}
require.NoError(t, err)

require.NoError(t, err)
var resp sdk.TxResponse
require.NoError(t, net.Config.Codec.UnmarshalJSON(outStake.Bytes(), &resp))
require.NotNil(t, resp)
fmt.Println(resp)
require.NotNil(t, resp.TxHash)
require.Equal(t, uint32(0), resp.Code)
})
}
}
2 changes: 1 addition & 1 deletion x/gateway/keeper/msg_server_stake_gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func (k msgServer) updateGateway(
if msg.Stake == nil {
return errors.Wrapf(types.ErrGatewayInvalidStake, "stake amount cannot be nil")
}
if gateway.Stake.IsGTE(*msg.Stake) {
if msg.Stake.IsLTE(*gateway.Stake) {
return errors.Wrapf(types.ErrGatewayInvalidStake, "stake amount %v must be higher than previous stake amount %v", msg.Stake, gateway.Stake)
}
gateway.Stake = msg.Stake
Expand Down
7 changes: 3 additions & 4 deletions x/gateway/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import "cosmossdk.io/errors"

// x/gateway module sentinel errors
var (
ErrSample = errors.Register(ModuleName, 1100, "sample error")
ErrGatewayInvalidAddress = errors.Register(ModuleName, 1101, "invalid gateway address")
ErrGatewayInvalidStake = errors.Register(ModuleName, 1102, "invalid gateway stake")
ErrGatewayUnauthorized = errors.Register(ModuleName, 1103, "unauthorized signer")
ErrGatewayInvalidAddress = errors.Register(ModuleName, 1, "invalid gateway address")
ErrGatewayInvalidStake = errors.Register(ModuleName, 2, "invalid gateway stake")
ErrGatewayUnauthorized = errors.Register(ModuleName, 3, "unauthorized signer")
)
Loading