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

[On-chain, Relayminer] chore: add claim msg validation #236

Merged
merged 38 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
cebfce1
chore: add testkeyring pkg
bryanchriswhite Nov 30, 2023
586e3a4
chore: update go.mod
bryanchriswhite Nov 29, 2023
825d0c3
refactor: add session keeper dependency to supplier keeper
bryanchriswhite Nov 29, 2023
d9eb488
refactor: add mock session keeper to supplier keeper testutil
bryanchriswhite Nov 29, 2023
0049e3b
refactor: supplier keeper testutil usage
bryanchriswhite Nov 29, 2023
5180140
chore: add claim session validation
bryanchriswhite Nov 29, 2023
4dfe48a
test: claim message validation unit coverage
bryanchriswhite Nov 29, 2023
5721b51
test: e2e session lifecycle
bryanchriswhite Nov 29, 2023
65d92e3
chore: add `ApplicationModuleGenesisStateWithAccounts` testutil
bryanchriswhite Nov 30, 2023
17fb3f1
wip: fix claims show/list tests
bryanchriswhite Nov 30, 2023
91815d1
fix: bug in session supplier hydration
bryanchriswhite Dec 1, 2023
d28c74c
wip: fixing tests
bryanchriswhite Dec 1, 2023
304d51f
wip: fixing tests
bryanchriswhite Dec 1, 2023
d02d5d7
chore: update mock node flag with in-tilt host
bryanchriswhite Dec 1, 2023
d191d39
wip: debugging
bryanchriswhite Dec 1, 2023
51cabc3
wip: debugging
bryanchriswhite Dec 1, 2023
c3926b1
chore: self-review improvements
bryanchriswhite Dec 1, 2023
7814b00
chore: review feedback improvements
bryanchriswhite Dec 4, 2023
79fdefa
chore: add TODO
bryanchriswhite Dec 4, 2023
7c08f69
fixup! chore: update mock node flag with in-tilt host
bryanchriswhite Dec 4, 2023
7ab73a9
chore: review feedback improvements
bryanchriswhite Dec 4, 2023
2361013
chore: review feedback improvements
bryanchriswhite Dec 4, 2023
1142628
wip
bryanchriswhite Dec 4, 2023
aedfb6e
chore: chore: review feedback improvements
bryanchriswhite Dec 4, 2023
9d5f62b
Merge remote-tracking branch 'pokt/main' into issues/140/chore/testke…
bryanchriswhite Dec 4, 2023
a2773c9
Merge branch 'issues/140/chore/testkeyring' into issues/140/chore/cla…
bryanchriswhite Dec 4, 2023
4e25816
fix: post-merge
bryanchriswhite Dec 4, 2023
4508e15
chore: review feedback improvements
bryanchriswhite Dec 4, 2023
a46d196
chore: remove todo
bryanchriswhite Dec 4, 2023
2f5e5ff
chore: self-review improvements
bryanchriswhite Dec 4, 2023
1ce457a
chore: re
bryanchriswhite Dec 5, 2023
b49441c
chore: review feedback improvements
bryanchriswhite Dec 5, 2023
a21ab57
chore: chore: review feedback improvements
bryanchriswhite Dec 5, 2023
b21f843
fix: test
bryanchriswhite Dec 5, 2023
7fa8c07
Merge remote-tracking branch 'pokt/main' into issues/140/chore/testke…
bryanchriswhite Dec 6, 2023
b176b7a
Merge branch 'issues/140/chore/testkeyring' into issues/140/chore/cla…
bryanchriswhite Dec 6, 2023
e58cd33
fix: disambiguate `CometLocalWebsocketURL` & `CometLocalTCPURL`
bryanchriswhite Dec 6, 2023
80e7386
Merge remote-tracking branch 'pokt/main' into issues/140/chore/claim-…
bryanchriswhite Dec 7, 2023
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
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,14 @@ go_mockgen: ## Use `mockgen` to generate mocks used for testing purposes of all
go generate ./pkg/relayer/interface.go
go generate ./pkg/crypto/rings/interface.go

.PHONY: go_fixturegen
go_fixturegen: ## Generate fixture data for unit tests
.PHONY: go_testgen_fixtures
go_testgen_fixtures: ## Generate fixture data for unit tests
go generate ./pkg/relayer/miner/miner_test.go

.PHONY: go_testgen_accounts
go_testgen_accounts: ## Generate test accounts for usage in test environments
go generate ./testutil/testkeyring/keyring.go

.PHONY: go_develop
go_develop: proto_regen go_mockgen ## Generate protos and mocks

Expand Down
1 change: 1 addition & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,7 @@ func New(
)
applicationModule := applicationmodule.NewAppModule(appCodec, app.ApplicationKeeper, app.AccountKeeper, app.BankKeeper)

// TODO_TECHDEBT: Evaluate if this NB goes away after we upgrade to cosmos 0.5x
// NB: there is a circular dependency between the supplier and session keepers.
bryanchriswhite marked this conversation as resolved.
Show resolved Hide resolved
// Because the keepers are values (as opposed to pointers), they are copied
// when passed into their respective module constructor functions. For this
Expand Down
12 changes: 9 additions & 3 deletions e2e/tests/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/stretchr/testify/require"

"github.com/pokt-network/poktroll/app"
"github.com/pokt-network/poktroll/testutil/testclient"
apptypes "github.com/pokt-network/poktroll/x/application/types"
sessiontypes "github.com/pokt-network/poktroll/x/session/types"
sharedtypes "github.com/pokt-network/poktroll/x/shared/types"
Expand Down Expand Up @@ -59,9 +60,10 @@ func TestMain(m *testing.M) {

type suite struct {
gocuke.TestingT
pocketd *pocketdBin
scenarioState map[string]any // temporary state for each scenario
cdc codec.Codec
pocketd *pocketdBin
scenarioState map[string]any // temporary state for each scenario
cdc codec.Codec
supplierQueryClient suppliertypes.QueryClient
}

func (s *suite) Before() {
Expand All @@ -71,6 +73,10 @@ func (s *suite) Before() {
s.buildAddrMap()
s.buildAppMap()
s.buildSupplierMap()

flagSet := testclient.NewLocalnetFlagSet(s)
clientCtx := testclient.NewLocalnetClientCtx(s, flagSet)
s.supplierQueryClient = suppliertypes.NewQueryClient(clientCtx)
}

// TestFeatures runs the e2e tests specified in any .features files in this directory
Expand Down
8 changes: 4 additions & 4 deletions e2e/tests/session.feature
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ Feature: Session Namespace

Scenario: Supplier completes claim/proof lifecycle for a valid session
Given the user has the pocketd binary installed
bryanchriswhite marked this conversation as resolved.
Show resolved Hide resolved
And the supplier "supplier1" has serviced a session of relays for application "app1"
When after the supplier creates a claim for the session
Then the claim created by supplier "supplier1" should be persisted on-chain
# TODO_IN_THIS_COMMIT: ...
When the supplier "supplier1" has serviced a session with "5" relays for service "svc1" for application "app1"
And after the supplier creates a claim for the session for service "svc1" for application "app1"
Then the claim created by supplier "supplier1" for service "svc1" for application "app1" should be persisted on-chain
# TODO_IMPROVE: ...
# And an event should be emitted...
89 changes: 49 additions & 40 deletions e2e/tests/session_steps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import (
"context"
"encoding/json"
"fmt"
"strconv"
"strings"
"time"

"github.com/stretchr/testify/require"

eventsquery "github.com/pokt-network/poktroll/pkg/client/events_query"
"github.com/pokt-network/poktroll/pkg/client/tx"
"github.com/pokt-network/poktroll/pkg/either"
"github.com/pokt-network/poktroll/pkg/observable"
"github.com/pokt-network/poktroll/pkg/observable/channel"
Expand All @@ -22,18 +24,21 @@ import (
const (
createClaimTimeoutDuration = 10 * time.Second
eitherEventsReplayBufferSize = 100
msgClaimSenderQueryFmt = "tm.event='Tx' AND message.sender='%s'"
testServiceId = "anvil"
eitherEventsBzReplayObsKey = "eitherEventsBzReplayObsKey"
preExistingClaimsKey = "preExistingClaimsKey"
)

var (
eitherEventsBzReplayObsKey = "eitherEventsBzReplayObsKey"
supplierAddressKey = "supplierAddressKey"
)

func (s *suite) AfterTheSupplierCreatesAClaimForTheSession() {
func (s *suite) AfterTheSupplierCreatesAClaimForTheSessionForServiceForApplication(serviceId, appName string) {
var ctx, done = context.WithCancel(context.Background())

// TODO_CONSIDERATION: if this test suite gets more complex, it might make
Olshansk marked this conversation as resolved.
Show resolved Hide resolved
// sense to refactor this key into a function that takes serviceId and appName
bryanchriswhite marked this conversation as resolved.
Show resolved Hide resolved
// as arguments and returns the key.
eitherEventsBzReplayObs := s.scenarioState[eitherEventsBzReplayObsKey].(observable.ReplayObservable[either.Bytes])

// TODO(#220): refactor to use EventsReplayClient once available.
channel.ForEach[either.Bytes](
ctx, eitherEventsBzReplayObs,
func(_ context.Context, eitherEventBz either.Bytes) {
Expand All @@ -44,19 +49,18 @@ func (s *suite) AfterTheSupplierCreatesAClaimForTheSession() {
return
}

// Unmarshal byte data into a TxEvent object.
// Try to deserialize the provided bytes into a TxEvent.
err = json.Unmarshal(eventBz, &map[string]any{})
// Unmarshal event data into a TxEventResponse object.
txEvent := &tx.TxEvent{}
err = json.Unmarshal(eventBz, txEvent)
require.NoError(s, err)

var found bool
// TODO_IN_THIS_COMMIT: improve or comment...
for _, event := range ((map[string]any{"result": nil})["result"]).(map[string]any)["events"].([]any) {
for _, attribute := range event.(map[string]any)["attributes"].([]any) {
if attribute.(map[string]any)["key"] == "action" {
for _, event := range txEvent.Result.Events {
for _, attribute := range event.Attributes {
if attribute.Key == "action" {
require.Equal(
s, "/pocket.supplier.MsgCreateClaim",
attribute.(map[string]any)["value"],
attribute.Value,
)
found = true
break
Expand All @@ -79,60 +83,65 @@ func (s *suite) AfterTheSupplierCreatesAClaimForTheSession() {
}
}

func (s *suite) TheClaimCreatedBySupplierShouldBePersistedOnchain(supplierName string) {
func (s *suite) TheClaimCreatedBySupplierForServiceForApplicationShouldBePersistedOnchain(supplierName, serviceId, appName string) {
ctx := context.Background()

// TODO_IN_THIS_COMMIT: set up in before hooks
flagSet := testclient.NewLocalnetFlagSet(s)
clientCtx := testclient.NewLocalnetClientCtx(s, flagSet)
supplierQueryClient := suppliertypes.NewQueryClient(clientCtx)

claimsRes, err := supplierQueryClient.AllClaims(ctx, &suppliertypes.QueryAllClaimsRequest{
claimsRes, err := s.supplierQueryClient.AllClaims(ctx, &suppliertypes.QueryAllClaimsRequest{
Filter: &suppliertypes.QueryAllClaimsRequest_SupplierAddress{
SupplierAddress: accNameToAddrMap[supplierName],
},
})
require.NoError(s, err)
require.NotNil(s, claimsRes)

// TODO_IN_THIS_COMMIT: query claims before this step, perhaps note the highest
// session end height, then compare against queried claims in this step,
// asserting the length is +1 and the highest session end height increased.
//require.Lenf(s, claimsRes.Claim, 1, "expected 1 claim, got %d", len(claimsRes.Claim))
require.NotEmpty(s, claimsRes.Claim)
// Assert that the number of claims has increased by one.
preExistingClaims := s.scenarioState[preExistingClaimsKey].([]suppliertypes.Claim)
require.Len(s, claimsRes.Claim, len(preExistingClaims)+1)

// TODO_IMPROVE: assert that the root hash of the claim contains the correct
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

// SMST sum. The sum can be retrieved by parsing the last 8 bytes as a
// binary-encoded uint64; e.g. something like:
// `binary.Uvarint(claim.RootHash[len(claim.RootHash-8):])`

// TODO_IMPROVE: add assertions about serviceId and appName and/or incorporate
// them into the scenarioState key(s).

claim := claimsRes.Claim[0]
require.Equal(s, accNameToAddrMap[supplierName], claim.SupplierAddress)
}

func (s *suite) TheSupplierHasServicedASessionOfRelaysForApplication(supplierName string, appName string) {
// TODO_IN_THIS_COMMIT: use consts or something
// TODO_IN_THIS_COMMIT: use testclient.CometLocalWebsocketURL instead.
pocketNodeWebsocketUrl := "ws://poktroll-sequencer:36657/websocket"
msgClaimSenderQueryFmt := "tm.event='Tx' AND message.sender='%s'"
msgSenderQuery := fmt.Sprintf(msgClaimSenderQueryFmt, accNameToAddrMap[supplierName])
s.Logf("msgSenderQuery: %s", msgSenderQuery)
func (s *suite) TheSupplierHasServicedASessionWithRelaysForServiceForApplication(supplierName, relayCountStr, serviceId, appName string) {
ctx := context.Background()

// TODO_TECHDEBT: refactor to use EventsReplayClient once available.
eventsQueryClient := eventsquery.NewEventsQueryClient(pocketNodeWebsocketUrl)
relayCount, err := strconv.Atoi(relayCountStr)
require.NoError(s, err)

// Query for any existing claims so that we can compensate for them in the
// future assertions about changes in on-chain claims.
claimsRes, err := s.supplierQueryClient.AllClaims(ctx, &suppliertypes.QueryAllClaimsRequest{})
require.NoError(s, err)
s.scenarioState[preExistingClaimsKey] = claimsRes.Claim

// Construct an events query client to listen for tx events from the supplier.
msgSenderQuery := fmt.Sprintf(msgClaimSenderQueryFmt, accNameToAddrMap[supplierName])

// TODO_TECHDEBT(#220): refactor to use EventsReplayClient once available.
eventsQueryClient := eventsquery.NewEventsQueryClient(testclient.CometLocalWebsocketURL)
eitherEventsBzObs, err := eventsQueryClient.EventsBytes(ctx, msgSenderQuery)
require.NoError(s, err)

eitherEventsBytesObs := observable.Observable[either.Bytes](eitherEventsBzObs)
eitherEventsBzRelayObs := channel.ToReplayObservable(ctx, eitherEventsReplayBufferSize, eitherEventsBytesObs)
s.scenarioState[eitherEventsBzReplayObsKey] = eitherEventsBzRelayObs

// TODO_IN_THIS_COMMMIT: use consts or something
s.sendRelaysForSession(
appName,
supplierName,
"anvil",
5,
testServiceId,
relayCount,
)
}

// TODO_IN_THIS_COMMIT: rename
func (s *suite) sendRelaysForSession(
appName string,
supplierName string,
Expand All @@ -143,7 +152,7 @@ func (s *suite) sendRelaysForSession(
s.TheSupplierIsStakedForService(supplierName, serviceId)
s.TheSessionForApplicationAndServiceContainsTheSupplier(appName, serviceId, supplierName)

// TODO_IN_THIS_COMMIT: something better
// TODO_IMPROVE/TODO_COMMUNITY: hard-code a default set of RPC calls to iterate over for coverage.
data := `{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}`

for i := 0; i < relayLimit; i++ {
Expand Down
6 changes: 5 additions & 1 deletion pkg/client/tx/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,11 @@ type (
// the transactions subscription.
type TxEvent struct {
// Tx is the binary representation of the tx hash.
Tx []byte `json:"tx"`
Tx []byte `json:"tx"`
Result TxResult `json:"result"`
bryanchriswhite marked this conversation as resolved.
Show resolved Hide resolved
}

type TxResult struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm worried that TxResult may be conflated with the definition of a TxResult in Comet/Tendermint land. Wdyt if ABCIEvents, TxResultEvents or removing the decoupling altogether?

Screenshot 2023-12-04 at 3 07 34 PM

https://github.com/cosmos/cosmos-sdk/blob/main/proto/tendermint/abci/types.proto#L416

Copy link
Contributor Author

@bryanchriswhite bryanchriswhite Dec 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for calling this out! 🙌 This is indeed the correct type and we should be using it. 🦾 I would convert TxEvent to an alias for now with a comment that it should either be unexported and used via a new interface, or remove it altogether. I feel like it might make more sense to leave in, especially for the time being, because:

  1. On the spectrum of [rollup agnostic] <---> [cosmos-sdk specific], this would be more of a middle position and removing it altogether may equate to a step backwards (depending on other considerations we may have made).
  2. This PR is already getting quite large.

I have gone digging (on more than one occasion) for the actual protobuf that is being used by comet/cosmos to produce the JSON structure we see in the event subscription stream. I can't remember if I looked at this one before or not but I'm realizing that it's tricky to connect the dots because it's being serialized to JSON. 🤔 Anyways, you nailed it - thanks!

Events []abciTypes.Event `json:"events"`
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/relayer/miner/gen/gen_fixtures.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func init() {
// random bytes.
// Output file is truncated and overwritten if it already exists.
//
// To regenerate all fixtures, use `make go_fixturegen`; to regenerate only this
// To regenerate all fixtures, use `make go_testgen_fixtures`; to regenerate only this
// test's fixtures run `go generate ./pkg/relayer/miner/miner_test.go`.
func main() {
flag.Parse()
Expand Down
2 changes: 1 addition & 1 deletion pkg/relayer/miner/gen/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ var (
`// DO NOT EDIT: this file was generated by gen/gen_fixtures.go,
// changes made will be overwritten upon regeneration.
//
// To regenerate all fixtures, use make go_fixturegen; to regenerate only this
// To regenerate all fixtures, use make go_testgen_fixture; to regenerate only this
// test's fixtures run go generate ./pkg/relayer/miner/miner_test.go.
package miner_test

Expand Down
2 changes: 1 addition & 1 deletion pkg/relayer/miner/miner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const testDifficulty = 16
// it pipes pre-mined relay fixtures. It asserts that the observable only emits
// mined relays with difficulty equal to or greater than testDifficulty.
//
// To regenerate all fixtures, use `make go_fixturegen`; to regenerate only this
// To regenerate all fixtures, use `make go_testgen_fixtures`; to regenerate only this
// test's fixtures run `go generate ./pkg/relayer/miner/miner_test.go`.
func TestMiner_MinedRelays(t *testing.T) {
var (
Expand Down
2 changes: 1 addition & 1 deletion pkg/relayer/miner/relay_fixtures_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// DO NOT EDIT: this file was generated by gen/gen_fixtures.go,
// changes made will be overwritten upon regeneration.
//
// To regenerate all fixtures, use make go_fixturegen; to regenerate only this
// To regenerate all fixtures, use make go_testgen_fixture; to regenerate only this
// test's fixtures run go generate ./pkg/relayer/miner/miner_test.go.
package miner_test

Expand Down
30 changes: 9 additions & 21 deletions testutil/keeper/supplier.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,14 @@ import (
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"

"github.com/pokt-network/poktroll/testutil/supplier"
"github.com/pokt-network/poktroll/testutil/supplier/mocks"
apptypes "github.com/pokt-network/poktroll/x/application/types"
sessiontypes "github.com/pokt-network/poktroll/x/session/types"
sharedtypes "github.com/pokt-network/poktroll/x/shared/types"
"github.com/pokt-network/poktroll/x/supplier/keeper"
"github.com/pokt-network/poktroll/x/supplier/types"
)

type SessionMetaFixturesByAppAddr map[string]SessionMetaFixture
type SessionMetaFixture struct {
SessionId string
AppAddr string
SupplierAddr string
}

func SupplierKeeper(t testing.TB, sessionFixtures SessionMetaFixturesByAppAddr) (*keeper.Keeper, sdk.Context) {
func SupplierKeeper(t testing.TB, sessionByAppAddr supplier.SessionsByAppAddress) (*keeper.Keeper, sdk.Context) {
t.Helper()

storeKey := sdk.NewKVStoreKey(types.StoreKey)
Expand Down Expand Up @@ -58,27 +50,23 @@ func SupplierKeeper(t testing.TB, sessionFixtures SessionMetaFixturesByAppAddr)
ctx sdk.Context,
req *sessiontypes.QueryGetSessionRequest,
) (*sessiontypes.QueryGetSessionResponse, error) {
sessionMock, ok := sessionFixtures[req.GetApplicationAddress()]
session, ok := sessionByAppAddr[req.GetApplicationAddress()]
require.Truef(t, ok, "application address not provided during mock construction: %q", req.ApplicationAddress)

return &sessiontypes.QueryGetSessionResponse{
Session: &sessiontypes.Session{
Header: &sessiontypes.SessionHeader{
ApplicationAddress: sessionMock.AppAddr,
ApplicationAddress: session.GetApplication().GetAddress(),
Service: req.GetService(),
SessionStartBlockHeight: 1,
SessionId: sessionMock.SessionId,
SessionId: session.GetSessionId(),
SessionEndBlockHeight: 5,
},
SessionId: sessionMock.SessionId,
SessionId: session.GetSessionId(),
SessionNumber: 1,
NumBlocksPerSession: 4,
Application: &apptypes.Application{
Address: sessionMock.AppAddr,
},
Suppliers: []*sharedtypes.Supplier{{
Address: sessionMock.SupplierAddr,
}},
NumBlocksPerSession: session.GetNumBlocksPerSession(),
Application: session.GetApplication(),
Suppliers: session.GetSuppliers(),
},
}, nil
},
Expand Down
7 changes: 4 additions & 3 deletions testutil/network/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ func DefaultApplicationModuleGenesisState(t *testing.T, n int) *apptypes.Genesis
return state
}

// TODO_IN_THIS_COMMIT: fix comment...
// ApplicationModuleGenesisStateWithAccount generates a GenesisState object with a single supplier with the given address.
// ApplicationModuleGenesisStateWithAccount generates a GenesisState object with
// a single application for each of the given addresses.
func ApplicationModuleGenesisStateWithAddresses(t *testing.T, addresses []string) *apptypes.GenesisState {
t.Helper()
state := apptypes.DefaultGenesis()
Expand Down Expand Up @@ -194,7 +194,8 @@ func DefaultSupplierModuleGenesisState(t *testing.T, n int) *suppliertypes.Genes
return state
}

// SupplierModuleGenesisStateWithAccount generates a GenesisState object with a single supplier with the given address.
// SupplierModuleGenesisStateWithAddresses generates a GenesisState object with
// a single supplier for each of the given addresses.
func SupplierModuleGenesisStateWithAddresses(t *testing.T, addresses []string) *suppliertypes.GenesisState {
t.Helper()
state := suppliertypes.DefaultGenesis()
Expand Down
Loading
Loading