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

epoching API: validator lifecycle #109

Merged
merged 31 commits into from
Sep 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c381929
init
SebastianElvis Aug 31, 2022
a5f87b7
fix CI
SebastianElvis Aug 31, 2022
e9174be
fix
SebastianElvis Aug 31, 2022
18affe4
minor
SebastianElvis Sep 1, 2022
c5360a2
init
SebastianElvis Sep 1, 2022
eee5c63
distinguish created vs bonded
SebastianElvis Sep 1, 2022
02f314c
minor
SebastianElvis Sep 1, 2022
eab8cab
init impl
SebastianElvis Sep 1, 2022
1d57202
pass CI
SebastianElvis Sep 1, 2022
fe7c550
record ckpt-assisted unbonding time
SebastianElvis Sep 1, 2022
0f4ff6f
minor fixes
SebastianElvis Sep 1, 2022
e974af6
created -> bonded
SebastianElvis Sep 1, 2022
a2b7c3a
comments and minor fixes
SebastianElvis Sep 1, 2022
9fffb70
record height only when operator undelegates
SebastianElvis Sep 1, 2022
527b82d
Merge branch 'main' into epoching-epoch-events-api
SebastianElvis Sep 1, 2022
54a3127
tests
SebastianElvis Sep 2, 2022
91cf670
prepare for fixing CI
SebastianElvis Sep 2, 2022
7189c38
reject msgs during 0 epoch
SebastianElvis Sep 2, 2022
39485d2
reject msgs in 0epoch
SebastianElvis Sep 2, 2022
d592381
update event
SebastianElvis Sep 2, 2022
abe11a4
fix CI
SebastianElvis Sep 2, 2022
146068f
Merge branch 'main' into epoching-epoch-events-api
SebastianElvis Sep 2, 2022
b73ba34
tidy
SebastianElvis Sep 2, 2022
39ee618
Merge branch 'epoching-epoch-events-api' into epoching-val-lifecycle
SebastianElvis Sep 2, 2022
83b3aff
mock stuff
SebastianElvis Sep 2, 2022
dd80914
fix multiple
SebastianElvis Sep 2, 2022
0ab0c47
tidy
SebastianElvis Sep 2, 2022
86d9ffb
go mod tidy
SebastianElvis Sep 2, 2022
b0be710
Merge branch 'main' into epoching-val-lifecycle
SebastianElvis Sep 4, 2022
5277a46
resolve duplicated stuff when resolving conflicts
SebastianElvis Sep 4, 2022
33d3094
minor
SebastianElvis Sep 4, 2022
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
14 changes: 0 additions & 14 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,6 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
Expand Down Expand Up @@ -556,7 +555,6 @@ 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.9.0 h1:npqHz788dryJiR/l6K/RUQAyh2SwV91+d1dnh4RjO9w=
github.com/jhump/protoreflect v1.9.0/go.mod h1:7GcYQDdMU/O/BBrl/cX6PNHpXh6cenjd8pneu5yW7Tg=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
Expand Down Expand Up @@ -698,7 +696,6 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS
github.com/neilotoole/errgroup v0.1.5/go.mod h1:Q2nLGf+594h0CLBs/Mbg6qOr7GtqDK7C2S41udRnToE=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
Expand All @@ -714,7 +711,6 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
Expand Down Expand Up @@ -747,11 +743,6 @@ github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa
github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA=
github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs=
github.com/otiai10/copy v1.6.0 h1:IinKAryFFuPONZ7cm6T6E2QX/vcJwSnlaA5lfoaXIiQ=
github.com/otiai10/copy v1.6.0/go.mod h1:XWfuS3CrI0R6IE0FbgHsEazaXO8G0LpMp9o8tos0x4E=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
github.com/otiai10/mint v1.3.2/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
Expand Down Expand Up @@ -1270,7 +1261,6 @@ golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d h1:Zu/JngovGLVi6t2J3nmAf3AoTDwuzw85YZ3b9o4yU7s=
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
Expand Down Expand Up @@ -1337,10 +1327,8 @@ golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWc
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
Expand Down Expand Up @@ -1474,7 +1462,6 @@ google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ6
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211223182754-3ac035c7e7cb/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220719170305-83ca9fad585f h1:P8EiVSxZwC6xH2niv2N66aqwMtYFg+D54gbjpcqKJtM=
google.golang.org/genproto v0.0.0-20220719170305-83ca9fad585f/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE=
google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o=
Expand All @@ -1490,7 +1477,6 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
Expand Down
18 changes: 18 additions & 0 deletions proto/babylon/epoching/v1/epoching.proto
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,21 @@ message QueuedMessage {
// TODO: after we bump to Cosmos SDK v0.46, add MsgCancelUnbondingDelegation
}
}

enum ValState {
CREATED = 0;
BONDED = 1;
UNBONDING = 2;
UNBONDED = 3;
REMOVED = 4;
}

message ValStateUpdate {
ValState state = 1;
uint64 height = 2;
}

message ValidatorLifecycle {
string val_addr = 1;
repeated ValStateUpdate val_life = 2;
}
13 changes: 13 additions & 0 deletions proto/babylon/epoching/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ service Query {
rpc EpochMsgs(QueryEpochMsgsRequest) returns (QueryEpochMsgsResponse) {
option (google.api.http).get = "/babylon/epoching/v1/epoch_msgs/{epoch_num}";
}

// ValidatorLifecycle queries the lifecycle of a given validator
rpc ValidatorLifecycle(QueryValidatorLifecycleRequest) returns (QueryValidatorLifecycleResponse) {
option (google.api.http).get = "/babylon/epoching/v1/validator_lifecycle/{val_addr}";
}
}

// QueryParamsRequest is request type for the Query/Params RPC method.
Expand Down Expand Up @@ -63,3 +68,11 @@ message QueryEpochMsgsResponse {
// pagination defines the pagination in the response
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}

message QueryValidatorLifecycleRequest {
string val_addr = 1;
}

message QueryValidatorLifecycleResponse {
ValidatorLifecycle val_life = 1;
}
9 changes: 8 additions & 1 deletion x/checkpointing/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package keeper
import (
"context"
"errors"

epochingtypes "github.com/babylonchain/babylon/x/epoching/types"
ed255192 "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -39,14 +40,20 @@ func (m msgServer) AddBlsSig(goCtx context.Context, msg *types.MsgAddBlsSig) (*t
// the epoching module
func (m msgServer) WrappedCreateValidator(goCtx context.Context, msg *types.MsgWrappedCreateValidator) (*types.MsgWrappedCreateValidatorResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

// TODO: porting other verification rules from staking module
valAddr, err := sdk.ValAddressFromBech32(msg.MsgCreateValidator.ValidatorAddress)
if err != nil {
return nil, err
}

// verify Proof-of-Possession
ok := msg.VerifyPoP(&ed255192.PubKey{Key: msg.MsgCreateValidator.Pubkey.Value})
if !ok {
return nil, errors.New("the proof-of-possession is not valid")
}

// store BLS public key
valAddr, err := sdk.ValAddressFromBech32(msg.MsgCreateValidator.ValidatorAddress)
err = m.k.CreateRegistration(ctx, *msg.Key.Pubkey, valAddr)
if err != nil {
return nil, err
Expand Down
12 changes: 11 additions & 1 deletion x/epoching/keeper/epoch_msg_queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,11 @@ func (k Keeper) GetCurrentEpochMsgs(ctx sdk.Context) []*types.QueuedMessage {

// HandleQueuedMsg unwraps a QueuedMessage and forwards it to the staking module
func (k Keeper) HandleQueuedMsg(ctx sdk.Context, msg *types.QueuedMessage) (*sdk.Result, error) {
var unwrappedMsgWithType sdk.Msg
var (
unwrappedMsgWithType sdk.Msg
err error
)

// TODO (non-urgent): after we bump to Cosmos SDK v0.46, add MsgCancelUnbondingDelegation
switch unwrappedMsg := msg.Msg.(type) {
case *types.QueuedMessage_MsgCreateValidator:
Expand All @@ -115,6 +119,11 @@ func (k Keeper) HandleQueuedMsg(ctx sdk.Context, msg *types.QueuedMessage) (*sdk
panic(sdkerrors.Wrap(types.ErrInvalidQueuedMessageType, msg.String()))
}

// failed to decode validator address
if err != nil {
panic(err)
}

// get the handler function from router
handler := k.router.Handler(unwrappedMsgWithType)

Expand All @@ -128,6 +137,7 @@ func (k Keeper) HandleQueuedMsg(ctx sdk.Context, msg *types.QueuedMessage) (*sdk
return result, err
}

// release the cache
msCache.Write()

return result, nil
Expand Down
23 changes: 23 additions & 0 deletions x/epoching/keeper/epoch_msg_queue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ func FuzzHandleQueuedMsg_MsgWrappedDelegate(f *testing.F) {
valPower, err := keeper.GetCurrentValidatorVotingPower(ctx, val)
require.NoError(t, err)

// ensure the validator's lifecycle data is generated
lc := keeper.GetValLifecycle(ctx, val)
require.NotNil(t, lc)
require.Equal(t, 1, len(lc.ValLife))
require.Equal(t, types.ValState_CREATED, lc.ValLife[0].State)
require.Equal(t, uint64(0), lc.ValLife[0].Height)

// delegate a random amount of tokens to the validator
numNewDels := rand.Int63n(1000) + 1
for i := int64(0); i < numNewDels; i++ {
Expand Down Expand Up @@ -149,6 +156,13 @@ func FuzzHandleQueuedMsg_MsgWrappedUndelegate(f *testing.F) {
valPower, err := helper.EpochingKeeper.GetCurrentValidatorVotingPower(ctx, val)
require.NoError(t, err)

// ensure the validator's lifecycle data is generated
lc := keeper.GetValLifecycle(ctx, val)
require.NotNil(t, lc)
require.Equal(t, 1, len(lc.ValLife))
require.Equal(t, types.ValState_CREATED, lc.ValLife[0].State)
require.Equal(t, uint64(0), lc.ValLife[0].Height)

// unbond a random amount of tokens from the validator
// Note that for any pair of delegator and validator, there can be `<=DefaultMaxEntries=7` concurrent undelegations at any time slot
// Otherwise, only `DefaultMaxEntries` undelegations will be processed at this height and the rest will be rejected
Expand Down Expand Up @@ -225,6 +239,15 @@ func FuzzHandleQueuedMsg_MsgWrappedBeginRedelegate(f *testing.F) {
require.NoError(t, err)
require.Equal(t, val1Power, val2Power)

// ensure the validator's lifecycle data is generated
for _, val := range []sdk.ValAddress{val1, val2} {
lc := keeper.GetValLifecycle(ctx, val)
require.NotNil(t, lc)
require.Equal(t, 1, len(lc.ValLife))
require.Equal(t, types.ValState_CREATED, lc.ValLife[0].State)
require.Equal(t, uint64(0), lc.ValLife[0].Height)
}

// redelegate a random amount of tokens from val1 to val2
// same as undelegation, there can be `<=DefaultMaxEntries=7` concurrent redelegation requests for any tuple (delegatorAddr, srcValidatorAddr, dstValidatorAddr)
// See https://github.com/cosmos/cosmos-sdk/blob/v0.45.5/x/staking/keeper/delegation.go#L908-L910
Expand Down
14 changes: 14 additions & 0 deletions x/epoching/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,17 @@ func (k Keeper) EpochMsgs(c context.Context, req *types.QueryEpochMsgsRequest) (
}
return resp, nil
}

// ValidatorLifecycle handles the QueryValidatorLifecycleRequest query
func (k Keeper) ValidatorLifecycle(c context.Context, req *types.QueryValidatorLifecycleRequest) (*types.QueryValidatorLifecycleResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
valAddr, err := sdk.ValAddressFromBech32(req.ValAddr)
if err != nil {
return nil, err
}
lc := k.GetValLifecycle(ctx, valAddr)
return &types.QueryValidatorLifecycleResponse{
ValLife: lc,
}, nil
// TODO: test this API
}
15 changes: 12 additions & 3 deletions x/epoching/keeper/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,24 @@ func (h Hooks) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, f
}
}

// Other staking hooks that are not used in the epoching module
func (h Hooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {}
func (h Hooks) BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) {}
func (h Hooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {
h.k.RecordNewValState(ctx, valAddr, types.ValState_CREATED)
}

func (h Hooks) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
h.k.RecordNewValState(ctx, valAddr, types.ValState_REMOVED)
}

func (h Hooks) AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
h.k.RecordNewValState(ctx, valAddr, types.ValState_BONDED)
}

func (h Hooks) AfterValidatorBeginUnbonding(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
h.k.RecordNewValState(ctx, valAddr, types.ValState_UNBONDING)
}

// Other staking hooks that are not used in the epoching module
func (h Hooks) BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) {}
func (h Hooks) BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
}
func (h Hooks) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
Expand Down
64 changes: 63 additions & 1 deletion x/epoching/keeper/modified_staking.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package keeper

import (
"fmt"

"github.com/babylonchain/babylon/x/epoching/types"
abci "github.com/tendermint/tendermint/abci/types"

sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -20,7 +23,7 @@ func (k *Keeper) ApplyMatureUnbonding(ctx sdk.Context, epochBoundaryHeader tmpro

// unbond all mature validators till the epoch boundary from the unbonding queue
ctx.WithBlockHeader(epochBoundaryHeader)
k.stk.UnbondAllMatureValidators(ctx)
k.UnbondAllMatureValidators(ctx)
ctx.WithBlockHeader(currHeader)

// get all mature unbonding delegations the epoch boundary from the ubd queue.
Expand Down Expand Up @@ -108,3 +111,62 @@ func (k *Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) []abci.Valid

return validatorUpdates
}

// UnbondAllMatureValidators unbonds all the mature unbonding validators that have finished their unbonding period.
// In addition, Babylon records the height of unbonding for each mature validator
// (adapted from https://github.com/cosmos/cosmos-sdk/blob/v0.45.5/x/staking/keeper/validator.go#L396-L447)
func (k Keeper) UnbondAllMatureValidators(ctx sdk.Context) {
store := ctx.KVStore(k.storeKey)

blockTime := ctx.BlockTime()
blockHeight := ctx.BlockHeight()

// unbondingValIterator will contains all validator addresses indexed under
// the ValidatorQueueKey prefix. Note, the entire index key is composed as
// ValidatorQueueKey | timeBzLen (8-byte big endian) | timeBz | heightBz (8-byte big endian),
// so it may be possible that certain validator addresses that are iterated
// over are not ready to unbond, so an explicit check is required.
unbondingValIterator := k.stk.ValidatorQueueIterator(ctx, blockTime, blockHeight)
defer unbondingValIterator.Close()

for ; unbondingValIterator.Valid(); unbondingValIterator.Next() {
key := unbondingValIterator.Key()
keyTime, keyHeight, err := stakingtypes.ParseValidatorQueueKey(key)
if err != nil {
panic(fmt.Errorf("failed to parse unbonding key: %w", err))
}

// All addresses for the given key have the same unbonding height and time.
// We only unbond if the height and time are less than the current height
// and time.
if keyHeight <= blockHeight && (keyTime.Before(blockTime) || keyTime.Equal(blockTime)) {
addrs := stakingtypes.ValAddresses{}
k.cdc.MustUnmarshal(unbondingValIterator.Value(), &addrs)

for _, valAddr := range addrs.Addresses {
addr, err := sdk.ValAddressFromBech32(valAddr)
if err != nil {
panic(err)
}
val, found := k.stk.GetValidator(ctx, addr)
if !found {
panic("validator in the unbonding queue was not found")
}

if !val.IsUnbonding() {
panic("unexpected validator in unbonding queue; status was not unbonding")
}

val = k.stk.UnbondingToUnbonded(ctx, val)
if val.GetDelegatorShares().IsZero() {
k.stk.RemoveValidator(ctx, val.GetOperator())
}

// Babylon modification: record the height when this validator becomes unbonded
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks for adding these comments!

k.RecordNewValState(ctx, addr, types.ValState_UNBONDED)
}

store.Delete(key)
}
}
}
Loading