@@ -75,23 +75,38 @@ var fallBackCodec = codec.NewProtoCodec(types.NewInterfaceRegistry())
7575
7676// GetHeightFromMetadata extracts the block height from gRPC metadata in the context.
7777// Returns 0 if no valid height is found.
78+ //
79+ // Deprecated: This function silently ignores parse errors and negative heights for backward compatibility.
80+ // Use GetHeightFromMetadataStrict for stricter error handling.
7881func GetHeightFromMetadata (grpcCtx gocontext.Context ) int64 {
82+ height , _ := GetHeightFromMetadataStrict (grpcCtx )
83+ return height
84+ }
85+
86+ // GetHeightFromMetadataStrict extracts the block height from gRPC metadata in the context.
87+ // Returns an error if the height header is present but invalid (parse error or negative).
88+ // Returns 0 with no error if no height header is present.
89+ func GetHeightFromMetadataStrict (grpcCtx gocontext.Context ) (int64 , error ) {
7990 md , ok := metadata .FromOutgoingContext (grpcCtx )
8091 if ! ok {
81- return 0
92+ return 0 , nil
8293 }
8394 heights := md .Get (grpctypes .GRPCBlockHeightHeader )
8495 if len (heights ) == 0 {
85- return 0
96+ return 0 , nil
8697 }
8798 height , err := strconv .ParseInt (heights [0 ], 10 , 64 )
8899 if err != nil {
89- return 0
100+ return 0 , errorsmod .Wrapf (
101+ sdkerrors .ErrInvalidRequest ,
102+ "invalid height header %q: %v" , grpctypes .GRPCBlockHeightHeader , err )
90103 }
91104 if height < 0 {
92- return 0
105+ return 0 , errorsmod .Wrapf (
106+ sdkerrors .ErrInvalidRequest ,
107+ "height (%d) from %q must be >= 0" , height , grpctypes .GRPCBlockHeightHeader )
93108 }
94- return height
109+ return height , nil
95110}
96111
97112// Invoke implements the grpc ClientConn.Invoke method
@@ -102,15 +117,19 @@ func (ctx Context) Invoke(grpcCtx gocontext.Context, method string, req, reply a
102117 // 2-2. or we are querying for state, in which case we call ABCI's Query if grpc client not set.
103118
104119 // In both cases, we don't allow empty request args (it will panic unexpectedly).
105- if reflect .ValueOf (req ).IsNil () {
120+ if req == nil {
121+ return errorsmod .Wrap (sdkerrors .ErrInvalidRequest , "request cannot be nil" )
122+ }
123+ reqVal := reflect .ValueOf (req )
124+ if reqVal .Kind () == reflect .Ptr && reqVal .IsNil () {
106125 return errorsmod .Wrap (sdkerrors .ErrInvalidRequest , "request cannot be nil" )
107126 }
108127
109128 // Case 1. Broadcasting a Tx.
110129 if reqProto , ok := req .(* tx.BroadcastTxRequest ); ok {
111130 res , ok := reply .(* tx.BroadcastTxResponse )
112131 if ! ok {
113- return errorsmod .Wrapf (sdkerrors .ErrInvalidRequest , "expected %T, got %T" , (* tx .BroadcastTxResponse )(nil ), req )
132+ return errorsmod .Wrapf (sdkerrors .ErrInvalidRequest , "expected %T, got %T" , (* tx .BroadcastTxResponse )(nil ), reply )
114133 }
115134
116135 broadcastRes , err := TxServiceBroadcast (grpcCtx , ctx , reqProto )
@@ -119,7 +138,7 @@ func (ctx Context) Invoke(grpcCtx gocontext.Context, method string, req, reply a
119138 }
120139 * res = * broadcastRes
121140
122- return err
141+ return nil
123142 }
124143
125144 if ctx .GRPCClient != nil {
@@ -128,7 +147,10 @@ func (ctx Context) Invoke(grpcCtx gocontext.Context, method string, req, reply a
128147 if ctx .GRPCConnProvider != nil {
129148 height := ctx .Height
130149 if height <= 0 {
131- height = GetHeightFromMetadata (grpcCtx )
150+ height , err = GetHeightFromMetadataStrict (grpcCtx )
151+ if err != nil {
152+ return err
153+ }
132154 }
133155
134156 grpcConn = ctx .GRPCConnProvider .GetGRPCConn (height )
@@ -143,11 +165,9 @@ func (ctx Context) Invoke(grpcCtx gocontext.Context, method string, req, reply a
143165 }
144166
145167 // parse height header
146- height := GetHeightFromMetadata (grpcCtx )
147- if height < 0 {
148- return errorsmod .Wrapf (
149- sdkerrors .ErrInvalidRequest ,
150- "client.Context.Invoke: height (%d) from %q must be >= 0" , height , grpctypes .GRPCBlockHeightHeader )
168+ height , err := GetHeightFromMetadataStrict (grpcCtx )
169+ if err != nil {
170+ return err
151171 }
152172
153173 if height > 0 {
0 commit comments