Skip to content

Commit

Permalink
btclightclient: Add BaseHeader query (#130)
Browse files Browse the repository at this point in the history
  • Loading branch information
vitsalis authored Sep 13, 2022
1 parent ca26533 commit 2b85f0b
Show file tree
Hide file tree
Showing 7 changed files with 579 additions and 47 deletions.
13 changes: 12 additions & 1 deletion proto/babylon/btclightclient/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,14 @@ service Query {
option (google.api.http).get = "/babylon/btclightclient/v1/mainchain";
}

// BestHeader return best header on canonical chain
// Tip return best header on canonical chain
rpc Tip(QueryTipRequest) returns (QueryTipResponse) {
option (google.api.http).get = "/babylon/btclightclient/v1/tip";
}

rpc BaseHeader(QueryBaseHeaderRequest) returns (QueryBaseHeaderResponse) {
option (google.api.http).get = "/babylon/btclightclient/v1/baseheader";
}
}

// QueryParamsRequest is request type for the Query/Params RPC method.
Expand Down Expand Up @@ -91,3 +95,10 @@ message QueryTipRequest {
message QueryTipResponse {
BTCHeaderInfo header = 1;
}

message QueryBaseHeaderRequest {
}

message QueryBaseHeaderResponse {
BTCHeaderInfo header = 1;
}
28 changes: 27 additions & 1 deletion x/btclightclient/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func GetQueryCmd(queryRoute string) *cobra.Command {
cmd.AddCommand(CmdContains())
cmd.AddCommand(CmdMainChain())
cmd.AddCommand(CmdTip())
cmd.AddCommand(CmdBaseHeader())

return cmd
}
Expand Down Expand Up @@ -146,7 +147,7 @@ func CmdMainChain() *cobra.Command {
func CmdTip() *cobra.Command {
cmd := &cobra.Command{
Use: "tip",
Short: "retrieve tip of btc blockchain",
Short: "retrieve tip of the bitcoin blockchain",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
Expand All @@ -167,3 +168,28 @@ func CmdTip() *cobra.Command {

return cmd
}

func CmdBaseHeader() *cobra.Command {
cmd := &cobra.Command{
Use: "base-header",
Short: "retrieve base header of the bitcoin blockchain",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)

queryClient := types.NewQueryClient(clientCtx)

params := types.NewQueryBaseHeaderRequest()
res, err := queryClient.BaseHeader(context.Background(), params)
if err != nil {
return err
}

return clientCtx.PrintProto(res)
},
}

flags.AddQueryFlagsToCmd(cmd)

return cmd
}
12 changes: 12 additions & 0 deletions x/btclightclient/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,15 @@ func (k Keeper) Tip(ctx context.Context, req *types.QueryTipRequest) (*types.Que

return &types.QueryTipResponse{Header: tip}, nil
}

func (k Keeper) BaseHeader(ctx context.Context, req *types.QueryBaseHeaderRequest) (*types.QueryBaseHeaderResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "invalid request")
}

sdkCtx := sdk.UnwrapSDKContext(ctx)

baseHeader := k.headersState(sdkCtx).GetBaseBTCHeader()

return &types.QueryBaseHeaderResponse{Header: baseHeader}, nil
}
80 changes: 80 additions & 0 deletions x/btclightclient/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,86 @@ func FuzzMainChainQuery(f *testing.F) {
})
}

func FuzzTipQuery(f *testing.F) {
/*
Checks:
1. If the request is nil, (nil, error) is returned
2. The query returns the tip BTC header
Data generation:
- Generate a random tree of headers and insert into storage
*/
datagen.AddRandomSeedsToFuzzer(f, 100)
f.Fuzz(func(t *testing.T, seed int64) {
rand.Seed(seed)
blcKeeper, ctx := testkeeper.BTCLightClientKeeper(t)
sdkCtx := sdk.WrapSDKContext(ctx)

// Test nil input
resp, err := blcKeeper.Tip(sdkCtx, nil)
if resp != nil {
t.Errorf("Nil input led to a non-nil response")
}
if err == nil {
t.Errorf("Nil input led to a nil error")
}

tree := genRandomTree(blcKeeper, ctx, 1, 10)

query := types.NewQueryTipRequest()
resp, err = blcKeeper.Tip(sdkCtx, query)
if err != nil {
t.Errorf("valid input led to an error: %s", err)
}
if resp == nil {
t.Errorf("Valid input led to nil response")
}
if !resp.Header.Eq(tree.GetTip()) {
t.Errorf("Invalid header returned. Expected %s, got %s", tree.GetTip().Hash, resp.Header.Hash)
}
})
}

func FuzzBaseHeaderQuery(f *testing.F) {
/*
Checks:
1. If the request is nil, (nil, error) is returned
2. The query returns the base BTC header
Data generation:
- Generate a random tree of headers and insert into storage.
*/
datagen.AddRandomSeedsToFuzzer(f, 100)
f.Fuzz(func(t *testing.T, seed int64) {
rand.Seed(seed)
blcKeeper, ctx := testkeeper.BTCLightClientKeeper(t)
sdkCtx := sdk.WrapSDKContext(ctx)

// Test nil input
resp, err := blcKeeper.BaseHeader(sdkCtx, nil)
if resp != nil {
t.Errorf("Nil input led to a non-nil response")
}
if err == nil {
t.Errorf("Nil input led to a nil error")
}

tree := genRandomTree(blcKeeper, ctx, 1, 10)

query := types.NewQueryBaseHeaderRequest()
resp, err = blcKeeper.BaseHeader(sdkCtx, query)
if err != nil {
t.Errorf("valid input led to an error: %s", err)
}
if resp == nil {
t.Errorf("Valid input led to nil response")
}
if !resp.Header.Eq(tree.GetRoot()) {
t.Errorf("Invalid header returned. Expected %s, got %s", tree.GetRoot().Hash, resp.Header.Hash)
}
})
}

// Constructors for PageRequest objects
func constructRequestWithKeyAndLimit(key []byte, limit uint64) *query.PageRequest {
// If limit is 0, set one randomly
Expand Down
4 changes: 4 additions & 0 deletions x/btclightclient/types/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,7 @@ func NewQueryMainChainRequest(req *query.PageRequest) *QueryMainChainRequest {
func NewQueryTipRequest() *QueryTipRequest {
return &QueryTipRequest{}
}

func NewQueryBaseHeaderRequest() *QueryBaseHeaderRequest {
return &QueryBaseHeaderRequest{}
}
Loading

0 comments on commit 2b85f0b

Please sign in to comment.