fix(server): allow align block header with skip check heaader in grpc server (#24068)

Co-authored-by: Alex | Interchain Labs <alex@interchainlabs.io>
Co-authored-by: Tyler <48813565+technicallyty@users.noreply.github.com>
This commit is contained in:
Đông Liều 2025-03-25 23:54:43 +07:00 committed by GitHub
parent d6fca6a5b6
commit 2be528f04f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 32 additions and 13 deletions

View File

@ -61,6 +61,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Bug Fixes
* (server) [#24068](https://github.com/cosmos/cosmos-sdk/pull/24068) Allow align block header with skip check header in grpc server.
* (x/gov) [#24044](https://github.com/cosmos/cosmos-sdk/pull/24044) Fix some places in which we call Remove inside a Walk (x/gov).
* (baseapp) [#24042](https://github.com/cosmos/cosmos-sdk/pull/24042) Fixed a data race inside BaseApp.getContext, found by end-to-end (e2e) tests.
* (client/server) [#24059](https://github.com/cosmos/cosmos-sdk/pull/24059) Consistently set viper prefix in client and server. It defaults for the binary name for both client and server.

View File

@ -22,6 +22,19 @@ import (
// RegisterGRPCServer registers gRPC services directly with the gRPC server.
func (app *BaseApp) RegisterGRPCServer(server gogogrpc.Server) {
app.RegisterGRPCServerWithSkipCheckHeader(server, false)
}
// RegisterGRPCServerWithSkipCheckHeader registers gRPC services with the specified gRPC server
// and bypass check header flag. During the commit phase, gRPC queries may be processed before the block header
// is fully updated, causing header checks to fail erroneously. Skipping the header check in these cases prevents
// false negatives and ensures more robust query handling. While bypassing the header check is generally preferred to avoid false
// negatives during the commit phase, there are niche scenarios where someone might want to enable it.
// For instance, if an application requires strict validation to ensure that the query context exactly
// reflects the expected block header (for consistency or security reasons), then enabling header checks
// could be beneficial. However, this strictness comes at the cost of potentially more frequent errors
// when queries occur during the commit phase.
func (app *BaseApp) RegisterGRPCServerWithSkipCheckHeader(server gogogrpc.Server, skipCheckHeader bool) {
// Define an interceptor for all gRPC queries: this interceptor will create
// a new sdk.Context, and pass it into the query handler.
interceptor := func(grpcCtx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
@ -47,7 +60,7 @@ func (app *BaseApp) RegisterGRPCServer(server gogogrpc.Server) {
// Create the sdk.Context. Passing false as 2nd arg, as we can't
// actually support proofs with gRPC right now.
sdkCtx, err := app.CreateQueryContext(height, false)
sdkCtx, err := app.CreateQueryContextWithCheckHeader(height, false, !skipCheckHeader)
if err != nil {
return nil, err
}

View File

@ -139,6 +139,9 @@ type GRPCConfig struct {
// MaxSendMsgSize defines the max message size in bytes the server can send.
// The default value is math.MaxInt32.
MaxSendMsgSize int `mapstructure:"max-send-msg-size"`
// SkipCheckHeader defines if the gRPC server should bypass check header.
SkipCheckHeader bool `mapstructure:"skip-check-header"`
}
// GRPCWebConfig defines configuration for the gRPC-web server.
@ -244,10 +247,11 @@ func DefaultConfig() *Config {
RPCMaxBodyBytes: 1000000,
},
GRPC: GRPCConfig{
Enable: true,
Address: DefaultGRPCAddress,
MaxRecvMsgSize: DefaultGRPCMaxRecvMsgSize,
MaxSendMsgSize: DefaultGRPCMaxSendMsgSize,
Enable: true,
Address: DefaultGRPCAddress,
MaxRecvMsgSize: DefaultGRPCMaxRecvMsgSize,
MaxSendMsgSize: DefaultGRPCMaxSendMsgSize,
SkipCheckHeader: false,
},
GRPCWeb: GRPCWebConfig{
Enable: true,

View File

@ -38,7 +38,7 @@ func NewGRPCServer(clientCtx client.Context, app types.Application, cfg config.G
grpc.MaxRecvMsgSize(maxRecvMsgSize),
)
app.RegisterGRPCServer(grpcSrv)
app.RegisterGRPCServerWithSkipCheckHeader(grpcSrv, cfg.SkipCheckHeader)
// Reflection allows consumers to build dynamic clients that can write to any
// Cosmos SDK application without relying on application packages at compile

View File

@ -91,10 +91,11 @@ const (
FlagAPIEnableUnsafeCORS = "api.enabled-unsafe-cors"
// gRPC-related flags
flagGRPCOnly = "grpc-only"
flagGRPCEnable = "grpc.enable"
flagGRPCAddress = "grpc.address"
flagGRPCWebEnable = "grpc-web.enable"
flagGRPCOnly = "grpc-only"
flagGRPCEnable = "grpc.enable"
flagGRPCAddress = "grpc.address"
flagGRPCWebEnable = "grpc-web.enable"
flagGRPCSkipCheckHeader = "grpc.skip-check-header"
// mempool flags
FlagMempoolMaxTxs = "mempool.max-txs"

View File

@ -39,9 +39,9 @@ type (
RegisterAPIRoutes(*api.Server, config.APIConfig)
// RegisterGRPCServer registers gRPC services directly with the gRPC
// server.
RegisterGRPCServer(grpc.Server)
// RegisterGRPCServerWithSkipCheckHeader registers gRPC services directly with the gRPC
// server and bypass check header flag.
RegisterGRPCServerWithSkipCheckHeader(grpc.Server, bool)
// RegisterTxService registers the gRPC Query service for tx (such as tx
// simulation, fetching txs by hash...).