diff --git a/x/logic/keeper/features/bech32_address_2.feature b/x/logic/keeper/features/bech32_address_2.feature index efc982fa..053c911b 100644 --- a/x/logic/keeper/features/bech32_address_2.feature +++ b/x/logic/keeper/features/bech32_address_2.feature @@ -16,7 +16,7 @@ Feature: bech32_address/2 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Address"] @@ -39,7 +39,7 @@ Feature: bech32_address/2 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Hrp", "Address"] @@ -63,7 +63,7 @@ Feature: bech32_address/2 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Address"] @@ -84,7 +84,7 @@ Feature: bech32_address/2 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Bech32"] @@ -109,7 +109,7 @@ Feature: bech32_address/2 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false results: @@ -130,7 +130,7 @@ Feature: bech32_address/2 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false results: @@ -146,7 +146,7 @@ Feature: bech32_address/2 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false results: @@ -163,7 +163,7 @@ Feature: bech32_address/2 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Hrp"] @@ -186,7 +186,7 @@ Feature: bech32_address/2 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Address"] @@ -207,7 +207,7 @@ Feature: bech32_address/2 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["X"] @@ -227,7 +227,7 @@ Feature: bech32_address/2 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Bech32"] @@ -247,7 +247,7 @@ Feature: bech32_address/2 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Bech32"] @@ -267,7 +267,7 @@ Feature: bech32_address/2 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Bech32"] @@ -287,7 +287,7 @@ Feature: bech32_address/2 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Bech32"] @@ -307,7 +307,7 @@ Feature: bech32_address/2 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Bech32"] @@ -327,7 +327,7 @@ Feature: bech32_address/2 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Address", "Bech32"] @@ -347,7 +347,7 @@ Feature: bech32_address/2 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Hrp", "Bech32"] diff --git a/x/logic/keeper/features/block_height_1.feature b/x/logic/keeper/features/block_height_1.feature index a7caff9a..f1f2d271 100644 --- a/x/logic/keeper/features/block_height_1.feature +++ b/x/logic/keeper/features/block_height_1.feature @@ -16,7 +16,7 @@ Feature: block_height/1 Then the answer we get is: """ yaml height: 100 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Height"] @@ -43,7 +43,7 @@ Feature: block_height/1 Then the answer we get is: """ yaml height: 101 - gas_used: 6033 + gas_used: 3877 answer: has_more: false variables: ["Height"] diff --git a/x/logic/keeper/features/block_time_1.feature b/x/logic/keeper/features/block_time_1.feature index d9657291..ae35c9e6 100644 --- a/x/logic/keeper/features/block_time_1.feature +++ b/x/logic/keeper/features/block_time_1.feature @@ -16,7 +16,7 @@ Feature: block_time/1 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Time"] @@ -44,7 +44,7 @@ Feature: block_time/1 Then the answer we get is: """ yaml height: 42 - gas_used: 6033 + gas_used: 3877 answer: has_more: false variables: ["Time"] diff --git a/x/logic/keeper/features/consult_1.feature b/x/logic/keeper/features/consult_1.feature index 68c062f6..27ac3ef8 100644 --- a/x/logic/keeper/features/consult_1.feature +++ b/x/logic/keeper/features/consult_1.feature @@ -34,7 +34,7 @@ Feature: consult/1 Then the answer we get is: """ yaml height: 42 - gas_used: 6034 + gas_used: 3878 answer: has_more: false variables: ["Who"] @@ -90,7 +90,7 @@ Feature: consult/1 Then the answer we get is: """ yaml height: 42 - gas_used: 6033 + gas_used: 3877 answer: has_more: false variables: ["X"] @@ -144,7 +144,7 @@ Feature: consult/1 Then the answer we get is: """ yaml height: 42 - gas_used: 6033 + gas_used: 3877 answer: has_more: false variables: ["File"] diff --git a/x/logic/keeper/features/current_output_1.feature b/x/logic/keeper/features/current_output_1.feature index 06b4cada..1468a9b0 100644 --- a/x/logic/keeper/features/current_output_1.feature +++ b/x/logic/keeper/features/current_output_1.feature @@ -28,7 +28,7 @@ Feature: current_output/1 Then the answer we get is: """ yaml height: 42 - gas_used: 6150 + gas_used: 3976 answer: has_more: false variables: @@ -66,7 +66,7 @@ Feature: current_output/1 Then the answer we get is: """ yaml height: 42 - gas_used: 6190 + gas_used: 4010 answer: has_more: false variables: @@ -104,7 +104,7 @@ Feature: current_output/1 Then the answer we get is: """ yaml height: 42 - gas_used: 6150 + gas_used: 3976 answer: has_more: false variables: @@ -145,7 +145,7 @@ Feature: current_output/1 Then the answer we get is: """ yaml height: 42 - gas_used: 6164 + gas_used: 3990 answer: has_more: false variables: @@ -176,7 +176,7 @@ Feature: current_output/1 Then the answer we get is: """ yaml height: 42 - gas_used: 6417 + gas_used: 4261 answer: has_more: false variables: diff --git a/x/logic/keeper/features/open_3.feature b/x/logic/keeper/features/open_3.feature index d42da376..d9e52e3d 100644 --- a/x/logic/keeper/features/open_3.feature +++ b/x/logic/keeper/features/open_3.feature @@ -31,7 +31,7 @@ Feature: open/3 Then the answer we get is: """ yaml height: 42 - gas_used: 6033 + gas_used: 3877 answer: has_more: false variables: diff --git a/x/logic/keeper/features/open_4.feature b/x/logic/keeper/features/open_4.feature index cec3cf88..b59f6ff1 100644 --- a/x/logic/keeper/features/open_4.feature +++ b/x/logic/keeper/features/open_4.feature @@ -43,7 +43,7 @@ Feature: open/4 Then the answer we get is: """ yaml height: 42 - gas_used: 6038 + gas_used: 3882 answer: has_more: false variables: ["URI"] @@ -86,7 +86,7 @@ Feature: open/4 Then the answer we get is: """ yaml height: 42 - gas_used: 6034 + gas_used: 3878 answer: has_more: false variables: ["Chars"] @@ -127,7 +127,7 @@ Feature: open/4 Then the answer we get is: """ yaml height: 42 - gas_used: 6034 + gas_used: 3878 answer: has_more: false variables: ["Chars"] @@ -149,7 +149,7 @@ Feature: open/4 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Stream"] @@ -170,7 +170,7 @@ Feature: open/4 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Stream"] @@ -191,7 +191,7 @@ Feature: open/4 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Stream"] @@ -212,7 +212,7 @@ Feature: open/4 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Stream"] @@ -232,7 +232,7 @@ Feature: open/4 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Stream"] @@ -251,7 +251,7 @@ Feature: open/4 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Stream"] @@ -270,7 +270,7 @@ Feature: open/4 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Resource", "Stream"] @@ -289,7 +289,7 @@ Feature: open/4 Then the answer we get is: """ yaml height: 42 - gas_used: 6032 + gas_used: 3876 answer: has_more: false variables: ["Mode", "Stream"] diff --git a/x/logic/keeper/grpc_query_ask.go b/x/logic/keeper/grpc_query_ask.go index bed5b716..9fd129d3 100644 --- a/x/logic/keeper/grpc_query_ask.go +++ b/x/logic/keeper/grpc_query_ask.go @@ -2,7 +2,7 @@ package keeper import ( goctx "context" - + "math" errorsmod "cosmossdk.io/errors" sdkmath "cosmossdk.io/math" @@ -37,18 +37,35 @@ func (k Keeper) Ask(ctx goctx.Context, req *types.QueryServiceAskRequest) (respo } }() - limits := k.limits(ctx) - if err := checkLimits(req, limits); err != nil { + params := k.GetParams(sdkCtx) + if err := checkLimits(req, params.Limits); err != nil { return nil, err } return k.execute( sdkCtx, + params, req.Program, req.Query, util.DerefOrDefault(req.Limit, defaultSolutionsLimit)) } +func checkLimits(request *types.QueryServiceAskRequest, limits types.Limits) error { + size := sdkmath.NewUint(uint64(len(request.GetQuery()))) + maxSize := util.DerefOrDefault(limits.MaxSize, sdkmath.NewUint(math.MaxInt64)) + if size.GT(maxSize) { + return errorsmod.Wrapf(types.LimitExceeded, "query: %d > MaxSize: %d", size.Uint64(), maxSize.Uint64()) + } + + resultCount := util.DerefOrDefault(request.Limit, defaultSolutionsLimit) + maxResultCount := util.DerefOrDefault(limits.MaxResultCount, sdkmath.NewUint(math.MaxInt64)) + if resultCount.GT(maxResultCount) { + return errorsmod.Wrapf(types.LimitExceeded, "query: %d > MaxResultCount: %d", resultCount.Uint64(), maxResultCount.Uint64()) + } + + return nil +} + // withSafeGasMeter returns a new context with a gas meter that has the given limit. // The gas meter is go-router-safe. func withSafeGasMeter(sdkCtx sdk.Context) sdk.Context { diff --git a/x/logic/keeper/grpc_query_ask_test.go b/x/logic/keeper/grpc_query_ask_test.go index 3d5b8e05..360c594b 100644 --- a/x/logic/keeper/grpc_query_ask_test.go +++ b/x/logic/keeper/grpc_query_ask_test.go @@ -37,6 +37,7 @@ func TestGRPCAsk(t *testing.T) { query string limit int maxResultCount int + maxSize int predicateBlacklist []string maxGas uint64 predicateCosts map[string]uint64 @@ -117,13 +118,13 @@ func TestGRPCAsk(t *testing.T) { query: "father(bob, X).", limit: 2, maxResultCount: 1, - expectedAnswer: &types.Answer{ - HasMore: true, - Variables: []string{"X"}, - Results: []types.Result{{Substitutions: []types.Substitution{{ - Variable: "X", Expression: "alice", - }}}}, - }, + expectedError: "query: 2 > MaxResultCount: 1: limit exceeded", + }, + { + program: "father(bob, alice). father(bob, john).", + query: "father(bob, X).", + maxSize: 5, + expectedError: "query: 15 > MaxSize: 5: limit exceeded", }, { query: "block_height(X).", @@ -141,16 +142,16 @@ func TestGRPCAsk(t *testing.T) { }, { query: "bank_balances(X, Y).", - maxGas: 3500, - expectedError: "out of gas: logic (5243/3500): limit exceeded", + maxGas: 3000, + expectedError: "out of gas: logic (3093/3000): limit exceeded", }, { query: "block_height(X).", - maxGas: 3500, + maxGas: 3000, predicateCosts: map[string]uint64{ "block_height/1": 10000, }, - expectedError: "out of gas: logic (13467/3500): limit exceeded", + expectedError: "out of gas: logic (11167/3000): limit exceeded", }, { program: "father(bob, 'élodie').", @@ -283,8 +284,8 @@ foo(a3) :- throw(error(resource_error(foo))). foo(a4). `, query: `foo(X).`, - limit: 5, - maxResultCount: 3, + limit: 3, + maxResultCount: 5, expectedAnswer: &types.Answer{ Variables: []string{"X"}, Results: []types.Result{ @@ -346,8 +347,10 @@ foo(a4). }, ) maxResultCount := sdkmath.NewUint(uint64(lo.If(tc.maxResultCount == 0, 1).Else(tc.maxResultCount))) + maxSize := sdkmath.NewUint(uint64(lo.If(tc.maxSize == 0, 5000).Else(tc.maxSize))) params := types.DefaultParams() params.Limits.MaxResultCount = &maxResultCount + params.Limits.MaxSize = &maxSize if tc.predicateBlacklist != nil { params.Interpreter.PredicatesFilter.Blacklist = tc.predicateBlacklist } diff --git a/x/logic/keeper/interpreter.go b/x/logic/keeper/interpreter.go index 36e4a51f..189e5dc8 100644 --- a/x/logic/keeper/interpreter.go +++ b/x/logic/keeper/interpreter.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "io" - "math" "strings" "github.com/ichiban/prolog" @@ -37,11 +36,6 @@ type writerStringer interface { fmt.Stringer } -func (k Keeper) limits(ctx context.Context) types.Limits { - params := k.GetParams(sdk.UnwrapSDKContext(ctx)) - return params.GetLimits() -} - func (k Keeper) enhanceContext(ctx context.Context) context.Context { sdkCtx := sdk.UnwrapSDKContext(ctx) sdkCtx = sdkCtx.WithValue(types.AuthKeeperContextKey, k.authKeeper) @@ -50,13 +44,12 @@ func (k Keeper) enhanceContext(ctx context.Context) context.Context { } func (k Keeper) execute( - ctx context.Context, program, query string, solutionsLimit sdkmath.Uint, + ctx context.Context, params types.Params, program, query string, solutionsLimit sdkmath.Uint, ) (*types.QueryServiceAskResponse, error) { ctx = k.enhanceContext(ctx) sdkCtx := sdk.UnwrapSDKContext(ctx) - limits := k.limits(sdkCtx) - i, userOutput, err := k.newInterpreter(ctx) + i, userOutput, err := k.newInterpreter(ctx, params) if err != nil { return nil, errorsmod.Wrapf(types.Internal, "error creating interpreter: %v", err.Error()) } @@ -64,7 +57,7 @@ func (k Keeper) execute( return nil, errorsmod.Wrapf(types.InvalidArgument, "error compiling query: %v", err.Error()) } - answer, err := k.queryInterpreter(ctx, i, query, sdkmath.MinUint(solutionsLimit, *limits.MaxResultCount)) + answer, err := k.queryInterpreter(ctx, i, query, solutionsLimit) if err != nil { return nil, err } @@ -85,9 +78,8 @@ func (k Keeper) queryInterpreter( } // newInterpreter creates a new interpreter properly configured. -func (k Keeper) newInterpreter(ctx context.Context) (*prolog.Interpreter, fmt.Stringer, error) { +func (k Keeper) newInterpreter(ctx context.Context, params types.Params) (*prolog.Interpreter, fmt.Stringer, error) { sdkctx := sdk.UnwrapSDKContext(ctx) - params := k.GetParams(sdkctx) interpreterParams := params.GetInterpreter() gasPolicy := params.GetGasPolicy() @@ -148,16 +140,6 @@ func (k Keeper) newInterpreter(ctx context.Context) (*prolog.Interpreter, fmt.St return i, userOutputBuffer, err } -func checkLimits(request *types.QueryServiceAskRequest, limits types.Limits) error { - size := sdkmath.NewUint(uint64(len(request.GetQuery()))) - maxSize := util.DerefOrDefault(limits.MaxSize, sdkmath.NewUint(math.MaxInt64)) - if size.GT(maxSize) { - return errorsmod.Wrapf(types.LimitExceeded, "query: %d > MaxSize: %d", size, maxSize) - } - - return nil -} - func lookupCost(predicate string, defaultCost uint64, costs []types.PredicateCost) uint64 { for _, c := range costs { if prolog2.PredicateMatches(predicate)(c.Predicate) {