-
Notifications
You must be signed in to change notification settings - Fork 887
feat(query): origin-aware pagination scan, limit, and offset caps #3948
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
Open
amir-deris
wants to merge
9
commits into
main
Choose a base branch
from
amir/plt-1001-pagination-scan-limit-revision
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 2 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
fad25b9
WIP
amir-deris ba46ceb
Addressing PR feedback, refactoring pagination
amir-deris d0df8d0
Removing some config test files
amir-deris 3ef7039
fix(query): close pagination scan-limit enforcement gaps
amir-deris 1c3b5ea
refactor(authz): route generic filtered pagination through context he…
amir-deris 24c3647
fix(query): reject oversized limit and offset on untrusted query path
amir-deris e6f8863
fix(query): align unfiltered offset pagination with base behavior
amir-deris 798408a
Merge branch 'main' into amir/plt-1001-pagination-scan-limit-revision
amir-deris 3bc5663
Removed feegrant/keeper/grpc_query.go
amir-deris File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| package baseapp | ||
|
|
||
| import ( | ||
| "context" | ||
| "fmt" | ||
| "net" | ||
| "strings" | ||
|
|
||
| srvconfig "github.com/sei-protocol/sei-chain/sei-cosmos/server/config" | ||
| servertypes "github.com/sei-protocol/sei-chain/sei-cosmos/server/types" | ||
| sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types" | ||
| "github.com/sei-protocol/sei-chain/sei-cosmos/types/query" | ||
| rpctypes "github.com/sei-protocol/sei-chain/sei-tendermint/rpc/jsonrpc/types" | ||
| "github.com/spf13/cast" | ||
| "google.golang.org/grpc/peer" | ||
| ) | ||
|
|
||
| const ( | ||
| FlagQueryTrustedCIDRs = "query.trusted-cidrs" | ||
| FlagQueryTrustedScanLimit = "query.trusted-scan-limit" | ||
| ) | ||
|
|
||
| type trustedCIDRMatcher struct { | ||
| networks []*net.IPNet | ||
| } | ||
|
|
||
| // newTrustedCIDRMatcher returns a matcher for parseable entries in cidrs, skipping the rest. | ||
| // warnQueryConfig should run before this so skipped entries are logged. | ||
| func newTrustedCIDRMatcher(cidrs []string) *trustedCIDRMatcher { | ||
| networks := make([]*net.IPNet, 0, len(cidrs)) | ||
| for _, cidr := range cidrs { | ||
| _, network, err := net.ParseCIDR(cidr) | ||
| if err != nil { | ||
| continue | ||
| } | ||
| networks = append(networks, network) | ||
| } | ||
| return &trustedCIDRMatcher{networks: networks} | ||
| } | ||
|
|
||
| func (m *trustedCIDRMatcher) contains(ipStr string) bool { | ||
| if m == nil { | ||
| return false | ||
| } | ||
| ip := net.ParseIP(stripHostPort(ipStr)) | ||
| if ip == nil { | ||
| return false | ||
| } | ||
| for _, network := range m.networks { | ||
| if network.Contains(ip) { | ||
| return true | ||
| } | ||
| } | ||
| return false | ||
| } | ||
|
|
||
| func readQueryConfig(appOpts servertypes.AppOptions) (srvconfig.QueryConfig, error) { | ||
| cfg := srvconfig.DefaultQueryConfig() | ||
| var err error | ||
|
|
||
| if v := appOpts.Get(FlagQueryTrustedCIDRs); v != nil { | ||
| if cfg.TrustedCIDRs, err = cast.ToStringSliceE(v); err != nil { | ||
| return cfg, fmt.Errorf("invalid %s: %w", FlagQueryTrustedCIDRs, err) | ||
| } | ||
| } | ||
| if v := appOpts.Get(FlagQueryTrustedScanLimit); v != nil { | ||
| if cfg.TrustedScanLimit, err = cast.ToUint64E(v); err != nil { | ||
| return cfg, fmt.Errorf("invalid %s: %w", FlagQueryTrustedScanLimit, err) | ||
| } | ||
| } | ||
| return cfg, nil | ||
| } | ||
|
|
||
| func warnQueryConfig(cfg srvconfig.QueryConfig) { | ||
| for _, warning := range srvconfig.ValidateQueryConfig(cfg) { | ||
| logger.Warn(warning) | ||
| } | ||
| } | ||
|
|
||
| func (app *BaseApp) enrichABCIQueryContext(ctx context.Context, sdkCtx sdk.Context) sdk.Context { | ||
| sdkCtx = sdkCtx.WithIsABCIQuery(true) | ||
| originIP := queryOriginIP(ctx) | ||
| trusted := app.trustedOriginMatcher != nil && app.trustedOriginMatcher.contains(originIP) | ||
| sdkCtx = sdkCtx.WithIsTrustedQueryOrigin(trusted) | ||
|
|
||
| if trusted { | ||
| if app.queryConfig.TrustedScanLimit == 0 { | ||
| sdkCtx = sdkCtx.WithQueryScanLimit(false, 0) | ||
| } else { | ||
| sdkCtx = sdkCtx.WithQueryScanLimit(true, app.queryConfig.TrustedScanLimit) | ||
| } | ||
| logger.Debug( | ||
| "query pagination using trusted scan limit", | ||
| "origin", originIP, | ||
| "limit", app.queryConfig.TrustedScanLimit, | ||
| ) | ||
| return sdkCtx | ||
| } | ||
|
|
||
| return sdkCtx.WithQueryScanLimit(true, query.MaxScanLimit) | ||
| } | ||
|
|
||
| func queryOriginIP(ctx context.Context) string { | ||
| if callInfo := rpctypes.GetCallInfo(ctx); callInfo != nil { | ||
| if addr := callInfo.RemoteAddr(); addr != "" { | ||
| return addr | ||
| } | ||
| } | ||
| if p, ok := peer.FromContext(ctx); ok && p.Addr != nil { | ||
| return p.Addr.String() | ||
| } | ||
| return "" | ||
| } | ||
|
|
||
| func stripHostPort(addr string) string { | ||
| if addr == "" { | ||
| return "" | ||
| } | ||
| if strings.HasPrefix(addr, "[") { | ||
| host, _, err := net.SplitHostPort(addr) | ||
| if err != nil { | ||
| return strings.Trim(addr, "[]") | ||
| } | ||
| return host | ||
| } | ||
| host, _, err := net.SplitHostPort(addr) | ||
| if err != nil { | ||
| return addr | ||
| } | ||
| return host | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| package baseapp | ||
|
|
||
| import ( | ||
| "net" | ||
| "testing" | ||
|
|
||
| srvconfig "github.com/sei-protocol/sei-chain/sei-cosmos/server/config" | ||
| "github.com/stretchr/testify/require" | ||
| "google.golang.org/grpc/peer" | ||
| ) | ||
|
|
||
| func TestTrustedCIDRMatcher(t *testing.T) { | ||
| matcher := newTrustedCIDRMatcher([]string{"127.0.0.1/32", "10.0.0.0/8"}) | ||
| require.True(t, matcher.contains("127.0.0.1:54321")) | ||
| require.True(t, matcher.contains("10.1.2.3")) | ||
| require.False(t, matcher.contains("203.0.113.1")) | ||
| } | ||
|
|
||
| func TestTrustedCIDRMatcherSkipsInvalidEntries(t *testing.T) { | ||
| matcher := newTrustedCIDRMatcher([]string{"not-a-cidr", "127.0.0.1/32"}) | ||
| require.True(t, matcher.contains("127.0.0.1")) | ||
| require.False(t, matcher.contains("203.0.113.1")) | ||
| } | ||
|
|
||
| func TestQueryOriginIPFromGRPCPeer(t *testing.T) { | ||
| addr, err := net.ResolveTCPAddr("tcp", "192.0.2.1:9090") | ||
| require.NoError(t, err) | ||
| ctx := peer.NewContext(t.Context(), &peer.Peer{Addr: addr}) | ||
| require.Equal(t, "192.0.2.1:9090", queryOriginIP(ctx)) | ||
| } | ||
|
|
||
| func TestValidateQueryConfigWarnsOnBroadCIDR(t *testing.T) { | ||
| warnings := srvconfig.ValidateQueryConfig(srvconfig.QueryConfig{ | ||
| TrustedCIDRs: []string{"0.0.0.0/0"}, | ||
| }) | ||
| require.Len(t, warnings, 1) | ||
| require.Contains(t, warnings[0], "overly broad") | ||
| } | ||
|
|
||
| func TestStripHostPort(t *testing.T) { | ||
| require.Equal(t, "127.0.0.1", stripHostPort("127.0.0.1:9090")) | ||
| require.Equal(t, "2001:db8::1", stripHostPort("[2001:db8::1]:9090")) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| TrustedCIDRs = <nil-slice> | ||
| TrustedScanLimit = uint64(100000) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| "query.trusted-cidrs" | ||
| "query.trusted-scan-limit" | ||
| # keys with a target of their own |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| # Code generated by TestWiringMatchesTheRecord. DO NOT EDIT. | ||
| # The coverage record. Which checks cover each configuration section in this package, one | ||
| # tab-separated (section, check) pair per line, read from this package's own test files. | ||
| # Compared exactly, the way go.sum is. A line that disappears is a check that was deleted, | ||
| # which is the one edit the remaining checks cannot report. Repeat calls collapse to one line, | ||
| # so this records which checks cover a section rather than how many times. | ||
| # Regenerate with `go test ./<pkg>/ -run TestWiringMatchesTheRecord -update` and read the diff. | ||
|
|
||
| query CheckAbsent | ||
| query CheckDefaults | ||
| query CheckEveryRowHasADiscriminatingSeed | ||
| query CheckKeyNames | ||
| query CheckManifestCoversEveryField | ||
| query CheckRow |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.