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 34 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
36 changes: 26 additions & 10 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -575,16 +575,6 @@ func New(
)
serviceModule := servicemodule.NewAppModule(appCodec, app.ServiceKeeper, app.AccountKeeper, app.BankKeeper)

app.SupplierKeeper = *suppliermodulekeeper.NewKeeper(
appCodec,
keys[suppliermoduletypes.StoreKey],
keys[suppliermoduletypes.MemStoreKey],
app.GetSubspace(suppliermoduletypes.ModuleName),

app.BankKeeper,
)
supplierModule := suppliermodule.NewAppModule(appCodec, app.SupplierKeeper, app.AccountKeeper, app.BankKeeper)

app.GatewayKeeper = *gatewaymodulekeeper.NewKeeper(
appCodec,
keys[gatewaymoduletypes.StoreKey],
Expand All @@ -607,6 +597,28 @@ 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
// reason, the existing pattern of ignite-generated keeper/module construction
// must be broken for these keepers and modules.
//
// Order of operations:
// 1. Construct supplier keeper
// 2. Construct session keeper
// 3. Provide session keeper to supplier keeper via custom #SupplySessionKeeper method.
// 4. Construct supplier module
// 5. Construct session module
app.SupplierKeeper = *suppliermodulekeeper.NewKeeper(
appCodec,
keys[suppliermoduletypes.StoreKey],
keys[suppliermoduletypes.MemStoreKey],
app.GetSubspace(suppliermoduletypes.ModuleName),

app.BankKeeper,
)

app.SessionKeeper = *sessionmodulekeeper.NewKeeper(
appCodec,
keys[sessionmoduletypes.StoreKey],
Expand All @@ -616,6 +628,10 @@ func New(
app.ApplicationKeeper,
app.SupplierKeeper,
)

app.SupplierKeeper.SupplySessionKeeper(app.SessionKeeper)

supplierModule := suppliermodule.NewAppModule(appCodec, app.SupplierKeeper, app.AccountKeeper, app.BankKeeper)
sessionModule := sessionmodule.NewAppModule(appCodec, app.SessionKeeper, app.AccountKeeper, app.BankKeeper)

// this line is used by starport scaffolding # stargate/app/keeperDefinition
Expand Down
14 changes: 11 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,11 @@ func TestMain(m *testing.M) {

type suite struct {
gocuke.TestingT
pocketd *pocketdBin
scenarioState map[string]any // temporary state for each scenario
cdc codec.Codec
// TODO_TECHDEBT: rename to `poktrolld`.
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 +74,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 All @@ -79,6 +86,7 @@ func TestFeatures(t *testing.T) {
gocuke.NewRunner(t, &suite{}).Path(flagFeaturesPath).Run()
}

// TODO_TECHDEBT: rename `pocketd` to `poktrolld`.
func (s *suite) TheUserHasThePocketdBinaryInstalled() {
s.TheUserRunsTheCommand("help")
}
Expand Down
10 changes: 10 additions & 0 deletions e2e/tests/session.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
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
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...
# TODO_INCOMPLETE: add step(s) for proof validation.
162 changes: 162 additions & 0 deletions e2e/tests/session_steps_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
//go:build e2e

package e2e

import (
"context"
"encoding/json"
"fmt"
"strconv"
"strings"
"time"

abci "github.com/cometbft/cometbft/abci/types"
"github.com/stretchr/testify/require"

eventsquery "github.com/pokt-network/poktroll/pkg/client/events_query"
"github.com/pokt-network/poktroll/pkg/either"
"github.com/pokt-network/poktroll/pkg/observable"
"github.com/pokt-network/poktroll/pkg/observable/channel"
"github.com/pokt-network/poktroll/testutil/testclient"
suppliertypes "github.com/pokt-network/poktroll/x/supplier/types"
)

const (
createClaimTimeoutDuration = 10 * time.Second
eitherEventsReplayBufferSize = 100
msgClaimSenderQueryFmt = "tm.event='Tx' AND message.sender='%s'"
testServiceId = "anvil"
eitherEventsBzReplayObsKey = "eitherEventsBzReplayObsKey"
preExistingClaimsKey = "preExistingClaimsKey"
)

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
// 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) {
eventBz, err := eitherEventBz.ValueOrError()
require.NoError(s, err)

if strings.Contains(string(eventBz), "jsonrpc") {
return
}

// Unmarshal event data into a TxEventResponse object.
txEvent := &abci.TxResult{}
err = json.Unmarshal(eventBz, txEvent)
require.NoError(s, err)

var found bool
for _, event := range txEvent.Result.Events {
for _, attribute := range event.Attributes {
if attribute.Key == "action" {
require.Equal(
s, "/pocket.supplier.MsgCreateClaim",
attribute.Value,
)
found = true
break
}
}
if found {
break
}
}
require.Truef(s, found, "unable to find event action attribute")

done()
},
)

select {
case <-ctx.Done():
case <-time.After(createClaimTimeoutDuration):
s.Fatal("timed out waiting for claim to be created")
}
}

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

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

// 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) TheSupplierHasServicedASessionWithRelaysForServiceForApplication(supplierName, relayCountStr, serviceId, appName string) {
ctx := context.Background()

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

s.sendRelaysForSession(
appName,
supplierName,
testServiceId,
relayCount,
)
}

func (s *suite) sendRelaysForSession(
appName string,
supplierName string,
serviceId string,
relayLimit int,
) {
s.TheApplicationIsStakedForService(appName, serviceId)
s.TheSupplierIsStakedForService(supplierName, serviceId)
s.TheSessionForApplicationAndServiceContainsTheSupplier(appName, serviceId, supplierName)

// 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++ {
s.TheApplicationSendsTheSupplierARequestForServiceWithData(appName, supplierName, serviceId, data)
s.TheApplicationReceivesASuccessfulRelayResponseSignedBy(appName, supplierName)
}
}
19 changes: 10 additions & 9 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ require (
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2
github.com/noot/ring-go v0.0.0-20231019173746-6c4b33bcf03f
github.com/pokt-network/smt v0.7.1
github.com/regen-network/gocuke v0.6.2
github.com/regen-network/gocuke v0.6.3
github.com/spf13/cast v1.5.1
github.com/spf13/cobra v1.7.0
github.com/spf13/pflag v1.0.5
Expand All @@ -63,7 +63,6 @@ require (
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
github.com/99designs/keyring v1.2.1 // indirect
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
github.com/alecthomas/participle/v2 v2.0.0-alpha7 // indirect
github.com/armon/go-metrics v0.4.1 // indirect
github.com/aws/aws-sdk-go v1.44.203 // indirect
github.com/benbjohnson/clock v1.3.5 // indirect
Expand All @@ -83,7 +82,7 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chzyer/readline v1.5.1 // indirect
github.com/cockroachdb/apd/v2 v2.0.2 // indirect
github.com/cockroachdb/apd/v3 v3.1.0 // indirect
github.com/cockroachdb/apd/v3 v3.2.1 // indirect
github.com/coinbase/rosetta-sdk-go/types v1.0.0 // indirect
github.com/confio/ics23/go v0.9.0 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
Expand All @@ -96,8 +95,10 @@ require (
github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect
github.com/cosmos/rosetta-sdk-go v0.10.0 // indirect
github.com/creachadair/taskgroup v0.6.1 // indirect
github.com/cucumber/common/gherkin/go/v22 v22.0.0 // indirect
github.com/cucumber/common/messages/go/v17 v17.1.1 // indirect
github.com/cucumber/common/messages/go/v19 v19.1.2 // indirect
github.com/cucumber/gherkin/go/v26 v26.2.0 // indirect
github.com/cucumber/messages/go/v21 v21.0.1 // indirect
github.com/cucumber/tag-expressions/go/v5 v5.0.6 // indirect
github.com/danieljoos/wincred v1.1.2 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
Expand Down Expand Up @@ -126,15 +127,15 @@ require (
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gofrs/uuid v4.3.1+incompatible // indirect
github.com/gofrs/uuid v4.4.0+incompatible // indirect
github.com/gogo/googleapis v1.4.1 // indirect
github.com/gogo/protobuf v1.3.3 // indirect
github.com/golang/glog v1.1.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/flatbuffers v2.0.0+incompatible // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/orderedcode v0.0.1 // indirect
github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect
Expand Down Expand Up @@ -289,10 +290,10 @@ require (
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools/v3 v3.5.0 // indirect
gotest.tools/v3 v3.5.1 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
nhooyr.io/websocket v1.8.7 // indirect
pgregory.net/rapid v0.5.5 // indirect
pgregory.net/rapid v1.1.0 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

Expand Down
Loading
Loading