diff --git a/testutil/integration/app.go b/testutil/integration/app.go index 98197836a..619a57820 100644 --- a/testutil/integration/app.go +++ b/testutil/integration/app.go @@ -393,6 +393,7 @@ func NewCompleteIntegrationApp(t *testing.T) *App { applicationKeeper, proofKeeper, sharedKeeper, + sessionKeeper, ) tokenomicsModule := tokenomics.NewAppModule( cdc, diff --git a/testutil/keeper/tokenomics.go b/testutil/keeper/tokenomics.go index 9309710d3..37b3ea6fb 100644 --- a/testutil/keeper/tokenomics.go +++ b/testutil/keeper/tokenomics.go @@ -156,6 +156,9 @@ func TokenomicsKeeperWithActorAddrs(t testing.TB) ( mockSharedKeeper := mocks.NewMockSharedKeeper(ctrl) mockSharedKeeper.EXPECT().GetProofWindowCloseHeight(gomock.Any(), gomock.Any()).AnyTimes() + // Mock the session keeper + mockSessionKeeper := mocks.NewMockSessionKeeper(ctrl) + k := tokenomicskeeper.NewKeeper( cdc, runtime.NewKVStoreService(storeKey), @@ -166,6 +169,7 @@ func TokenomicsKeeperWithActorAddrs(t testing.TB) ( mockApplicationKeeper, mockProofKeeper, mockSharedKeeper, + mockSessionKeeper, ) sdkCtx := sdk.NewContext(stateStore, cmtproto.Header{}, false, log.NewNopLogger()) @@ -332,6 +336,7 @@ func NewTokenomicsModuleKeepers( appKeeper, proofKeeper, sharedKeeper, + sessionKeeper, ) require.NoError(t, tokenomicsKeeper.SetParams(ctx, tokenomicstypes.DefaultParams())) diff --git a/x/shared/session.go b/x/shared/session.go index 2bcc1b45f..6fd21d7e2 100644 --- a/x/shared/session.go +++ b/x/shared/session.go @@ -5,11 +5,6 @@ import ( sharedtypes "github.com/pokt-network/poktroll/x/shared/types" ) -const ( - minimumClaimWindowSizeBlocks = 1 - minimumProofWindowSizeBlocks = 1 -) - // TODO_DOCUMENT(@bryanchriswhite): Move this into the documentation: https://github.com/pokt-network/poktroll/pull/571#discussion_r1630923625 // GetSessionStartHeight returns the block height at which the session containing @@ -123,26 +118,12 @@ func GetEarliestSupplierClaimCommitHeight( // window open block hash and the supplier address. randomNumber := poktrand.SeededInt63(claimWindowOpenBlockHash, []byte(supplierAddr)) - distributionWindowSizeBlocks := GetClaimWindowSizeBlocks(sharedParams) + distributionWindowSizeBlocks := sharedParams.GetClaimWindowCloseOffsetBlocks() randCreateClaimHeightOffset := randomNumber % int64(distributionWindowSizeBlocks) return claimWindowOpenHeight + randCreateClaimHeightOffset } -// GetClaimWindowSizeBlocks returns the number of blocks between the opening and closing -// of the claim window, given the passed sharedParams. -func GetClaimWindowSizeBlocks(sharedParams *sharedtypes.Params) uint64 { - windowSizeBlocks := sharedParams.ClaimWindowCloseOffsetBlocks - - sharedParams.ClaimWindowOpenOffsetBlocks - - minimumClaimWindowSizeBlocks - - if windowSizeBlocks < 1 { - return 1 - } - - return windowSizeBlocks -} - // GetEarliestSupplierProofCommitHeight returns the earliest block height at which a proof // for the session that includes queryHeight can be committed for a given supplier // and the passed sharedParams. @@ -158,22 +139,8 @@ func GetEarliestSupplierProofCommitHeight( // window open block hash and the supplier address. randomNumber := poktrand.SeededInt63(proofWindowOpenBlockHash, []byte(supplierAddr)) - distributionWindowSizeBlocks := GetProofWindowSizeBlocks(sharedParams) + distributionWindowSizeBlocks := sharedParams.GetProofWindowCloseOffsetBlocks() randCreateProofHeightOffset := randomNumber % int64(distributionWindowSizeBlocks) return proofWindowOpenHeight + randCreateProofHeightOffset } - -// GetProofWindowSizeBlocks returns the number of blocks between the opening and closing -// of the proof window, given the passed sharedParams. -func GetProofWindowSizeBlocks(sharedParams *sharedtypes.Params) uint64 { - windowSizeBlocks := sharedParams.ProofWindowCloseOffsetBlocks - - sharedParams.ProofWindowOpenOffsetBlocks - - minimumProofWindowSizeBlocks - - if windowSizeBlocks < 1 { - return 1 - } - - return windowSizeBlocks -} diff --git a/x/shared/session_test.go b/x/shared/session_test.go index 31b19e62e..b11d89d60 100644 --- a/x/shared/session_test.go +++ b/x/shared/session_test.go @@ -217,10 +217,10 @@ func TestClaimProofWindows(t *testing.T) { require.GreaterOrEqual(t, earliestProofCommitHeight, claimWindowCloseHeight) require.Greater(t, proofWindowCloseHeight, earliestProofCommitHeight) - claimWindowSizeBlocks := GetClaimWindowSizeBlocks(&test.sharedParams) + claimWindowSizeBlocks := test.sharedParams.GetClaimWindowCloseOffsetBlocks() require.Greater(t, claimWindowSizeBlocks, uint64(0)) - proofWindowSizeBlocks := GetProofWindowSizeBlocks(&test.sharedParams) + proofWindowSizeBlocks := test.sharedParams.GetProofWindowCloseOffsetBlocks() require.Greater(t, proofWindowSizeBlocks, uint64(0)) wg.Done() diff --git a/x/tokenomics/keeper/keeper.go b/x/tokenomics/keeper/keeper.go index 7e6c13b87..8952a9e0a 100644 --- a/x/tokenomics/keeper/keeper.go +++ b/x/tokenomics/keeper/keeper.go @@ -8,6 +8,8 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/pokt-network/poktroll/pkg/client" + prooftypes "github.com/pokt-network/poktroll/x/proof/types" "github.com/pokt-network/poktroll/x/tokenomics/types" ) @@ -26,6 +28,9 @@ type Keeper struct { applicationKeeper types.ApplicationKeeper proofKeeper types.ProofKeeper sharedKeeper types.SharedKeeper + sessionKeeper types.SessionKeeper + + sharedQuerier client.SharedQueryClient } func NewKeeper( @@ -39,11 +44,14 @@ func NewKeeper( applicationKeeper types.ApplicationKeeper, proofKeeper types.ProofKeeper, sharedKeeper types.SharedKeeper, + sessionKeeper types.SessionKeeper, ) Keeper { if _, err := sdk.AccAddressFromBech32(authority); err != nil { panic(fmt.Sprintf("invalid authority address: %s", authority)) } + sharedQuerier := prooftypes.NewSharedKeeperQueryClient(sharedKeeper, sessionKeeper) + return Keeper{ cdc: cdc, storeService: storeService, @@ -55,6 +63,9 @@ func NewKeeper( applicationKeeper: applicationKeeper, proofKeeper: proofKeeper, sharedKeeper: sharedKeeper, + sessionKeeper: sessionKeeper, + + sharedQuerier: sharedQuerier, } } diff --git a/x/tokenomics/keeper/settle_pending_claims.go b/x/tokenomics/keeper/settle_pending_claims.go index 4d9b94562..35b71f5a3 100644 --- a/x/tokenomics/keeper/settle_pending_claims.go +++ b/x/tokenomics/keeper/settle_pending_claims.go @@ -4,6 +4,7 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" poktrand "github.com/pokt-network/poktroll/pkg/crypto/rand" "github.com/pokt-network/poktroll/telemetry" @@ -26,10 +27,10 @@ func (k Keeper) SettlePendingClaims(ctx sdk.Context) ( ) { logger := k.Logger().With("method", "SettlePendingClaims") - // TODO_BLOCKER(@Olshansk): Optimize this by indexing expiringClaims appropriately - // and only retrieving the expiringClaims that need to be settled rather than all - // of them and iterating through them one by one. - expiringClaims := k.getExpiringClaims(ctx) + expiringClaims, err := k.getExpiringClaims(ctx) + if err != nil { + return settledResult, expiredResult, err + } blockHeight := ctx.BlockHeight() @@ -168,25 +169,52 @@ func (k Keeper) SettlePendingClaims(ctx sdk.Context) ( // This is the height at which the proof window closes. // If the proof window closes and a proof IS NOT required -> settle the claim. // If the proof window closes and a proof IS required -> only settle it if a proof is available. -func (k Keeper) getExpiringClaims(ctx sdk.Context) (expiringClaims []prooftypes.Claim) { +func (k Keeper) getExpiringClaims(ctx sdk.Context) (expiringClaims []prooftypes.Claim, err error) { blockHeight := ctx.BlockHeight() - // TODO_TECHDEBT: Optimize this by indexing claims appropriately - // and only retrieving the claims that need to be settled rather than all - // of them and iterating through them one by one. - claims := k.proofKeeper.GetAllClaims(ctx) + // NB: This error can be safely ignored as on-chain SharedQueryClient implementation cannot return an error. + sharedParams, _ := k.sharedQuerier.GetParams(ctx) + claimWindowSizeBlocks := sharedParams.GetClaimWindowOpenOffsetBlocks() + sharedParams.GetClaimWindowCloseOffsetBlocks() + proofWindowSizeBlocks := sharedParams.GetProofWindowOpenOffsetBlocks() + sharedParams.GetProofWindowCloseOffsetBlocks() + + // expiringSessionEndHeight is the session end height of the session whose proof + // window has most recently closed. + expiringSessionEndHeight := blockHeight - + int64(claimWindowSizeBlocks+ + proofWindowSizeBlocks+1) + + allClaims := k.proofKeeper.GetAllClaims(ctx) + _ = allClaims + + var nextKey []byte + for { + claimsRes, err := k.proofKeeper.AllClaims(ctx, &prooftypes.QueryAllClaimsRequest{ + Pagination: &query.PageRequest{ + Key: nextKey, + }, + Filter: &prooftypes.QueryAllClaimsRequest_SessionEndHeight{ + SessionEndHeight: uint64(expiringSessionEndHeight), + }, + }) + if err != nil { + return nil, err + } - // Loop over all claims we need to check for expiration - for _, claim := range claims { - claimSessionStartHeight := claim.GetSessionHeader().GetSessionStartBlockHeight() - expirationHeight := k.sharedKeeper.GetProofWindowCloseHeight(ctx, claimSessionStartHeight) - if blockHeight >= expirationHeight { + for _, claim := range claimsRes.GetClaims() { expiringClaims = append(expiringClaims, claim) } + + // Continue if there are more claims to fetch. + nextKey = claimsRes.Pagination.GetNextKey() + if nextKey != nil { + continue + } + + break } // Return the actually expiring claims - return expiringClaims + return expiringClaims, nil } // proofRequirementForClaim checks if a proof is required for a claim. diff --git a/x/tokenomics/module/module.go b/x/tokenomics/module/module.go index f4c2b388e..2e857d5fd 100644 --- a/x/tokenomics/module/module.go +++ b/x/tokenomics/module/module.go @@ -182,6 +182,7 @@ type ModuleInputs struct { ApplicationKeeper types.ApplicationKeeper ProofKeeper types.ProofKeeper SharedKeeper types.SharedKeeper + SessionKeeper types.SessionKeeper } type ModuleOutputs struct { @@ -207,6 +208,7 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { in.ApplicationKeeper, in.ProofKeeper, in.SharedKeeper, + in.SessionKeeper, ) m := NewAppModule( in.Cdc, diff --git a/x/tokenomics/types/expected_keepers.go b/x/tokenomics/types/expected_keepers.go index ffe72e8f9..a5ada5bb3 100644 --- a/x/tokenomics/types/expected_keepers.go +++ b/x/tokenomics/types/expected_keepers.go @@ -1,4 +1,4 @@ -//go:generate mockgen -destination ../../../testutil/tokenomics/mocks/expected_keepers_mock.go -package mocks . AccountKeeper,BankKeeper,ApplicationKeeper,ProofKeeper,SharedKeeper +//go:generate mockgen -destination ../../../testutil/tokenomics/mocks/expected_keepers_mock.go -package mocks . AccountKeeper,BankKeeper,ApplicationKeeper,ProofKeeper,SharedKeeper,SessionKeeper package types @@ -10,6 +10,7 @@ import ( apptypes "github.com/pokt-network/poktroll/x/application/types" prooftypes "github.com/pokt-network/poktroll/x/proof/types" + sessiontypes "github.com/pokt-network/poktroll/x/session/types" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" ) @@ -41,6 +42,8 @@ type ProofKeeper interface { GetProof(ctx context.Context, sessionId, supplierAddr string) (proof prooftypes.Proof, isProofFound bool) RemoveProof(ctx context.Context, sessionId, supplierAddr string) + AllClaims(ctx context.Context, req *prooftypes.QueryAllClaimsRequest) (*prooftypes.QueryAllClaimsResponse, error) + // Only used for testing & simulation UpsertClaim(ctx context.Context, claim prooftypes.Claim) UpsertProof(ctx context.Context, claim prooftypes.Proof) @@ -56,6 +59,12 @@ type SharedKeeper interface { GetProofWindowCloseHeight(ctx context.Context, queryHeight int64) int64 } +type SessionKeeper interface { + GetSession(context.Context, *sessiontypes.QueryGetSessionRequest) (*sessiontypes.QueryGetSessionResponse, error) + GetBlockHash(ctx context.Context, height int64) []byte + StoreBlockHash(ctx context.Context) +} + type SupplierKeeper interface { GetSupplier(ctx context.Context, supplierAddr string) (supplier sharedtypes.Supplier, found bool) SetSupplier(ctx context.Context, supplier sharedtypes.Supplier)