Skip to content
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

fix: TODO: use base64.URLEncoding to modify TestQueryBlockByHash #711

Merged
merged 5 commits into from
Oct 14, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/grpc/tmservice/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func (s queryServer) GetBlockByHash(_ context.Context, req *GetBlockByHashReques
if n == 0 {
return nil, status.Error(codes.InvalidArgument, "block hash cannot be empty")
}
return nil, status.Error(codes.InvalidArgument, "The length of blcok hash must be 32")
return nil, status.Error(codes.InvalidArgument, "the length of block hash must be 32")
}

res, err := getBlockByHash(s.clientCtx, req.Hash)
Expand Down
12 changes: 6 additions & 6 deletions client/grpc/tmservice/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package tmservice_test

import (
"context"
"encoding/base64"
"fmt"
"testing"

Expand Down Expand Up @@ -98,7 +99,7 @@ func (s IntegrationTestSuite) TestQueryBlockByHash() {
err string
}{
{blkhash, false, ""},
{bytes.HexBytes("wrong hash"), true, "The length of blcok hash must be 32: invalid request"},
{bytes.HexBytes("wrong hash"), true, "the length of block hash must be 32: invalid request"},
{bytes.HexBytes(""), true, "block hash cannot be empty"},
}

Expand All @@ -112,11 +113,10 @@ func (s IntegrationTestSuite) TestQueryBlockByHash() {
}
}

// TODO: Unlike gRPC, REST requests often fail. Need to understand the cause later
//restRes, err := rest.GetRequest(fmt.Sprintf("%s/lbm/base/ostracon/v1/block/%s", val.APIAddress, base64.StdEncoding.EncodeToString(blkhash)))
//s.Require().NoError(err)
//var blockInfoRes tmservice.GetBlockByHashResponse
//s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(restRes, &blockInfoRes))
restRes, err := rest.GetRequest(fmt.Sprintf("%s/lbm/base/ostracon/v1/block/%s", val.APIAddress, base64.URLEncoding.EncodeToString(blkhash)))
s.Require().NoError(err)
var blockInfoRes tmservice.GetBlockByHashResponse
s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(restRes, &blockInfoRes))
}

func (s IntegrationTestSuite) TestQueryBlockByHeight() {
Expand Down
49 changes: 48 additions & 1 deletion client/rpc/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package rpc

import (
"context"
"crypto/sha256"
"encoding/base64"
"fmt"
"net/http"
"strconv"
Expand Down Expand Up @@ -73,6 +75,24 @@ func getBlock(clientCtx client.Context, height *int64) ([]byte, error) {
return legacy.Cdc.MarshalJSON(res)
}

func getBlockByHash(clientCtx client.Context, hash []byte) ([]byte, error) {
// get the node
node, err := clientCtx.GetNode()
if err != nil {
return nil, err
}

// header -> BlockchainInfo
// header, tx -> Block
// results -> BlockResults
res, err := node.BlockByHash(context.Background(), hash)
if err != nil {
return nil, err
}

return legacy.Cdc.MarshalJSON(res)
}

// get the current blockchain height
func GetChainHeight(clientCtx client.Context) (int64, error) {
node, err := clientCtx.GetNode()
Expand All @@ -89,6 +109,33 @@ func GetChainHeight(clientCtx client.Context) (int64, error) {
return height, nil
}

// REST handler to get a block by hash
func BlockByHashRequestHandlerFn(clientCtx client.Context) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)

hash := vars["hash"]
blockHash, err := base64.URLEncoding.DecodeString(hash)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest,
"couldn't decode block hash by Base64URLDecode.")
return
}
if n := len(blockHash); n != sha256.Size {
rest.WriteErrorResponse(w, http.StatusBadRequest,
"the length of block hash must be 32")
return
}

output, err := getBlockByHash(clientCtx, blockHash)
if rest.CheckInternalServerError(w, err) {
return
}

rest.PostProcessResponseBare(w, clientCtx, output)
}
}

// REST handler to get a block
func BlockRequestHandlerFn(clientCtx client.Context) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
Expand All @@ -97,7 +144,7 @@ func BlockRequestHandlerFn(clientCtx client.Context) http.HandlerFunc {
height, err := strconv.ParseInt(vars["height"], 10, 64)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest,
"couldn't parse block height. Assumed format is '/block/{height}'.")
"couldn't parse block height. Assumed format is '/blocks/{height}'.")
return
}

Expand Down
1 change: 1 addition & 0 deletions client/rpc/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ func RegisterRoutes(clientCtx client.Context, r *mux.Router) {
r.HandleFunc("/syncing", NodeSyncingRequestHandlerFn(clientCtx)).Methods("GET")
r.HandleFunc("/blocks/latest", LatestBlockRequestHandlerFn(clientCtx)).Methods("GET")
r.HandleFunc("/blocks/{height}", BlockRequestHandlerFn(clientCtx)).Methods("GET")
r.HandleFunc("/block/{hash}", BlockByHashRequestHandlerFn(clientCtx)).Methods("GET")
r.HandleFunc("/validatorsets/latest", LatestValidatorSetRequestHandlerFn(clientCtx)).Methods("GET")
r.HandleFunc("/validatorsets/{height}", ValidatorSetRequestHandlerFn(clientCtx)).Methods("GET")
}
75 changes: 75 additions & 0 deletions client/rpc/rpc_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package rpc_test

import (
"encoding/base64"
"fmt"
"testing"

Expand Down Expand Up @@ -54,6 +55,80 @@ func (s *IntegrationTestSuite) TestLatestBlocks() {
var result ctypes.ResultBlock
err = legacy.Cdc.UnmarshalJSON(res, &result)
s.Require().NoError(err)

{
var result2 ctypes.ResultBlock
res, err := rest.GetRequest(fmt.Sprintf("%s/blocks/%d", val0.APIAddress, result.Block.Height))
s.Require().NoError(err)
err = legacy.Cdc.UnmarshalJSON(res, &result2)
s.Require().NoError(err)
s.Require().Equal(result, result2)
}
{
var result3 ctypes.ResultBlock
hash64 := base64.URLEncoding.EncodeToString(result.Block.Hash())
res, err := rest.GetRequest(fmt.Sprintf("%s/block/%s", val0.APIAddress, hash64))
s.Require().NoError(err)
err = legacy.Cdc.UnmarshalJSON(res, &result3)
s.Require().NoError(err)
s.Require().Equal(result, result3)
}
}

func (s *IntegrationTestSuite) TestBlockWithFailure() {
val0 := s.network.Validators[0]

tcs := []struct {
name string
height string
errRes string
}{
{
name: "parse error",
height: "a",
errRes: "{\"error\":\"couldn't parse block height. Assumed format is '/blocks/{height}'.\"}",
},
{
name: "bigger height error",
height: "1234567890",
errRes: "{\"error\":\"requested block height is bigger then the chain length\"}",
},
}
for _, tc := range tcs {
s.T().Run(tc.name, func(t *testing.T) {
res, err := rest.GetRequest(fmt.Sprintf("%s/blocks/%s", val0.APIAddress, tc.height))
s.Require().NoError(err)
s.Require().Equal(tc.errRes, string(res))
})
}
}

func (s *IntegrationTestSuite) TestBlockByHashWithFailure() {
val0 := s.network.Validators[0]

tcs := []struct {
name string
hash string
errRes string
}{
{
name: "base64 error",
hash: "wrong hash",
errRes: "{\"error\":\"couldn't decode block hash by Base64URLDecode.\"}",
},
{
name: "size error",
hash: base64.URLEncoding.EncodeToString([]byte{0}),
errRes: "{\"error\":\"the length of block hash must be 32\"}",
},
}
for _, tc := range tcs {
s.T().Run(tc.name, func(t *testing.T) {
res, err := rest.GetRequest(fmt.Sprintf("%s/block/%s", val0.APIAddress, tc.hash))
s.Require().NoError(err)
s.Require().Equal(tc.errRes, string(res))
})
}
}

func TestIntegrationTestSuite(t *testing.T) {
Expand Down
5 changes: 2 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ require (
github.com/tendermint/tm-db v0.6.7
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e
google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd
google.golang.org/grpc v1.48.0
google.golang.org/grpc v1.49.0
google.golang.org/protobuf v1.28.1
gopkg.in/yaml.v2 v2.4.0
)
Expand Down Expand Up @@ -122,7 +122,7 @@ require (
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/stretchr/objx v0.4.0 // indirect
github.com/subosito/gotenv v1.4.1 // indirect
github.com/tendermint/tendermint v0.34.19 // indirect
github.com/tendermint/tendermint v0.34.14 // indirect
github.com/zondax/hid v0.9.0 // indirect
go.etcd.io/bbolt v1.3.6 // indirect
golang.org/x/net v0.0.0-20220617184016-355a448f1bc9 // indirect
Expand All @@ -137,6 +137,5 @@ require (
replace (
github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76
github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1

google.golang.org/grpc => google.golang.org/grpc v1.33.2
)
Loading