Skip to content

Commit

Permalink
feat: Add bls pubkey set api (#232)
Browse files Browse the repository at this point in the history
  • Loading branch information
gitferry authored Dec 5, 2022
1 parent 9d85f02 commit e52cbae
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 1 deletion.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ require (
github.com/cosmos/cosmos-proto v1.0.0-alpha8
github.com/cosmos/ibc-go/v5 v5.1.0
github.com/golang/mock v1.6.0
github.com/jinzhu/copier v0.3.5
google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8
)

Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,8 @@ github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1C
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jhump/protoreflect v1.12.1-0.20220721211354-060cc04fc18b h1:izTof8BKh/nE1wrKOrloNA5q4odOarjf+Xpe+4qow98=
github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg=
github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
Expand Down
43 changes: 42 additions & 1 deletion x/checkpointing/keeper/grpc_query_bls.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,49 @@ package keeper
import (
"context"
"github.com/babylonchain/babylon/x/checkpointing/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/jinzhu/copier"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

func (k Keeper) BlsPublicKeyList(c context.Context, req *types.QueryBlsPublicKeyListRequest) (*types.QueryBlsPublicKeyListResponse, error) {
panic("TODO: implement this")
if req == nil {
return nil, status.Error(codes.InvalidArgument, "invalid request")
}
sdkCtx := sdk.UnwrapSDKContext(c)
valBLSKeys, err := k.GetBLSPubKeySet(sdkCtx, req.EpochNum)
if err != nil {
return nil, err
}

if req.Pagination == nil {
return &types.QueryBlsPublicKeyListResponse{
ValidatorWithBlsKeys: valBLSKeys,
}, nil
}

total := uint64(len(valBLSKeys))
start := req.Pagination.Offset
if start > total-1 {
return nil, status.Error(codes.InvalidArgument, "pagination offset out of range")
}
var end uint64
if req.Pagination.Limit == 0 {
end = total
} else {
end = req.Pagination.Limit + start
}
if end > total {
end = total
}
var copiedValBLSKeys []*types.ValidatorWithBlsKey
err = copier.Copy(&copiedValBLSKeys, valBLSKeys[start:end])
if err != nil {
return nil, err
}

return &types.QueryBlsPublicKeyListResponse{
ValidatorWithBlsKeys: copiedValBLSKeys,
}, nil
}
116 changes: 116 additions & 0 deletions x/checkpointing/keeper/grpc_query_bls_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package keeper_test

import (
"github.com/babylonchain/babylon/app"
"github.com/babylonchain/babylon/crypto/bls12381"
"github.com/babylonchain/babylon/testutil/datagen"
checkpointingkeeper "github.com/babylonchain/babylon/x/checkpointing/keeper"
"github.com/babylonchain/babylon/x/checkpointing/types"
"github.com/babylonchain/babylon/x/epoching/testepoching"
"github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/query"
"github.com/stretchr/testify/require"
"math/rand"
"testing"
)

// FuzzQueryBLSKeySet does the following checks
// 1. check the query when there's only a genesis validator
// 2. check the query when there are n+1 validators without pagination
// 3. check the query when there are n+1 validators with pagination
func FuzzQueryBLSKeySet(f *testing.F) {
datagen.AddRandomSeedsToFuzzer(f, 10)
f.Fuzz(func(t *testing.T, seed int64) {
rand.Seed(seed)
// a genesis validator is generated for setup
helper := testepoching.NewHelper(t)
ek := helper.EpochingKeeper
ck := helper.App.CheckpointingKeeper
querier := checkpointingkeeper.Querier{Keeper: ck}
queryHelper := baseapp.NewQueryServerTestHelper(helper.Ctx, helper.App.InterfaceRegistry())
types.RegisterQueryServer(queryHelper, querier)
queryClient := types.NewQueryClient(queryHelper)
msgServer := checkpointingkeeper.NewMsgServerImpl(ck)
// add BLS pubkey to the genesis validator
valSet := ek.GetValidatorSet(helper.Ctx, 0)
require.Len(t, valSet, 1)
genesisVal := valSet[0]
genesisBLSPubkey := bls12381.GenPrivKey().PubKey()
err := ck.CreateRegistration(helper.Ctx, genesisBLSPubkey, genesisVal.Addr)
require.NoError(t, err)

// BeginBlock of block 1, and thus entering epoch 1
ctx := helper.BeginBlock()
epoch := ek.GetEpoch(ctx)
require.Equal(t, uint64(1), epoch.EpochNumber)

// 1. query public key list when there's only a genesis validator
queryRequest := &types.QueryBlsPublicKeyListRequest{
EpochNum: 1,
}
res, err := queryClient.BlsPublicKeyList(ctx, queryRequest)
require.NoError(t, err)
require.Len(t, res.ValidatorWithBlsKeys, 1)
require.Equal(t, res.ValidatorWithBlsKeys[0].BlsPubKey, genesisBLSPubkey.Bytes())
require.Equal(t, res.ValidatorWithBlsKeys[0].ValidatorAddress, genesisVal.Addr.String())

// add n new validators via MsgWrappedCreateValidator
n := rand.Intn(3) + 1
addrs := app.AddTestAddrs(helper.App, helper.Ctx, n, sdk.NewInt(100000000))

wcvMsgs := make([]*types.MsgWrappedCreateValidator, n)
for i := 0; i < n; i++ {
msg, err := buildMsgWrappedCreateValidator(addrs[i])
require.NoError(t, err)
wcvMsgs[i] = msg
_, err = msgServer.WrappedCreateValidator(ctx, msg)
require.NoError(t, err)
}

// EndBlock of block 1
ctx = helper.EndBlock()

// go to BeginBlock of block 11, and thus entering epoch 2
for i := uint64(0); i < ek.GetParams(ctx).EpochInterval; i++ {
ctx = helper.GenAndApplyEmptyBlock()
}
epoch = ek.GetEpoch(ctx)
require.Equal(t, uint64(2), epoch.EpochNumber)

// 2. query BLS public keys when there are n+1 validators without pagination
req := types.QueryBlsPublicKeyListRequest{
EpochNum: 2,
}
resp, err := queryClient.BlsPublicKeyList(ctx, &req)
require.NoError(t, err)
require.Len(t, resp.ValidatorWithBlsKeys, n+1)
expectedValSet := ek.GetValidatorSet(ctx, 2)
require.Len(t, expectedValSet, n+1)
for i, expectedVal := range expectedValSet {
require.Equal(t, expectedVal.Addr.String(), resp.ValidatorWithBlsKeys[i].ValidatorAddress)
}

// 3.1 query BLS public keys when there are n+1 validators with limit pagination
req = types.QueryBlsPublicKeyListRequest{
EpochNum: 2,
Pagination: &query.PageRequest{
Limit: 1,
},
}
resp, err = queryClient.BlsPublicKeyList(ctx, &req)
require.NoError(t, err)
require.Len(t, resp.ValidatorWithBlsKeys, 1)

// 3.2 query BLS public keys when there are n+1 validators with offset pagination
req = types.QueryBlsPublicKeyListRequest{
EpochNum: 2,
Pagination: &query.PageRequest{
Offset: 1,
},
}
resp, err = queryClient.BlsPublicKeyList(ctx, &req)
require.NoError(t, err)
require.Len(t, resp.ValidatorWithBlsKeys, n)
})
}
18 changes: 18 additions & 0 deletions x/checkpointing/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,24 @@ func (k Keeper) CreateRegistration(ctx sdk.Context, blsPubKey bls12381.PublicKey
return k.RegistrationState(ctx).CreateRegistration(blsPubKey, valAddr)
}

// GetBLSPubKeySet returns the set of BLS public keys in the same order of the validator set for a given epoch
func (k Keeper) GetBLSPubKeySet(ctx sdk.Context, epochNumber uint64) ([]*types.ValidatorWithBlsKey, error) {
valset := k.GetValidatorSet(ctx, epochNumber)
valWithblsKeys := make([]*types.ValidatorWithBlsKey, len(valset))
for i, val := range valset {
pubkey, err := k.GetBlsPubKey(ctx, val.Addr)
if err != nil {
return nil, err
}
valWithblsKeys[i] = &types.ValidatorWithBlsKey{
ValidatorAddress: val.Addr.String(),
BlsPubKey: pubkey,
}
}

return valWithblsKeys, nil
}

func (k Keeper) GetBlsPubKey(ctx sdk.Context, address sdk.ValAddress) (bls12381.PublicKey, error) {
return k.RegistrationState(ctx).GetBlsPubKey(address)
}
Expand Down

0 comments on commit e52cbae

Please sign in to comment.