Skip to content

Commit

Permalink
Add custom query (#114)
Browse files Browse the repository at this point in the history
* Add custom query for getting earliest btc block number
  • Loading branch information
KonradStaniec authored Sep 7, 2022
1 parent 14d0279 commit 51aa21e
Show file tree
Hide file tree
Showing 15 changed files with 716 additions and 135 deletions.
2 changes: 1 addition & 1 deletion proto/babylon/btccheckpoint/btccheckpoint.proto
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
syntax = "proto3";
package babylon.btccheckpoint;
package babylon.btccheckpoint.v1;

import "gogoproto/gogo.proto";

Expand Down
2 changes: 1 addition & 1 deletion proto/babylon/btccheckpoint/genesis.proto
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
syntax = "proto3";
package babylon.btccheckpoint;
package babylon.btccheckpoint.v1;

import "gogoproto/gogo.proto";
import "babylon/btccheckpoint/params.proto";
Expand Down
2 changes: 1 addition & 1 deletion proto/babylon/btccheckpoint/params.proto
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
syntax = "proto3";
package babylon.btccheckpoint;
package babylon.btccheckpoint.v1;

import "gogoproto/gogo.proto";

Expand Down
21 changes: 19 additions & 2 deletions proto/babylon/btccheckpoint/query.proto
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
syntax = "proto3";
package babylon.btccheckpoint;
package babylon.btccheckpoint.v1;

import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
Expand All @@ -13,9 +13,15 @@ option go_package = "github.com/babylonchain/babylon/x/btccheckpoint/types";
service Query {
// Parameters queries the parameters of the module.
rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
option (google.api.http).get = "/babylonchain/babylon/btccheckpoint/params";
option (google.api.http).get = "/babylon/btccheckpoint/v1/params";
}
// this line is used by starport scaffolding # 2


// BtcCheckpointHeight returns earliest block height for given rawcheckpoint
rpc BtcCheckpointHeight(QueryBtcCheckpointHeightRequest) returns (QueryBtcCheckpointHeightResponse) {
option (google.api.http).get = "/babylon/btccheckpoint/v1/{epoch_num}";
}
}

// QueryParamsRequest is request type for the Query/Params RPC method.
Expand All @@ -28,3 +34,14 @@ message QueryParamsResponse {
}

// this line is used by starport scaffolding # 3

message QueryBtcCheckpointHeightRequest {
// Number of epoch for which the earliest checkpointing btc height is requested
uint64 epoch_num = 1;
}

// QueryCurrentEpochResponse is response type for the Query/CurrentEpoch RPC method
message QueryBtcCheckpointHeightResponse {
// Earliest btc block number containing given raw checkpoint
uint64 earliest_btc_block_number = 1;
}
2 changes: 1 addition & 1 deletion proto/babylon/btccheckpoint/tx.proto
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
syntax = "proto3";
package babylon.btccheckpoint;
package babylon.btccheckpoint.v1;

// this line is used by starport scaffolding # proto/tx/import

Expand Down
37 changes: 34 additions & 3 deletions x/btccheckpoint/client/cli/query.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package cli

import (
"context"
"fmt"
// "strings"
"strconv"

"github.com/spf13/cobra"

"github.com/cosmos/cosmos-sdk/client"
// "github.com/cosmos/cosmos-sdk/client/flags"
// sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/babylonchain/babylon/x/btccheckpoint/types"
)
Expand All @@ -27,5 +26,37 @@ func GetQueryCmd(queryRoute string) *cobra.Command {
cmd.AddCommand(CmdQueryParams())
// this line is used by starport scaffolding # 1

cmd.AddCommand(CmdBtcCheckpointHeight())
return cmd
}

func CmdBtcCheckpointHeight() *cobra.Command {
cmd := &cobra.Command{
Use: "btc-height rawcheckpoint",
Short: "retrieve earliest btc height for given epoch",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)

queryClient := types.NewQueryClient(clientCtx)

epoch_num, err := strconv.ParseUint(args[0], 10, 64)

if err != nil {
return err
}

params := types.QueryBtcCheckpointHeightRequest{EpochNum: epoch_num}

res, err := queryClient.BtcCheckpointHeight(context.Background(), &params)

if err != nil {
return err
}

return clientCtx.PrintProto(res)
},
}

return cmd
}
74 changes: 74 additions & 0 deletions x/btccheckpoint/keeper/grpc_query.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,81 @@
package keeper

import (
"context"
"errors"
"math"

"github.com/babylonchain/babylon/x/btccheckpoint/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

var _ types.QueryServer = Keeper{}

func (k Keeper) lowestBtcHeight(ctx sdk.Context, subKey *types.SubmissionKey) (uint64, error) {
// initializing to max, as then every header number will be smaller
var lowestHeaderNumber uint64 = math.MaxUint64

for _, tk := range subKey.Key {

if !k.CheckHeaderIsOnMainChain(ctx, tk.Hash) {
return 0, errors.New("one of submission headers not on main chain")
}

headerNumber, err := k.GetBlockHeight(ctx, tk.Hash)

if err != nil {
// CheckHeaderIsOnMainChain (which uses main chain depth) returned true which
// means header should be saved and we should know its heigh but GetBlockHeight
// returned error. Something is really bad, panic.
panic("Inconsistent data model in btc light client")
}

if headerNumber < lowestHeaderNumber {
lowestHeaderNumber = headerNumber
}
}

return lowestHeaderNumber, nil
}

func (k Keeper) BtcCheckpointHeight(c context.Context, req *types.QueryBtcCheckpointHeightRequest) (*types.QueryBtcCheckpointHeightResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "invalid request")
}

ctx := sdk.UnwrapSDKContext(c)

checkpointEpoch := req.GetEpochNum()

epochData := k.GetEpochData(ctx, checkpointEpoch)

// Check if we have any submission for given epoch
if epochData == nil || len(epochData.Key) == 0 {
return nil, errors.New("checkpoint for given epoch not yet submitted")
}

var lowestHeaderNumber uint64 = math.MaxUint64

// we need to go for each submission in given epoch
for _, submissionKey := range epochData.Key {

headerNumber, err := k.lowestBtcHeight(ctx, submissionKey)

if err != nil {
// submission is not valid for some reason, ignore it
continue
}

if headerNumber < lowestHeaderNumber {
lowestHeaderNumber = headerNumber
}
}

if lowestHeaderNumber == math.MaxUint64 {
return nil, errors.New("there is no valid submission for given raw checkpoint")
}

return &types.QueryBtcCheckpointHeightResponse{EarliestBtcBlockNumber: lowestHeaderNumber}, nil
}
5 changes: 5 additions & 0 deletions x/btccheckpoint/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ func (k Keeper) CheckHeaderIsKnown(ctx sdk.Context, hash *bbn.BTCHeaderHashBytes
return err == nil
}

func (k Keeper) CheckHeaderIsOnMainChain(ctx sdk.Context, hash *bbn.BTCHeaderHashBytes) bool {
depth, err := k.btcLightClientKeeper.MainChainDepth(ctx, hash)
return err == nil && depth >= 0
}

func (k Keeper) MainChainDepth(ctx sdk.Context, hash *bbn.BTCHeaderHashBytes) (uint64, bool, error) {
depth, err := k.btcLightClientKeeper.MainChainDepth(ctx, hash)

Expand Down
1 change: 0 additions & 1 deletion x/btccheckpoint/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,6 @@ func TestStateTransitionOfValidSubmission(t *testing.T) {

// fire tip change callback
k.OnTipChange(ctx)

// TODO customs Equality for submission keys to check this are really keys
// we are looking for
unc = k.GetAllUnconfirmedSubmissions(ctx)
Expand Down
78 changes: 39 additions & 39 deletions x/btccheckpoint/types/btccheckpoint.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 12 additions & 12 deletions x/btccheckpoint/types/genesis.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 51aa21e

Please sign in to comment.