feat(x/staking): implement RotateConsPubKey method (#18188)

This commit is contained in:
atheeshp 2023-11-15 12:29:50 +05:30 committed by GitHub
parent e269c6d5db
commit 0f8c6c2c12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 496 additions and 231 deletions

View File

@ -13409,8 +13409,8 @@ func (x *fastReflection_ConsPubKeyRotationHistory) Interface() protoreflect.Prot
// While iterating, mutating operations may only be performed
// on the current field descriptor.
func (x *fastReflection_ConsPubKeyRotationHistory) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
if x.OperatorAddress != "" {
value := protoreflect.ValueOfString(x.OperatorAddress)
if len(x.OperatorAddress) != 0 {
value := protoreflect.ValueOfBytes(x.OperatorAddress)
if !f(fd_ConsPubKeyRotationHistory_operator_address, value) {
return
}
@ -13455,7 +13455,7 @@ func (x *fastReflection_ConsPubKeyRotationHistory) Range(f func(protoreflect.Fie
func (x *fastReflection_ConsPubKeyRotationHistory) Has(fd protoreflect.FieldDescriptor) bool {
switch fd.FullName() {
case "cosmos.staking.v1beta1.ConsPubKeyRotationHistory.operator_address":
return x.OperatorAddress != ""
return len(x.OperatorAddress) != 0
case "cosmos.staking.v1beta1.ConsPubKeyRotationHistory.old_cons_pubkey":
return x.OldConsPubkey != nil
case "cosmos.staking.v1beta1.ConsPubKeyRotationHistory.new_cons_pubkey":
@ -13481,7 +13481,7 @@ func (x *fastReflection_ConsPubKeyRotationHistory) Has(fd protoreflect.FieldDesc
func (x *fastReflection_ConsPubKeyRotationHistory) Clear(fd protoreflect.FieldDescriptor) {
switch fd.FullName() {
case "cosmos.staking.v1beta1.ConsPubKeyRotationHistory.operator_address":
x.OperatorAddress = ""
x.OperatorAddress = nil
case "cosmos.staking.v1beta1.ConsPubKeyRotationHistory.old_cons_pubkey":
x.OldConsPubkey = nil
case "cosmos.staking.v1beta1.ConsPubKeyRotationHistory.new_cons_pubkey":
@ -13508,7 +13508,7 @@ func (x *fastReflection_ConsPubKeyRotationHistory) Get(descriptor protoreflect.F
switch descriptor.FullName() {
case "cosmos.staking.v1beta1.ConsPubKeyRotationHistory.operator_address":
value := x.OperatorAddress
return protoreflect.ValueOfString(value)
return protoreflect.ValueOfBytes(value)
case "cosmos.staking.v1beta1.ConsPubKeyRotationHistory.old_cons_pubkey":
value := x.OldConsPubkey
return protoreflect.ValueOfMessage(value.ProtoReflect())
@ -13542,7 +13542,7 @@ func (x *fastReflection_ConsPubKeyRotationHistory) Get(descriptor protoreflect.F
func (x *fastReflection_ConsPubKeyRotationHistory) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) {
switch fd.FullName() {
case "cosmos.staking.v1beta1.ConsPubKeyRotationHistory.operator_address":
x.OperatorAddress = value.Interface().(string)
x.OperatorAddress = value.Bytes()
case "cosmos.staking.v1beta1.ConsPubKeyRotationHistory.old_cons_pubkey":
x.OldConsPubkey = value.Message().Interface().(*anypb.Any)
case "cosmos.staking.v1beta1.ConsPubKeyRotationHistory.new_cons_pubkey":
@ -13604,7 +13604,7 @@ func (x *fastReflection_ConsPubKeyRotationHistory) Mutable(fd protoreflect.Field
func (x *fastReflection_ConsPubKeyRotationHistory) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value {
switch fd.FullName() {
case "cosmos.staking.v1beta1.ConsPubKeyRotationHistory.operator_address":
return protoreflect.ValueOfString("")
return protoreflect.ValueOfBytes(nil)
case "cosmos.staking.v1beta1.ConsPubKeyRotationHistory.old_cons_pubkey":
m := new(anypb.Any)
return protoreflect.ValueOfMessage(m.ProtoReflect())
@ -13840,7 +13840,7 @@ func (x *fastReflection_ConsPubKeyRotationHistory) ProtoMethods() *protoiface.Me
if wireType != 2 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field OperatorAddress", wireType)
}
var stringLen uint64
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow
@ -13850,23 +13850,25 @@ func (x *fastReflection_ConsPubKeyRotationHistory) ProtoMethods() *protoiface.Me
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
if byteLen < 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength
}
postIndex := iNdEx + intStringLen
postIndex := iNdEx + byteLen
if postIndex < 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength
}
if postIndex > l {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF
}
x.OperatorAddress = string(dAtA[iNdEx:postIndex])
x.OperatorAddress = append(x.OperatorAddress[:0], dAtA[iNdEx:postIndex]...)
if x.OperatorAddress == nil {
x.OperatorAddress = []byte{}
}
iNdEx = postIndex
case 2:
if wireType != 2 {
@ -14033,7 +14035,7 @@ func (x *fastReflection_ConsPubKeyRotationHistory) ProtoMethods() *protoiface.Me
var _ protoreflect.List = (*_ValAddrsOfRotatedConsKeys_1_list)(nil)
type _ValAddrsOfRotatedConsKeys_1_list struct {
list *[]string
list *[][]byte
}
func (x *_ValAddrsOfRotatedConsKeys_1_list) Len() int {
@ -14044,17 +14046,17 @@ func (x *_ValAddrsOfRotatedConsKeys_1_list) Len() int {
}
func (x *_ValAddrsOfRotatedConsKeys_1_list) Get(i int) protoreflect.Value {
return protoreflect.ValueOfString((*x.list)[i])
return protoreflect.ValueOfBytes((*x.list)[i])
}
func (x *_ValAddrsOfRotatedConsKeys_1_list) Set(i int, value protoreflect.Value) {
valueUnwrapped := value.String()
valueUnwrapped := value.Bytes()
concreteValue := valueUnwrapped
(*x.list)[i] = concreteValue
}
func (x *_ValAddrsOfRotatedConsKeys_1_list) Append(value protoreflect.Value) {
valueUnwrapped := value.String()
valueUnwrapped := value.Bytes()
concreteValue := valueUnwrapped
*x.list = append(*x.list, concreteValue)
}
@ -14068,8 +14070,8 @@ func (x *_ValAddrsOfRotatedConsKeys_1_list) Truncate(n int) {
}
func (x *_ValAddrsOfRotatedConsKeys_1_list) NewElement() protoreflect.Value {
v := ""
return protoreflect.ValueOfString(v)
var v []byte
return protoreflect.ValueOfBytes(v)
}
func (x *_ValAddrsOfRotatedConsKeys_1_list) IsValid() bool {
@ -14261,7 +14263,7 @@ func (x *fastReflection_ValAddrsOfRotatedConsKeys) Mutable(fd protoreflect.Field
switch fd.FullName() {
case "cosmos.staking.v1beta1.ValAddrsOfRotatedConsKeys.addresses":
if x.Addresses == nil {
x.Addresses = []string{}
x.Addresses = [][]byte{}
}
value := &_ValAddrsOfRotatedConsKeys_1_list{list: &x.Addresses}
return protoreflect.ValueOfList(value)
@ -14279,7 +14281,7 @@ func (x *fastReflection_ValAddrsOfRotatedConsKeys) Mutable(fd protoreflect.Field
func (x *fastReflection_ValAddrsOfRotatedConsKeys) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value {
switch fd.FullName() {
case "cosmos.staking.v1beta1.ValAddrsOfRotatedConsKeys.addresses":
list := []string{}
list := [][]byte{}
return protoreflect.ValueOfList(&_ValAddrsOfRotatedConsKeys_1_list{list: &list})
default:
if fd.IsExtension() {
@ -14351,8 +14353,8 @@ func (x *fastReflection_ValAddrsOfRotatedConsKeys) ProtoMethods() *protoiface.Me
var l int
_ = l
if len(x.Addresses) > 0 {
for _, s := range x.Addresses {
l = len(s)
for _, b := range x.Addresses {
l = len(b)
n += 1 + l + runtime.Sov(uint64(l))
}
}
@ -14447,7 +14449,7 @@ func (x *fastReflection_ValAddrsOfRotatedConsKeys) ProtoMethods() *protoiface.Me
if wireType != 2 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType)
}
var stringLen uint64
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow
@ -14457,23 +14459,23 @@ func (x *fastReflection_ValAddrsOfRotatedConsKeys) ProtoMethods() *protoiface.Me
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
if byteLen < 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength
}
postIndex := iNdEx + intStringLen
postIndex := iNdEx + byteLen
if postIndex < 0 {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength
}
if postIndex > l {
return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF
}
x.Addresses = append(x.Addresses, string(dAtA[iNdEx:postIndex]))
x.Addresses = append(x.Addresses, make([]byte, postIndex-iNdEx))
copy(x.Addresses[len(x.Addresses)-1], dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
@ -15935,7 +15937,7 @@ type ConsPubKeyRotationHistory struct {
unknownFields protoimpl.UnknownFields
// operator_address defines the address of the validator's operator; bech encoded in JSON.
OperatorAddress string `protobuf:"bytes,1,opt,name=operator_address,json=operatorAddress,proto3" json:"operator_address,omitempty"`
OperatorAddress []byte `protobuf:"bytes,1,opt,name=operator_address,json=operatorAddress,proto3" json:"operator_address,omitempty"`
// old_cons_pubkey is the old consensus public key of the validator, as a Protobuf Any.
OldConsPubkey *anypb.Any `protobuf:"bytes,2,opt,name=old_cons_pubkey,json=oldConsPubkey,proto3" json:"old_cons_pubkey,omitempty"`
// new_cons_pubkey is the new consensus public key of the validator, as a Protobuf Any.
@ -15966,11 +15968,11 @@ func (*ConsPubKeyRotationHistory) Descriptor() ([]byte, []int) {
return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{22}
}
func (x *ConsPubKeyRotationHistory) GetOperatorAddress() string {
func (x *ConsPubKeyRotationHistory) GetOperatorAddress() []byte {
if x != nil {
return x.OperatorAddress
}
return ""
return nil
}
func (x *ConsPubKeyRotationHistory) GetOldConsPubkey() *anypb.Any {
@ -16008,7 +16010,7 @@ type ValAddrsOfRotatedConsKeys struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Addresses []string `protobuf:"bytes,1,rep,name=addresses,proto3" json:"addresses,omitempty"`
Addresses [][]byte `protobuf:"bytes,1,rep,name=addresses,proto3" json:"addresses,omitempty"`
}
func (x *ValAddrsOfRotatedConsKeys) Reset() {
@ -16031,7 +16033,7 @@ func (*ValAddrsOfRotatedConsKeys) Descriptor() ([]byte, []int) {
return file_cosmos_staking_v1beta1_staking_proto_rawDescGZIP(), []int{23}
}
func (x *ValAddrsOfRotatedConsKeys) GetAddresses() []string {
func (x *ValAddrsOfRotatedConsKeys) GetAddresses() [][]byte {
if x != nil {
return x.Addresses
}
@ -16416,7 +16418,7 @@ var file_cosmos_staking_v1beta1_staking_proto_rawDesc = []byte{
0x61, 0x74, 0x65, 0x73, 0x22, 0xd0, 0x02, 0x0a, 0x19, 0x43, 0x6f, 0x6e, 0x73, 0x50, 0x75, 0x62,
0x4b, 0x65, 0x79, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x69, 0x73, 0x74, 0x6f,
0x72, 0x79, 0x12, 0x29, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61,
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6f, 0x70,
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6f, 0x70,
0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x56, 0x0a,
0x0f, 0x6f, 0x6c, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
@ -16437,7 +16439,7 @@ var file_cosmos_staking_v1beta1_staking_proto_rawDesc = []byte{
0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, 0x00, 0x22, 0x53, 0x0a, 0x19, 0x56, 0x61, 0x6c, 0x41, 0x64,
0x64, 0x72, 0x73, 0x4f, 0x66, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x73,
0x4b, 0x65, 0x79, 0x73, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65,
0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73,
0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73,
0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e,
0x67, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x2a, 0xb6, 0x01, 0x0a,
0x0a, 0x42, 0x6f, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2c, 0x0a, 0x17, 0x42,

View File

@ -57,7 +57,7 @@ type MsgClient interface {
UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error)
// RotateConsPubKey defines an operation for rotating the consensus keys
// of a validator.
// Since: cosmos-sdk 0.48
// Since: cosmos-sdk 0.51
RotateConsPubKey(ctx context.Context, in *MsgRotateConsPubKey, opts ...grpc.CallOption) (*MsgRotateConsPubKeyResponse, error)
}
@ -169,7 +169,7 @@ type MsgServer interface {
UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error)
// RotateConsPubKey defines an operation for rotating the consensus keys
// of a validator.
// Since: cosmos-sdk 0.48
// Since: cosmos-sdk 0.51
RotateConsPubKey(context.Context, *MsgRotateConsPubKey) (*MsgRotateConsPubKeyResponse, error)
mustEmbedUnimplementedMsgServer()
}

View File

@ -16,7 +16,7 @@ func TestMultiIndex(t *testing.T) {
return value.City, nil
})
// we crete two reference keys for primary key 1 and 2 associated with "milan"
// we create two reference keys for primary key 1 and 2 associated with "milan"
require.NoError(t, mi.Reference(ctx, 1, company{City: "milan"}, func() (company, error) { return company{}, collections.ErrNotFound }))
require.NoError(t, mi.Reference(ctx, 2, company{City: "milan"}, func() (company, error) { return company{}, collections.ErrNotFound }))

View File

@ -415,7 +415,7 @@ message ConsPubKeyRotationHistory {
option (gogoproto.goproto_getters) = false;
// operator_address defines the address of the validator's operator; bech encoded in JSON.
string operator_address = 1;
bytes operator_address = 1;
// old_cons_pubkey is the old consensus public key of the validator, as a Protobuf Any.
google.protobuf.Any old_cons_pubkey = 2 [(cosmos_proto.accepts_interface) = "cosmos.crypto.PubKey"];
// new_cons_pubkey is the new consensus public key of the validator, as a Protobuf Any.
@ -429,5 +429,5 @@ message ConsPubKeyRotationHistory {
// ValAddrsOfRotatedConsKeys contains the array of validator addresses which rotated their keys
// This is to block the validator's next rotation till unbonding period.
message ValAddrsOfRotatedConsKeys {
repeated string addresses = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
repeated bytes addresses = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}

View File

@ -48,7 +48,7 @@ service Msg {
// RotateConsPubKey defines an operation for rotating the consensus keys
// of a validator.
// Since: cosmos-sdk 0.48
// Since: cosmos-sdk 0.51
rpc RotateConsPubKey(MsgRotateConsPubKey) returns (MsgRotateConsPubKeyResponse);
}

View File

@ -9,8 +9,8 @@ import (
reflect "reflect"
address "cosmossdk.io/core/address"
types0 "cosmossdk.io/x/bank/types"
types "github.com/cosmos/cosmos-sdk/types"
types "cosmossdk.io/x/bank/types"
types0 "github.com/cosmos/cosmos-sdk/types"
gomock "github.com/golang/mock/gomock"
)
@ -52,10 +52,10 @@ func (mr *MockAccountKeeperMockRecorder) AddressCodec() *gomock.Call {
}
// GetAccount mocks base method.
func (m *MockAccountKeeper) GetAccount(arg0 context.Context, arg1 types.AccAddress) types.AccountI {
func (m *MockAccountKeeper) GetAccount(arg0 context.Context, arg1 types0.AccAddress) types0.AccountI {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetAccount", arg0, arg1)
ret0, _ := ret[0].(types.AccountI)
ret0, _ := ret[0].(types0.AccountI)
return ret0
}
@ -66,10 +66,10 @@ func (mr *MockAccountKeeperMockRecorder) GetAccount(arg0, arg1 interface{}) *gom
}
// NewAccount mocks base method.
func (m *MockAccountKeeper) NewAccount(arg0 context.Context, arg1 types.AccountI) types.AccountI {
func (m *MockAccountKeeper) NewAccount(arg0 context.Context, arg1 types0.AccountI) types0.AccountI {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NewAccount", arg0, arg1)
ret0, _ := ret[0].(types.AccountI)
ret0, _ := ret[0].(types0.AccountI)
return ret0
}
@ -80,7 +80,7 @@ func (mr *MockAccountKeeperMockRecorder) NewAccount(arg0, arg1 interface{}) *gom
}
// RemoveAccount mocks base method.
func (m *MockAccountKeeper) RemoveAccount(ctx context.Context, acc types.AccountI) {
func (m *MockAccountKeeper) RemoveAccount(ctx context.Context, acc types0.AccountI) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RemoveAccount", ctx, acc)
}
@ -92,7 +92,7 @@ func (mr *MockAccountKeeperMockRecorder) RemoveAccount(ctx, acc interface{}) *go
}
// SetAccount mocks base method.
func (m *MockAccountKeeper) SetAccount(arg0 context.Context, arg1 types.AccountI) {
func (m *MockAccountKeeper) SetAccount(arg0 context.Context, arg1 types0.AccountI) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SetAccount", arg0, arg1)
}
@ -127,10 +127,10 @@ func (m *MockBankKeeper) EXPECT() *MockBankKeeperMockRecorder {
}
// Burn mocks base method.
func (m *MockBankKeeper) Burn(arg0 context.Context, arg1 *types0.MsgBurn) (*types0.MsgBurnResponse, error) {
func (m *MockBankKeeper) Burn(arg0 context.Context, arg1 *types.MsgBurn) (*types.MsgBurnResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Burn", arg0, arg1)
ret0, _ := ret[0].(*types0.MsgBurnResponse)
ret0, _ := ret[0].(*types.MsgBurnResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@ -142,10 +142,10 @@ func (mr *MockBankKeeperMockRecorder) Burn(arg0, arg1 interface{}) *gomock.Call
}
// GetAllBalances mocks base method.
func (m *MockBankKeeper) GetAllBalances(ctx context.Context, addr types.AccAddress) types.Coins {
func (m *MockBankKeeper) GetAllBalances(ctx context.Context, addr types0.AccAddress) types0.Coins {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetAllBalances", ctx, addr)
ret0, _ := ret[0].(types.Coins)
ret0, _ := ret[0].(types0.Coins)
return ret0
}
@ -156,7 +156,7 @@ func (mr *MockBankKeeperMockRecorder) GetAllBalances(ctx, addr interface{}) *gom
}
// MintCoins mocks base method.
func (m *MockBankKeeper) MintCoins(ctx context.Context, moduleName string, amt types.Coins) error {
func (m *MockBankKeeper) MintCoins(ctx context.Context, moduleName string, amt types0.Coins) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MintCoins", ctx, moduleName, amt)
ret0, _ := ret[0].(error)
@ -170,10 +170,10 @@ func (mr *MockBankKeeperMockRecorder) MintCoins(ctx, moduleName, amt interface{}
}
// MultiSend mocks base method.
func (m *MockBankKeeper) MultiSend(arg0 context.Context, arg1 *types0.MsgMultiSend) (*types0.MsgMultiSendResponse, error) {
func (m *MockBankKeeper) MultiSend(arg0 context.Context, arg1 *types.MsgMultiSend) (*types.MsgMultiSendResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "MultiSend", arg0, arg1)
ret0, _ := ret[0].(*types0.MsgMultiSendResponse)
ret0, _ := ret[0].(*types.MsgMultiSendResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@ -185,10 +185,10 @@ func (mr *MockBankKeeperMockRecorder) MultiSend(arg0, arg1 interface{}) *gomock.
}
// Send mocks base method.
func (m *MockBankKeeper) Send(arg0 context.Context, arg1 *types0.MsgSend) (*types0.MsgSendResponse, error) {
func (m *MockBankKeeper) Send(arg0 context.Context, arg1 *types.MsgSend) (*types.MsgSendResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Send", arg0, arg1)
ret0, _ := ret[0].(*types0.MsgSendResponse)
ret0, _ := ret[0].(*types.MsgSendResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@ -200,7 +200,7 @@ func (mr *MockBankKeeperMockRecorder) Send(arg0, arg1 interface{}) *gomock.Call
}
// SendCoinsFromModuleToAccount mocks base method.
func (m *MockBankKeeper) SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error {
func (m *MockBankKeeper) SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr types0.AccAddress, amt types0.Coins) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SendCoinsFromModuleToAccount", ctx, senderModule, recipientAddr, amt)
ret0, _ := ret[0].(error)
@ -214,10 +214,10 @@ func (mr *MockBankKeeperMockRecorder) SendCoinsFromModuleToAccount(ctx, senderMo
}
// SetSendEnabled mocks base method.
func (m *MockBankKeeper) SetSendEnabled(arg0 context.Context, arg1 *types0.MsgSetSendEnabled) (*types0.MsgSetSendEnabledResponse, error) {
func (m *MockBankKeeper) SetSendEnabled(arg0 context.Context, arg1 *types.MsgSetSendEnabled) (*types.MsgSetSendEnabledResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SetSendEnabled", arg0, arg1)
ret0, _ := ret[0].(*types0.MsgSetSendEnabledResponse)
ret0, _ := ret[0].(*types.MsgSetSendEnabledResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@ -229,10 +229,10 @@ func (mr *MockBankKeeperMockRecorder) SetSendEnabled(arg0, arg1 interface{}) *go
}
// SpendableCoins mocks base method.
func (m *MockBankKeeper) SpendableCoins(ctx context.Context, addr types.AccAddress) types.Coins {
func (m *MockBankKeeper) SpendableCoins(ctx context.Context, addr types0.AccAddress) types0.Coins {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SpendableCoins", ctx, addr)
ret0, _ := ret[0].(types.Coins)
ret0, _ := ret[0].(types0.Coins)
return ret0
}
@ -243,10 +243,10 @@ func (mr *MockBankKeeperMockRecorder) SpendableCoins(ctx, addr interface{}) *gom
}
// UpdateParams mocks base method.
func (m *MockBankKeeper) UpdateParams(arg0 context.Context, arg1 *types0.MsgUpdateParams) (*types0.MsgUpdateParamsResponse, error) {
func (m *MockBankKeeper) UpdateParams(arg0 context.Context, arg1 *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpdateParams", arg0, arg1)
ret0, _ := ret[0].(*types0.MsgUpdateParamsResponse)
ret0, _ := ret[0].(*types.MsgUpdateParamsResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}

View File

@ -0,0 +1,93 @@
package keeper
import (
"bytes"
"context"
"time"
"cosmossdk.io/collections"
"cosmossdk.io/x/staking/types"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// maxRotations is the value of max rotations can be made in unbonding period for a validator.
const maxRotations = 1
// setConsPubKeyRotationHistory sets the consensus key rotation of a validator into state
func (k Keeper) setConsPubKeyRotationHistory(
ctx context.Context, valAddr sdk.ValAddress,
oldPubKey, newPubKey *codectypes.Any, fee sdk.Coin,
) error {
sdkCtx := sdk.UnwrapSDKContext(ctx)
height := uint64(sdkCtx.BlockHeight())
history := types.ConsPubKeyRotationHistory{
OperatorAddress: valAddr.Bytes(),
OldConsPubkey: oldPubKey,
NewConsPubkey: newPubKey,
Height: height,
Fee: fee,
}
err := k.RotationHistory.Set(ctx, valAddr, history)
if err != nil {
return err
}
ubdTime, err := k.UnbondingTime(ctx)
if err != nil {
return err
}
queueTime := sdkCtx.BlockHeader().Time.Add(ubdTime)
if err := k.ValidatorConsensusKeyRotationRecordIndexKey.Set(ctx, collections.Join(valAddr.Bytes(), queueTime)); err != nil {
return err
}
return k.setConsKeyQueue(ctx, queueTime, valAddr)
}
// exceedsMaxRotations returns true if the key rotations exceed the limit, currently we are limiting one rotation for unbonding period.
func (k Keeper) exceedsMaxRotations(ctx context.Context, valAddr sdk.ValAddress) error {
count := 0
rng := collections.NewPrefixedPairRange[[]byte, time.Time](valAddr)
if err := k.ValidatorConsensusKeyRotationRecordIndexKey.Walk(ctx, rng, func(key collections.Pair[[]byte, time.Time]) (stop bool, err error) {
count++
return count >= maxRotations, nil
}); err != nil {
return err
}
if count >= maxRotations {
return types.ErrExceedingMaxConsPubKeyRotations
}
return nil
}
// setConsKeyQueue sets array of rotated validator addresses to a key of current block time + unbonding period
// this is to keep track of rotations made within the unbonding period
func (k Keeper) setConsKeyQueue(ctx context.Context, ts time.Time, valAddr sdk.ValAddress) error {
queueRec, err := k.ValidatorConsensusKeyRotationRecordQueue.Get(ctx, ts)
if err != nil {
return err
}
if !bytesSliceExists(queueRec.Addresses, valAddr.Bytes()) {
// Address does not exist, so you can append it to the list
queueRec.Addresses = append(queueRec.Addresses, valAddr.Bytes())
}
return k.ValidatorConsensusKeyRotationRecordQueue.Set(ctx, ts, queueRec)
}
func bytesSliceExists(sliceList [][]byte, targetBytes []byte) bool {
for _, bytesSlice := range sliceList {
if bytes.Equal(bytesSlice, targetBytes) {
return true
}
}
return false
}

View File

@ -9,6 +9,7 @@ import (
"cosmossdk.io/collections"
collcodec "cosmossdk.io/collections/codec"
"cosmossdk.io/collections/indexes"
addresscodec "cosmossdk.io/core/address"
storetypes "cosmossdk.io/core/store"
"cosmossdk.io/log"
@ -41,6 +42,27 @@ func HistoricalInfoCodec(cdc codec.BinaryCodec) collcodec.ValueCodec[types.Histo
})
}
type rotationHistoryIndexes struct {
Block *indexes.Multi[uint64, []byte, types.ConsPubKeyRotationHistory]
}
func (a rotationHistoryIndexes) IndexesList() []collections.Index[[]byte, types.ConsPubKeyRotationHistory] {
return []collections.Index[[]byte, types.ConsPubKeyRotationHistory]{
a.Block,
}
}
func NewRotationHistoryIndexes(sb *collections.SchemaBuilder) rotationHistoryIndexes {
return rotationHistoryIndexes{
Block: indexes.NewMulti(
sb, types.BlockConsPubKeyRotationHistoryKey, "cons_pubkey_history_by_block", collections.Uint64Key, collections.BytesKey,
func(_ []byte, v types.ConsPubKeyRotationHistory) (uint64, error) {
return v.Height, nil
},
),
}
}
// Keeper of the x/staking store
type Keeper struct {
storeService storetypes.KVStoreService
@ -93,6 +115,15 @@ type Keeper struct {
LastValidatorPower collections.Map[[]byte, gogotypes.Int64Value]
// Params key: ParamsKeyPrefix | value: Params
Params collections.Item[types.Params]
// ValidatorConsensusKeyRotationRecordIndexKey: this key is used to restrict the validator next rotation within waiting (unbonding) period
ValidatorConsensusKeyRotationRecordIndexKey collections.KeySet[collections.Pair[[]byte, time.Time]]
// ValidatorConsensusKeyRotationRecordQueue: this key is used to set the unbonding period time on each rotation
ValidatorConsensusKeyRotationRecordQueue collections.Map[time.Time, types.ValAddrsOfRotatedConsKeys]
// RotatedConsKeyMapIndex: prefix for rotated cons address to new cons address
RotatedConsKeyMapIndex collections.Map[[]byte, []byte]
// ValidatorConsPubKeyRotationHistory: consPubkey rotation history by validator
// A index is being added with key `BlockConsPubKeyRotationHistory`: consPubkey rotation history by height
RotationHistory *collections.IndexedMap[[]byte, types.ConsPubKeyRotationHistory, rotationHistoryIndexes]
}
// NewKeeper creates a new staking Keeper instance
@ -226,6 +257,40 @@ func NewKeeper(
),
// key is: 113 (it's a direct prefix)
Params: collections.NewItem(sb, types.ParamsKey, "params", codec.CollValue[types.Params](cdc)),
// key format is: 103 | valAddr | time
ValidatorConsensusKeyRotationRecordIndexKey: collections.NewKeySet(
sb, types.ValidatorConsensusKeyRotationRecordIndexKey,
"cons_pub_rotation_index",
collections.PairKeyCodec(collections.BytesKey, sdk.TimeKey),
),
// key format is: 104 | time
ValidatorConsensusKeyRotationRecordQueue: collections.NewMap(
sb, types.ValidatorConsensusKeyRotationRecordQueueKey,
"cons_pub_rotation_queue",
sdk.TimeKey,
codec.CollValue[types.ValAddrsOfRotatedConsKeys](cdc),
),
// key format is: 105 | valAddr
RotatedConsKeyMapIndex: collections.NewMap(
sb, types.RotatedConsKeyMapIndex,
"cons_pubkey_map",
collections.BytesKey,
collections.BytesValue,
),
// key format is : 101 | rotation history
// index is : 102 | rotation history
RotationHistory: collections.NewIndexedMap(
sb,
types.ValidatorConsPubKeyRotationHistoryKey,
"cons_pub_rotation_history",
collections.BytesKey,
codec.CollValue[types.ConsPubKeyRotationHistory](cdc),
NewRotationHistoryIndexes(sb),
),
}
schema, err := sb.Build()

View File

@ -2,6 +2,7 @@ package keeper
import (
"context"
"errors"
"strconv"
"time"
@ -9,6 +10,7 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"cosmossdk.io/collections"
errorsmod "cosmossdk.io/errors"
"cosmossdk.io/math"
"cosmossdk.io/x/staking/types"
@ -605,6 +607,76 @@ func (k msgServer) UpdateParams(ctx context.Context, msg *types.MsgUpdateParams)
return &types.MsgUpdateParamsResponse{}, nil
}
func (k msgServer) RotateConsPubKey(_ context.Context, _ *types.MsgRotateConsPubKey) (*types.MsgRotateConsPubKeyResponse, error) {
return nil, nil
func (k msgServer) RotateConsPubKey(ctx context.Context, msg *types.MsgRotateConsPubKey) (res *types.MsgRotateConsPubKeyResponse, err error) {
cv := msg.NewPubkey.GetCachedValue()
pk, ok := cv.(cryptotypes.PubKey)
if !ok {
return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidType, "expecting cryptotypes.PubKey, got %T", cv)
}
// check cons key is already present in the key rotation history.
rotatedTo, err := k.RotatedConsKeyMapIndex.Get(ctx, pk.Address())
if err != nil && !errors.Is(err, collections.ErrNotFound) {
return nil, err
}
if rotatedTo != nil {
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidAddress,
"the new public key is already present in rotation history, please try with a different one")
}
newConsAddr := sdk.ConsAddress(pk.Address())
// checks if NewPubKey is not duplicated on ValidatorsByConsAddr
validator1, _ := k.Keeper.ValidatorByConsAddr(ctx, newConsAddr)
if validator1 != nil {
return nil, types.ErrConsensusPubKeyAlreadyUsedForValidator
}
valAddr, err := k.validatorAddressCodec.StringToBytes(msg.ValidatorAddress)
if err != nil {
return nil, err
}
validator2, err := k.Keeper.GetValidator(ctx, valAddr)
if err != nil {
return nil, types.ErrNoValidatorFound
}
if status := validator2.GetStatus(); status != types.Bonded {
return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidType, "validator status is not bonded, got %s", status.String())
}
// Check if the validator is exceeding parameter MaxConsPubKeyRotations within the
// unbonding period by iterating ConsPubKeyRotationHistory.
err = k.exceedsMaxRotations(ctx, valAddr)
if err != nil {
return nil, err
}
// Check if the signing account has enough balance to pay KeyRotationFee
// KeyRotationFees are sent to the community fund.
params, err := k.Params.Get(ctx)
if err != nil {
return nil, err
}
err = k.Keeper.bankKeeper.SendCoinsFromAccountToModule(ctx, sdk.AccAddress(valAddr), types.DistributionModuleName, sdk.NewCoins(params.KeyRotationFee))
if err != nil {
return nil, err
}
// Add ConsPubKeyRotationHistory for tracking rotation
err = k.setConsPubKeyRotationHistory(
ctx,
valAddr,
validator2.ConsensusPubkey,
msg.NewPubkey,
params.KeyRotationFee,
)
if err != nil {
return nil, err
}
return res, nil
}

View File

@ -227,6 +227,20 @@ func (mr *MockBankKeeperMockRecorder) LockedCoins(ctx, addr interface{}) *gomock
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LockedCoins", reflect.TypeOf((*MockBankKeeper)(nil).LockedCoins), ctx, addr)
}
// SendCoinsFromAccountToModule mocks base method.
func (m *MockBankKeeper) SendCoinsFromAccountToModule(ctx context.Context, senderAddr types0.AccAddress, recipientModule string, amt types0.Coins) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SendCoinsFromAccountToModule", ctx, senderAddr, recipientModule, amt)
ret0, _ := ret[0].(error)
return ret0
}
// SendCoinsFromAccountToModule indicates an expected call of SendCoinsFromAccountToModule.
func (mr *MockBankKeeperMockRecorder) SendCoinsFromAccountToModule(ctx, senderAddr, recipientModule, amt interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromAccountToModule", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromAccountToModule), ctx, senderAddr, recipientModule, amt)
}
// SendCoinsFromModuleToModule mocks base method.
func (m *MockBankKeeper) SendCoinsFromModuleToModule(ctx context.Context, senderPool, recipientPool string, amt types0.Coins) error {
m.ctrl.T.Helper()

View File

@ -47,4 +47,8 @@ var (
ErrInvalidSigner = errors.Register(ModuleName, 43, "expected authority account as only signer for proposal message")
ErrBadRedelegationSrc = errors.Register(ModuleName, 44, "redelegation source validator not found")
ErrNoUnbondingType = errors.Register(ModuleName, 45, "unbonding type not found")
// consensus key errors
ErrConsensusPubKeyAlreadyUsedForValidator = errors.Register(ModuleName, 46, "consensus pubkey is already used for a validator")
ErrExceedingMaxConsPubKeyRotations = errors.Register(ModuleName, 47, "exceeding maximum consensus pubkey rotations within unbonding period")
)

View File

@ -35,6 +35,7 @@ type BankKeeper interface {
GetSupply(ctx context.Context, denom string) sdk.Coin
SendCoinsFromAccountToModule(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
SendCoinsFromModuleToModule(ctx context.Context, senderPool, recipientPool string, amt sdk.Coins) error
UndelegateCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
DelegateCoinsFromAccountToModule(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error

View File

@ -24,6 +24,11 @@ const (
// GovModuleName is the name of the gov module
GovModuleName = "gov"
// distributionModuleName duplicates the distribution module's name to avoid a cyclic dependency with x/distribution.
// It should be synced with the distribution module's name if it is ever changed.
// See: https://github.com/cosmos/cosmos-sdk/blob/912390d5fc4a32113ea1aacc98b77b2649aea4c2/x/distribution/types/keys.go#L15
DistributionModuleName = "distribution"
)
var (
@ -58,6 +63,12 @@ var (
ParamsKey = collections.NewPrefix(81) // prefix for parameters for module x/staking
DelegationByValIndexKey = collections.NewPrefix(113) // key for delegations by a validator
ValidatorConsPubKeyRotationHistoryKey = collections.NewPrefix(101) // prefix for consPubkey rotation history by validator
BlockConsPubKeyRotationHistoryKey = collections.NewPrefix(102) // prefix for consPubkey rotation history by height
ValidatorConsensusKeyRotationRecordQueueKey = collections.NewPrefix(103) // this key is used to set the unbonding period time on each rotation
ValidatorConsensusKeyRotationRecordIndexKey = collections.NewPrefix(104) // this key is used to restrict the validator next rotation within waiting (unbonding) period
RotatedConsKeyMapIndex = collections.NewPrefix(105) // prefix for rotated cons address to new cons address
)
// UnbondingType defines the type of unbonding operation

View File

@ -1324,7 +1324,7 @@ func (m *ValidatorUpdates) GetUpdates() []types3.ValidatorUpdate {
// ConsPubKeyRotationHistory contains a validator's consensus public key rotation history.
type ConsPubKeyRotationHistory struct {
// operator_address defines the address of the validator's operator; bech encoded in JSON.
OperatorAddress string `protobuf:"bytes,1,opt,name=operator_address,json=operatorAddress,proto3" json:"operator_address,omitempty"`
OperatorAddress []byte `protobuf:"bytes,1,opt,name=operator_address,json=operatorAddress,proto3" json:"operator_address,omitempty"`
// old_cons_pubkey is the old consensus public key of the validator, as a Protobuf Any.
OldConsPubkey *types1.Any `protobuf:"bytes,2,opt,name=old_cons_pubkey,json=oldConsPubkey,proto3" json:"old_cons_pubkey,omitempty"`
// new_cons_pubkey is the new consensus public key of the validator, as a Protobuf Any.
@ -1371,7 +1371,7 @@ var xxx_messageInfo_ConsPubKeyRotationHistory proto.InternalMessageInfo
// ValAddrsOfRotatedConsKeys contains the array of validator addresses which rotated their keys
// This is to block the validator's next rotation till unbonding period.
type ValAddrsOfRotatedConsKeys struct {
Addresses []string `protobuf:"bytes,1,rep,name=addresses,proto3" json:"addresses,omitempty"`
Addresses [][]byte `protobuf:"bytes,1,rep,name=addresses,proto3" json:"addresses,omitempty"`
}
func (m *ValAddrsOfRotatedConsKeys) Reset() { *m = ValAddrsOfRotatedConsKeys{} }
@ -1407,7 +1407,7 @@ func (m *ValAddrsOfRotatedConsKeys) XXX_DiscardUnknown() {
var xxx_messageInfo_ValAddrsOfRotatedConsKeys proto.InternalMessageInfo
func (m *ValAddrsOfRotatedConsKeys) GetAddresses() []string {
func (m *ValAddrsOfRotatedConsKeys) GetAddresses() [][]byte {
if m != nil {
return m.Addresses
}
@ -1448,137 +1448,138 @@ func init() {
}
var fileDescriptor_64c30c6cf92913c9 = []byte{
// 2078 bytes of a gzipped FileDescriptorProto
// 2083 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x59, 0x4d, 0x6c, 0x5b, 0x49,
0x1d, 0xcf, 0xb3, 0x5d, 0x27, 0xf9, 0x3b, 0x89, 0x9d, 0xe9, 0x97, 0xe3, 0xee, 0xc6, 0xae, 0xb7,
0xb0, 0x6d, 0xa1, 0x0e, 0x2d, 0xa8, 0x87, 0x80, 0x40, 0x75, 0xec, 0x6e, 0xbc, 0x1f, 0x49, 0x78,
0x4e, 0x02, 0xcb, 0xd7, 0xd3, 0xf8, 0xbd, 0xb1, 0xfd, 0x88, 0x3d, 0xcf, 0xbc, 0x19, 0xb7, 0xf1,
0x1d, 0xcf, 0xb3, 0x5d, 0x27, 0xf9, 0xdb, 0x89, 0x9d, 0xe9, 0x97, 0xe3, 0xee, 0xc6, 0xae, 0xb7,
0xb0, 0x6d, 0xa1, 0x0e, 0x2d, 0xa8, 0x87, 0x80, 0x40, 0x75, 0xec, 0x6e, 0xbd, 0x1f, 0x49, 0x78,
0x4e, 0x02, 0xcb, 0xd7, 0xd3, 0xf8, 0xbd, 0xb1, 0xfd, 0x88, 0x3d, 0xcf, 0xbc, 0x19, 0xb7, 0xf5,
0x9d, 0xc3, 0x2a, 0x2b, 0xa4, 0x3d, 0x01, 0x12, 0xaa, 0xa8, 0xc4, 0x65, 0xb9, 0xed, 0xa1, 0xe2,
0xce, 0x6d, 0x41, 0x42, 0xaa, 0x7a, 0x42, 0x48, 0x04, 0xd4, 0x1e, 0xba, 0x82, 0x0b, 0xe2, 0xc4,
0x11, 0xcd, 0xbc, 0x79, 0x1f, 0x8e, 0xe3, 0xe6, 0xa3, 0x2b, 0xb4, 0x62, 0x2f, 0x91, 0x67, 0xe6,
0xff, 0xff, 0xbd, 0xff, 0xf7, 0xcc, 0xff, 0x1f, 0xb8, 0x62, 0x3a, 0xac, 0xeb, 0xb0, 0x25, 0xc6,
0xf1, 0x8e, 0x4d, 0x5b, 0x4b, 0xf7, 0x6e, 0x36, 0x08, 0xc7, 0x37, 0xfd, 0x75, 0xa9, 0xe7, 0x3a,
0xdc, 0x41, 0x17, 0x3c, 0xaa, 0x92, 0xbf, 0xab, 0xa8, 0x72, 0xe7, 0x5a, 0x4e, 0xcb, 0x91, 0x24,
0x4b, 0xe2, 0x97, 0x47, 0x9d, 0x5b, 0x68, 0x39, 0x4e, 0xab, 0x43, 0x96, 0xe4, 0xaa, 0xd1, 0x6f,
0x2e, 0x61, 0x3a, 0x50, 0x47, 0x8b, 0x07, 0x8f, 0xac, 0xbe, 0x8b, 0xb9, 0xed, 0x50, 0x75, 0x9e,
0x3f, 0x78, 0xce, 0xed, 0x2e, 0x61, 0x1c, 0x77, 0x7b, 0x3e, 0xb6, 0x27, 0x89, 0xe1, 0x7d, 0x54,
0x89, 0xa5, 0xb0, 0x95, 0x2a, 0x0d, 0xcc, 0x48, 0xa0, 0x87, 0xe9, 0xd8, 0x3e, 0xf6, 0x3c, 0xee,
0xda, 0xd4, 0x59, 0x92, 0x7f, 0xd5, 0xd6, 0x2b, 0x9c, 0x50, 0x8b, 0xb8, 0x5d, 0x9b, 0xf2, 0x25,
0x3e, 0xe8, 0x11, 0xe6, 0xfd, 0x55, 0xa7, 0x97, 0x22, 0xa7, 0xb8, 0x61, 0xda, 0xd1, 0xc3, 0xe2,
0x2f, 0x34, 0x98, 0x5b, 0xb5, 0x19, 0x77, 0x5c, 0xdb, 0xc4, 0x9d, 0x1a, 0x6d, 0x3a, 0xe8, 0xeb,
0x90, 0x6c, 0x13, 0x6c, 0x11, 0x37, 0xab, 0x15, 0xb4, 0xab, 0xa9, 0x5b, 0xd9, 0x52, 0x08, 0x50,
0xf2, 0x78, 0x57, 0xe5, 0x79, 0x79, 0xfa, 0xe3, 0xfd, 0xfc, 0xc4, 0x87, 0xcf, 0x3f, 0xba, 0xae,
0xe9, 0x8a, 0x05, 0x55, 0x20, 0x79, 0x0f, 0x77, 0x18, 0xe1, 0xd9, 0x58, 0x21, 0x7e, 0x35, 0x75,
0xeb, 0x72, 0xe9, 0x70, 0x9b, 0x97, 0xb6, 0x71, 0xc7, 0xb6, 0x30, 0x77, 0x86, 0x51, 0x3c, 0xde,
0xe5, 0x58, 0x56, 0x2b, 0xbe, 0xaf, 0x41, 0x26, 0x94, 0x4c, 0x27, 0xa6, 0xe3, 0x5a, 0x28, 0x0b,
0x93, 0xb8, 0xd7, 0x6b, 0x63, 0xd6, 0x96, 0xc2, 0xcd, 0xe8, 0xfe, 0x12, 0x7d, 0x0d, 0x12, 0xc2,
0xc8, 0xd9, 0x98, 0x94, 0x39, 0x57, 0xf2, 0x3c, 0x50, 0xf2, 0x3d, 0x50, 0xda, 0xf4, 0x3d, 0x50,
0x4e, 0x7c, 0xf0, 0xb7, 0xbc, 0xa6, 0x4b, 0x6a, 0xf4, 0x3a, 0xa4, 0xef, 0xf9, 0x82, 0x30, 0x43,
0xe2, 0xc6, 0x25, 0xee, 0x5c, 0xb8, 0xbd, 0x8a, 0x59, 0xbb, 0xf8, 0xf3, 0x18, 0xa4, 0x57, 0x9c,
0x6e, 0xd7, 0x66, 0xcc, 0x76, 0xa8, 0x8e, 0x39, 0x61, 0xe8, 0x4d, 0x48, 0xb8, 0x98, 0x13, 0x29,
0xc9, 0x74, 0xf9, 0xb6, 0x50, 0xe3, 0x2f, 0xfb, 0xf9, 0x4b, 0x9e, 0xc2, 0xcc, 0xda, 0x29, 0xd9,
0xce, 0x52, 0x17, 0xf3, 0x76, 0xe9, 0x6d, 0xd2, 0xc2, 0xe6, 0xa0, 0x42, 0xcc, 0x27, 0x8f, 0x6e,
0x80, 0xb2, 0x47, 0x85, 0x98, 0x9e, 0xce, 0x12, 0x03, 0x7d, 0x1b, 0xa6, 0xba, 0x78, 0xd7, 0x90,
0x78, 0xb1, 0x97, 0xc2, 0x9b, 0xec, 0xe2, 0x5d, 0x21, 0x1f, 0xfa, 0x11, 0xa4, 0x05, 0xa4, 0xd9,
0xc6, 0xb4, 0x45, 0x3c, 0xe4, 0xf8, 0x4b, 0x21, 0xcf, 0x76, 0xf1, 0xee, 0x8a, 0x44, 0x13, 0xf8,
0xcb, 0x89, 0x4f, 0x1e, 0xe6, 0xb5, 0xe2, 0xef, 0x35, 0x80, 0xd0, 0x30, 0x08, 0x43, 0xc6, 0x0c,
0x56, 0xf2, 0xa3, 0x4c, 0x85, 0xd1, 0xeb, 0xe3, 0x22, 0xe1, 0x80, 0x59, 0xcb, 0xb3, 0x42, 0xbc,
0xc7, 0xfb, 0x79, 0xcd, 0xfb, 0x6a, 0xda, 0x1c, 0x31, 0x7b, 0xaa, 0xdf, 0xb3, 0x30, 0x27, 0xc6,
0x31, 0x1d, 0x2e, 0x01, 0x85, 0xd3, 0x3d, 0x40, 0xf0, 0xb8, 0xc5, 0xb9, 0xd2, 0xe1, 0x43, 0x0d,
0x52, 0x15, 0xc2, 0x4c, 0xd7, 0xee, 0x89, 0x24, 0x16, 0x51, 0xd6, 0x75, 0xa8, 0xbd, 0xa3, 0x52,
0x60, 0x5a, 0xf7, 0x97, 0x28, 0x07, 0x53, 0xb6, 0x45, 0x28, 0xb7, 0xf9, 0xc0, 0x73, 0x93, 0x1e,
0xac, 0x05, 0xd7, 0x7d, 0xd2, 0x60, 0xb6, 0x6f, 0x67, 0xdd, 0x5f, 0xa2, 0x6b, 0x90, 0x61, 0xc4,
0xec, 0xbb, 0x36, 0x1f, 0x18, 0xa6, 0x43, 0x39, 0x36, 0x79, 0x36, 0x21, 0x49, 0xd2, 0xfe, 0xfe,
0x8a, 0xb7, 0x2d, 0x40, 0x2c, 0xc2, 0xb1, 0xdd, 0x61, 0xd9, 0x33, 0x1e, 0x88, 0x5a, 0x2a, 0x51,
0xf7, 0x26, 0x61, 0x3a, 0x48, 0x1d, 0xb4, 0x02, 0x19, 0xa7, 0x47, 0x5c, 0xf1, 0xdb, 0xc0, 0x96,
0xe5, 0x12, 0xc6, 0x54, 0x34, 0x66, 0x9f, 0x3c, 0xba, 0x71, 0x4e, 0x19, 0xfc, 0x8e, 0x77, 0x52,
0xe7, 0xae, 0x4d, 0x5b, 0x7a, 0xda, 0xe7, 0x50, 0xdb, 0xe8, 0x5d, 0xe1, 0x32, 0xca, 0x08, 0x65,
0x7d, 0x66, 0xf4, 0xfa, 0x8d, 0x1d, 0x32, 0x50, 0x46, 0x3d, 0x37, 0x62, 0xd4, 0x3b, 0x74, 0x50,
0xce, 0xfe, 0x31, 0x84, 0x36, 0xdd, 0x41, 0x8f, 0x3b, 0xa5, 0x8d, 0x7e, 0xe3, 0x2d, 0x32, 0x10,
0xae, 0x52, 0x38, 0x1b, 0x12, 0x06, 0x5d, 0x80, 0xe4, 0x8f, 0xb1, 0xdd, 0x21, 0x96, 0xb4, 0xc8,
0x94, 0xae, 0x56, 0x68, 0x19, 0x92, 0x8c, 0x63, 0xde, 0x67, 0xd2, 0x0c, 0x73, 0xb7, 0x8a, 0xe3,
0x62, 0xa3, 0xec, 0x50, 0xab, 0x2e, 0x29, 0x75, 0xc5, 0x81, 0x56, 0x20, 0xc9, 0x9d, 0x1d, 0x42,
0x95, 0x81, 0xca, 0x5f, 0x52, 0xd1, 0x7c, 0x7e, 0x34, 0x9a, 0x6b, 0x94, 0x47, 0xe2, 0xb8, 0x46,
0xb9, 0xae, 0x58, 0xd1, 0x0f, 0x20, 0x63, 0x91, 0x0e, 0x69, 0x49, 0xcb, 0xb1, 0x36, 0x76, 0x09,
0xcb, 0x26, 0x25, 0xdc, 0xcd, 0x13, 0x27, 0x87, 0x9e, 0x0e, 0xa0, 0xea, 0x12, 0x09, 0x6d, 0x40,
0xca, 0x0a, 0xc3, 0x29, 0x3b, 0x29, 0x8d, 0xf9, 0xda, 0x38, 0x1d, 0x23, 0x91, 0x17, 0xad, 0x85,
0x51, 0x08, 0x11, 0x41, 0x7d, 0xda, 0x70, 0xa8, 0x65, 0xd3, 0x96, 0xd1, 0x26, 0x76, 0xab, 0xcd,
0xb3, 0x53, 0x05, 0xed, 0x6a, 0x5c, 0x4f, 0x07, 0xfb, 0xab, 0x72, 0x1b, 0x6d, 0xc0, 0x5c, 0x48,
0x2a, 0x33, 0x64, 0xfa, 0xa4, 0x19, 0x32, 0x1b, 0x00, 0x08, 0x12, 0xf4, 0x0e, 0x40, 0x98, 0x83,
0x59, 0x90, 0x68, 0xc5, 0xa3, 0xb3, 0x39, 0xaa, 0x4c, 0x04, 0x00, 0x7d, 0x1f, 0xce, 0x76, 0x6d,
0x6a, 0x30, 0xd2, 0x69, 0x1a, 0xca, 0x72, 0x02, 0x37, 0x75, 0x72, 0x6f, 0xce, 0x77, 0x6d, 0x5a,
0x27, 0x9d, 0x66, 0x25, 0x40, 0x41, 0xdf, 0x80, 0x4b, 0xa1, 0xf6, 0x0e, 0x35, 0xda, 0x4e, 0xc7,
0x32, 0x5c, 0xd2, 0x34, 0x4c, 0xa7, 0x4f, 0x79, 0x76, 0x46, 0xda, 0xec, 0x62, 0x40, 0xb2, 0x4e,
0x57, 0x9d, 0x8e, 0xa5, 0x93, 0xe6, 0x8a, 0x38, 0x46, 0xaf, 0x41, 0xa8, 0xba, 0x61, 0x5b, 0x2c,
0x3b, 0x5b, 0x88, 0x5f, 0x4d, 0xe8, 0x33, 0xc1, 0x66, 0xcd, 0x62, 0xcb, 0x53, 0xef, 0x3d, 0xcc,
0x4f, 0x7c, 0xf2, 0x30, 0x3f, 0x51, 0xbc, 0x0b, 0x33, 0xdb, 0xb8, 0xa3, 0xf2, 0x88, 0x30, 0x74,
0x1b, 0xa6, 0xb1, 0xbf, 0xc8, 0x6a, 0x85, 0xf8, 0x0b, 0xf3, 0x30, 0x24, 0x2d, 0xfe, 0x56, 0x83,
0x64, 0x65, 0x7b, 0x03, 0xdb, 0x2e, 0xaa, 0xc2, 0x7c, 0x18, 0x98, 0xc7, 0x4d, 0xe9, 0x30, 0x96,
0xfd, 0x9c, 0x5e, 0x83, 0xf9, 0xe0, 0x02, 0x0b, 0x60, 0xbc, 0x7b, 0xe5, 0xf2, 0x93, 0x47, 0x37,
0x5e, 0x55, 0x30, 0x41, 0x25, 0x39, 0x80, 0x77, 0xef, 0xc0, 0x7e, 0x44, 0xe7, 0x37, 0x61, 0xd2,
0x13, 0x95, 0xa1, 0x6f, 0xc1, 0x99, 0x9e, 0xf8, 0x21, 0x55, 0x4d, 0xdd, 0x5a, 0x1c, 0x1b, 0xe0,
0x92, 0x3e, 0x1a, 0x0e, 0x1e, 0x5f, 0xf1, 0xfd, 0x18, 0x40, 0x65, 0x7b, 0x7b, 0xd3, 0xb5, 0x7b,
0x1d, 0xc2, 0x3f, 0x2d, 0xdd, 0xb7, 0xe0, 0x7c, 0xa8, 0x3b, 0x73, 0xcd, 0x93, 0xeb, 0x7f, 0x36,
0xe0, 0xaf, 0xbb, 0xe6, 0xa1, 0xb0, 0x16, 0xe3, 0x01, 0x6c, 0xfc, 0xe4, 0xb0, 0x15, 0xc6, 0x47,
0x2d, 0xfb, 0x5d, 0x48, 0x85, 0xc6, 0x60, 0xa8, 0x06, 0x53, 0x5c, 0xfd, 0x56, 0x06, 0x2e, 0x8e,
0x37, 0xb0, 0xcf, 0x16, 0x35, 0x72, 0xc0, 0x5e, 0xfc, 0x8f, 0x06, 0x10, 0xc9, 0x91, 0xcf, 0x66,
0x8c, 0xa1, 0x1a, 0x24, 0x55, 0x25, 0x8e, 0x9f, 0xb6, 0x12, 0x2b, 0x80, 0x88, 0x51, 0x7f, 0x16,
0x83, 0xb3, 0x5b, 0x7e, 0xf6, 0x7e, 0xf6, 0x6d, 0xb0, 0x05, 0x93, 0x84, 0x72, 0xd7, 0x96, 0x46,
0x10, 0x3e, 0xff, 0xca, 0x38, 0x9f, 0x1f, 0xa2, 0x54, 0x95, 0x72, 0x77, 0x10, 0x8d, 0x00, 0x1f,
0x2b, 0x62, 0x8f, 0x5f, 0xc5, 0x21, 0x3b, 0x8e, 0x55, 0xbc, 0x86, 0x4d, 0x97, 0xc8, 0x0d, 0xff,
0x92, 0xd1, 0x64, 0xc1, 0x9c, 0xf3, 0xb7, 0xd5, 0x1d, 0xa3, 0x83, 0x78, 0x95, 0x89, 0xe0, 0x12,
0xa4, 0xa7, 0x7b, 0x86, 0xcd, 0x85, 0x08, 0xf2, 0x96, 0xd9, 0x84, 0xb4, 0x4d, 0x6d, 0x6e, 0xe3,
0x8e, 0xd1, 0xc0, 0x1d, 0x4c, 0x4d, 0xff, 0xb9, 0x7a, 0xa2, 0x2b, 0x61, 0x4e, 0x61, 0x94, 0x3d,
0x08, 0x54, 0x85, 0x49, 0x1f, 0x2d, 0x71, 0x72, 0x34, 0x9f, 0x17, 0x5d, 0x86, 0x99, 0xe8, 0xc5,
0x20, 0x9f, 0x1e, 0x09, 0x3d, 0x15, 0xb9, 0x17, 0x8e, 0xba, 0x79, 0x92, 0x2f, 0xbc, 0x79, 0xd4,
0xeb, 0xee, 0xd7, 0x71, 0x98, 0xd7, 0x89, 0xf5, 0xff, 0xef, 0x96, 0x0d, 0x00, 0x2f, 0x55, 0x45,
0x25, 0x55, 0x9e, 0x39, 0x45, 0xbe, 0x4f, 0x7b, 0x20, 0x15, 0xc6, 0xff, 0x57, 0x1e, 0xfa, 0x6b,
0x0c, 0x66, 0xa2, 0x1e, 0xfa, 0x5c, 0x5e, 0x5a, 0x68, 0x2d, 0x2c, 0x53, 0x09, 0x59, 0xa6, 0xae,
0x8d, 0x2b, 0x53, 0x23, 0xd1, 0x7c, 0x44, 0x7d, 0x7a, 0x1e, 0x87, 0xe4, 0x06, 0x76, 0x71, 0x97,
0xa1, 0xf5, 0x91, 0x87, 0xac, 0xd7, 0x48, 0x2e, 0x8c, 0x04, 0x73, 0x45, 0x4d, 0x5f, 0xbc, 0x58,
0xfe, 0xe5, 0xb8, 0x77, 0xec, 0x17, 0x60, 0x4e, 0x34, 0xc4, 0x61, 0x67, 0x2f, 0x8d, 0x3b, 0x2b,
0xfb, 0xda, 0x40, 0x7b, 0x86, 0xf2, 0x90, 0x12, 0x64, 0x61, 0x1d, 0x16, 0x34, 0xd0, 0xc5, 0xbb,
0x55, 0x6f, 0x07, 0xdd, 0x00, 0xd4, 0x0e, 0x06, 0x13, 0x46, 0x68, 0x08, 0x41, 0x37, 0x1f, 0x9e,
0xf8, 0xe4, 0xaf, 0x02, 0x08, 0x29, 0x0c, 0x8b, 0x50, 0xa7, 0xab, 0xba, 0xba, 0x69, 0xb1, 0x53,
0x11, 0x1b, 0xe8, 0xa7, 0x9a, 0xf7, 0x1e, 0x3e, 0xd0, 0x36, 0xab, 0x76, 0x64, 0xf3, 0x18, 0x49,
0xf1, 0xef, 0xfd, 0x7c, 0x6e, 0x80, 0xbb, 0x9d, 0xe5, 0xe2, 0x21, 0x38, 0xc5, 0xc3, 0x3a, 0x79,
0xf1, 0x70, 0x1e, 0x6e, 0xbb, 0x51, 0x0d, 0x32, 0x3b, 0x64, 0x60, 0xb8, 0x0e, 0xf7, 0x0a, 0x4d,
0x93, 0x10, 0xd5, 0xb8, 0x2c, 0xf8, 0xbe, 0x6d, 0x60, 0x46, 0x22, 0xef, 0x7c, 0x9b, 0x96, 0x13,
0x42, 0x3a, 0x7d, 0x6e, 0x87, 0x0c, 0x74, 0xc5, 0x77, 0x97, 0x90, 0xe5, 0x2b, 0x22, 0x53, 0xf6,
0x9e, 0x7f, 0x74, 0x5d, 0x09, 0x7d, 0x83, 0x59, 0x3b, 0x4b, 0xbb, 0xc1, 0x6c, 0xce, 0x73, 0xaf,
0x78, 0xf4, 0xa2, 0xf0, 0x02, 0xd2, 0x09, 0xeb, 0x89, 0xe6, 0x51, 0x34, 0x1b, 0x91, 0xa6, 0x40,
0x7b, 0x71, 0xb3, 0x11, 0xf2, 0x0f, 0x35, 0x1b, 0x91, 0xf4, 0xfc, 0x66, 0x58, 0xff, 0x63, 0x47,
0x69, 0x13, 0x8d, 0x4c, 0xc5, 0x24, 0xb3, 0x7e, 0xa2, 0xf8, 0x27, 0x0d, 0x16, 0x46, 0x22, 0x39,
0x10, 0xd9, 0x04, 0xe4, 0x46, 0x0e, 0x65, 0x44, 0x0c, 0x94, 0xe8, 0xa7, 0x4b, 0x8c, 0x79, 0x77,
0xe4, 0x12, 0xf8, 0x74, 0x2e, 0x32, 0x55, 0xc5, 0xfe, 0xa0, 0xc1, 0xb9, 0xa8, 0x00, 0x81, 0x2a,
0x75, 0x98, 0x89, 0x7e, 0x5a, 0x29, 0x71, 0xe5, 0x38, 0x4a, 0x44, 0xe5, 0x1f, 0x02, 0x41, 0xdb,
0x61, 0xb5, 0xf0, 0x86, 0x82, 0x37, 0x8f, 0x6d, 0x14, 0x5f, 0xb0, 0x43, 0xab, 0x86, 0xe7, 0x9b,
0x7f, 0x6a, 0x90, 0xd8, 0x70, 0x9c, 0x0e, 0xfa, 0x09, 0xcc, 0x53, 0x87, 0x1b, 0x22, 0xb3, 0x88,
0x65, 0xa8, 0x19, 0x81, 0x57, 0x89, 0xab, 0x2f, 0xb4, 0xd5, 0x3f, 0xf6, 0xf3, 0xa3, 0x9c, 0xc3,
0x06, 0x54, 0xa3, 0x28, 0xea, 0xf0, 0xb2, 0x24, 0xda, 0xf4, 0xc6, 0x08, 0x4d, 0x98, 0x1d, 0xfe,
0x9c, 0x57, 0xad, 0xef, 0x1c, 0xf5, 0xb9, 0xd9, 0x23, 0x3f, 0x35, 0xd3, 0x88, 0x7c, 0x67, 0x79,
0x4a, 0x78, 0xed, 0x5f, 0xc2, 0x73, 0xef, 0x42, 0x26, 0x28, 0x55, 0x5b, 0x72, 0x8e, 0xc5, 0x44,
0x68, 0x78, 0x23, 0x2d, 0xbf, 0x51, 0x28, 0x44, 0x27, 0xb6, 0xb8, 0x61, 0xda, 0xa5, 0x03, 0x3c,
0x43, 0xe6, 0x54, 0xbc, 0xc5, 0xc7, 0x31, 0x58, 0x58, 0x71, 0x28, 0x53, 0xc3, 0x1c, 0x95, 0xd0,
0xde, 0x08, 0x76, 0x80, 0xae, 0x8d, 0x1b, 0x35, 0x8d, 0x0e, 0x94, 0xb6, 0x21, 0x2d, 0x6e, 0x56,
0xd3, 0xa1, 0x2f, 0x39, 0x4f, 0x9a, 0x75, 0x3a, 0x96, 0x92, 0x68, 0x87, 0x0c, 0x04, 0x2e, 0x25,
0xf7, 0x87, 0x70, 0xe3, 0xa7, 0xc3, 0xa5, 0xe4, 0x7e, 0x04, 0xf7, 0x02, 0x24, 0xd5, 0xb3, 0x2a,
0x21, 0x1f, 0x0d, 0x6a, 0x85, 0x6e, 0x43, 0x5c, 0x54, 0xc1, 0x33, 0x27, 0xa8, 0x1b, 0x82, 0x21,
0x72, 0x9b, 0xd5, 0x61, 0x41, 0x0d, 0x08, 0xd8, 0x7a, 0x53, 0x5a, 0x94, 0x48, 0x85, 0xde, 0x22,
0x83, 0x53, 0x4f, 0x0b, 0xae, 0xff, 0x4e, 0x03, 0x08, 0xe7, 0x62, 0xe8, 0xcb, 0x70, 0xb1, 0xbc,
0xbe, 0x56, 0x31, 0xea, 0x9b, 0x77, 0x36, 0xb7, 0xea, 0xc6, 0xd6, 0x5a, 0x7d, 0xa3, 0xba, 0x52,
0xbb, 0x5b, 0xab, 0x56, 0x32, 0x13, 0xb9, 0xf4, 0xde, 0x83, 0x42, 0x6a, 0x8b, 0xb2, 0x1e, 0x31,
0xed, 0xa6, 0x4d, 0x2c, 0xf4, 0x45, 0x38, 0x37, 0x4c, 0x2d, 0x56, 0xd5, 0x4a, 0x46, 0xcb, 0xcd,
0xec, 0x3d, 0x28, 0x4c, 0x79, 0xad, 0x01, 0xb1, 0xd0, 0x55, 0x38, 0x3f, 0x4a, 0x57, 0x5b, 0x7b,
0x23, 0x13, 0xcb, 0xcd, 0xee, 0x3d, 0x28, 0x4c, 0x07, 0x3d, 0x04, 0x2a, 0x02, 0x8a, 0x52, 0x2a,
0xbc, 0x78, 0x0e, 0xf6, 0x1e, 0x14, 0x92, 0x5e, 0xb6, 0xe4, 0x12, 0xef, 0xfd, 0x66, 0x71, 0xe2,
0xfa, 0x0f, 0x01, 0x6a, 0xb4, 0xe9, 0x62, 0x53, 0x56, 0x85, 0x1c, 0x5c, 0xa8, 0xad, 0xdd, 0xd5,
0xef, 0xac, 0x6c, 0xd6, 0xd6, 0xd7, 0x86, 0xc5, 0x3e, 0x70, 0x56, 0x59, 0xdf, 0x2a, 0xbf, 0x5d,
0x35, 0xea, 0xb5, 0x37, 0xd6, 0x32, 0x1a, 0xba, 0x08, 0x67, 0x87, 0xce, 0xbe, 0xb3, 0xb6, 0x59,
0x7b, 0xa7, 0x9a, 0x89, 0x95, 0x6f, 0x7f, 0xfc, 0x74, 0x51, 0x7b, 0xfc, 0x74, 0x51, 0xfb, 0xfb,
0xd3, 0x45, 0xed, 0x83, 0x67, 0x8b, 0x13, 0x8f, 0x9f, 0x2d, 0x4e, 0xfc, 0xf9, 0xd9, 0xe2, 0xc4,
0xf7, 0x5e, 0x19, 0xca, 0xc3, 0xf0, 0x26, 0x92, 0xff, 0xcc, 0x68, 0x24, 0x65, 0xd4, 0x7c, 0xf5,
0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x38, 0xe3, 0xc3, 0xc6, 0x44, 0x1a, 0x00, 0x00,
0xff, 0xff, 0xbd, 0xff, 0xf7, 0xcc, 0xff, 0x1f, 0xb8, 0x64, 0x3a, 0xac, 0xe7, 0xb0, 0x65, 0xc6,
0xf1, 0x8e, 0x4d, 0xdb, 0xcb, 0x77, 0xaf, 0x37, 0x09, 0xc7, 0xd7, 0xfd, 0x75, 0xb9, 0xef, 0x3a,
0xdc, 0x41, 0xe7, 0x3c, 0xaa, 0xb2, 0xbf, 0xab, 0xa8, 0xf2, 0x67, 0xda, 0x4e, 0xdb, 0x91, 0x24,
0xcb, 0xe2, 0x97, 0x47, 0x9d, 0x5f, 0x6c, 0x3b, 0x4e, 0xbb, 0x4b, 0x96, 0xe5, 0xaa, 0x39, 0x68,
0x2d, 0x63, 0x3a, 0x54, 0x47, 0x4b, 0xfb, 0x8f, 0xac, 0x81, 0x8b, 0xb9, 0xed, 0x50, 0x75, 0x5e,
0xd8, 0x7f, 0xce, 0xed, 0x1e, 0x61, 0x1c, 0xf7, 0xfa, 0x3e, 0xb6, 0x27, 0x89, 0xe1, 0x7d, 0x54,
0x89, 0xa5, 0xb0, 0x95, 0x2a, 0x4d, 0xcc, 0x48, 0xa0, 0x87, 0xe9, 0xd8, 0x3e, 0xf6, 0x02, 0xee,
0xd9, 0xd4, 0x59, 0x96, 0x7f, 0xd5, 0xd6, 0x2b, 0x9c, 0x50, 0x8b, 0xb8, 0x3d, 0x9b, 0xf2, 0x65,
0x3e, 0xec, 0x13, 0xe6, 0xfd, 0x55, 0xa7, 0x17, 0x22, 0xa7, 0xb8, 0x69, 0xda, 0xd1, 0xc3, 0xd2,
0x2f, 0x34, 0x98, 0xbf, 0x63, 0x33, 0xee, 0xb8, 0xb6, 0x89, 0xbb, 0x75, 0xda, 0x72, 0xd0, 0xd7,
0x21, 0xd9, 0x21, 0xd8, 0x22, 0x6e, 0x4e, 0x2b, 0x6a, 0x97, 0x53, 0x37, 0x72, 0xe5, 0x10, 0xa0,
0xec, 0xf1, 0xde, 0x91, 0xe7, 0x95, 0xd9, 0x8f, 0xf7, 0x0a, 0x53, 0x1f, 0x3e, 0xff, 0xe8, 0xaa,
0xa6, 0x2b, 0x16, 0x54, 0x85, 0xe4, 0x5d, 0xdc, 0x65, 0x84, 0xe7, 0x62, 0xc5, 0xf8, 0xe5, 0xd4,
0x8d, 0x8b, 0xe5, 0x83, 0x6d, 0x5e, 0xde, 0xc6, 0x5d, 0xdb, 0xc2, 0xdc, 0x19, 0x45, 0xf1, 0x78,
0x57, 0x62, 0x39, 0xad, 0xf4, 0xbe, 0x06, 0xd9, 0x50, 0x32, 0x9d, 0x98, 0x8e, 0x6b, 0xa1, 0x1c,
0x4c, 0xe3, 0x7e, 0xbf, 0x83, 0x59, 0x47, 0x0a, 0x97, 0xd6, 0xfd, 0x25, 0xfa, 0x1a, 0x24, 0x84,
0x91, 0x73, 0x31, 0x29, 0x73, 0xbe, 0xec, 0x79, 0xa0, 0xec, 0x7b, 0xa0, 0xbc, 0xe9, 0x7b, 0xa0,
0x92, 0xf8, 0xe0, 0x6f, 0x05, 0x4d, 0x97, 0xd4, 0xe8, 0x75, 0xc8, 0xdc, 0xf5, 0x05, 0x61, 0x86,
0xc4, 0x8d, 0x4b, 0xdc, 0xf9, 0x70, 0xfb, 0x0e, 0x66, 0x9d, 0xd2, 0xcf, 0x63, 0x90, 0x59, 0x75,
0x7a, 0x3d, 0x9b, 0x31, 0xdb, 0xa1, 0x3a, 0xe6, 0x84, 0xa1, 0x37, 0x21, 0xe1, 0x62, 0x4e, 0xa4,
0x24, 0xb3, 0x95, 0x9b, 0x42, 0x8d, 0xbf, 0xec, 0x15, 0x2e, 0x78, 0x0a, 0x33, 0x6b, 0xa7, 0x6c,
0x3b, 0xcb, 0x3d, 0xcc, 0x3b, 0xe5, 0xb7, 0x49, 0x1b, 0x9b, 0xc3, 0x2a, 0x31, 0x9f, 0x3c, 0xba,
0x06, 0xca, 0x1e, 0x55, 0x62, 0x7a, 0x3a, 0x4b, 0x0c, 0xf4, 0x6d, 0x98, 0xe9, 0xe1, 0xfb, 0x86,
0xc4, 0x8b, 0xbd, 0x14, 0xde, 0x74, 0x0f, 0xdf, 0x17, 0xf2, 0xa1, 0x1f, 0x41, 0x46, 0x40, 0x9a,
0x1d, 0x4c, 0xdb, 0xc4, 0x43, 0x8e, 0xbf, 0x14, 0xf2, 0x5c, 0x0f, 0xdf, 0x5f, 0x95, 0x68, 0x02,
0x7f, 0x25, 0xf1, 0xc9, 0xc3, 0x82, 0x56, 0xfa, 0xbd, 0x06, 0x10, 0x1a, 0x06, 0x61, 0xc8, 0x9a,
0xc1, 0x4a, 0x7e, 0x94, 0xa9, 0x30, 0x7a, 0x7d, 0x52, 0x24, 0xec, 0x33, 0x6b, 0x65, 0x4e, 0x88,
0xf7, 0x78, 0xaf, 0xa0, 0x79, 0x5f, 0xcd, 0x98, 0x63, 0x66, 0x4f, 0x0d, 0xfa, 0x16, 0xe6, 0xc4,
0x38, 0xa2, 0xc3, 0x25, 0xa0, 0x70, 0xba, 0x07, 0x08, 0x1e, 0xb7, 0x38, 0x57, 0x3a, 0x7c, 0xa8,
0x41, 0xaa, 0x4a, 0x98, 0xe9, 0xda, 0x7d, 0x91, 0xc4, 0x22, 0xca, 0x7a, 0x0e, 0xb5, 0x77, 0x54,
0x0a, 0xcc, 0xea, 0xfe, 0x12, 0xe5, 0x61, 0xc6, 0xb6, 0x08, 0xe5, 0x36, 0x1f, 0x7a, 0x6e, 0xd2,
0x83, 0xb5, 0xe0, 0xba, 0x47, 0x9a, 0xcc, 0xf6, 0xed, 0xac, 0xfb, 0x4b, 0x74, 0x05, 0xb2, 0x8c,
0x98, 0x03, 0xd7, 0xe6, 0x43, 0xc3, 0x74, 0x28, 0xc7, 0x26, 0xcf, 0x25, 0x24, 0x49, 0xc6, 0xdf,
0x5f, 0xf5, 0xb6, 0x05, 0x88, 0x45, 0x38, 0xb6, 0xbb, 0x2c, 0x77, 0xca, 0x03, 0x51, 0x4b, 0x25,
0xea, 0xee, 0x34, 0xcc, 0x06, 0xa9, 0x83, 0x56, 0x21, 0xeb, 0xf4, 0x89, 0x2b, 0x7e, 0x1b, 0xd8,
0xb2, 0x5c, 0xc2, 0x98, 0x8a, 0xc6, 0xdc, 0x93, 0x47, 0xd7, 0xce, 0x28, 0x83, 0xdf, 0xf2, 0x4e,
0x1a, 0xdc, 0xb5, 0x69, 0x5b, 0xcf, 0xf8, 0x1c, 0x6a, 0x1b, 0xbd, 0x2b, 0x5c, 0x46, 0x19, 0xa1,
0x6c, 0xc0, 0x8c, 0xfe, 0xa0, 0xb9, 0x43, 0x86, 0xca, 0xa8, 0x67, 0xc6, 0x8c, 0x7a, 0x8b, 0x0e,
0x2b, 0xb9, 0x3f, 0x86, 0xd0, 0xa6, 0x3b, 0xec, 0x73, 0xa7, 0xbc, 0x31, 0x68, 0xbe, 0x45, 0x86,
0xc2, 0x55, 0x0a, 0x67, 0x43, 0xc2, 0xa0, 0x73, 0x90, 0xfc, 0x31, 0xb6, 0xbb, 0xc4, 0x92, 0x16,
0x99, 0xd1, 0xd5, 0x0a, 0xad, 0x40, 0x92, 0x71, 0xcc, 0x07, 0x4c, 0x9a, 0x61, 0xfe, 0x46, 0x69,
0x52, 0x6c, 0x54, 0x1c, 0x6a, 0x35, 0x24, 0xa5, 0xae, 0x38, 0xd0, 0x2a, 0x24, 0xb9, 0xb3, 0x43,
0xa8, 0x32, 0x50, 0xe5, 0x4b, 0x2a, 0x9a, 0xcf, 0x8e, 0x47, 0x73, 0x9d, 0xf2, 0x48, 0x1c, 0xd7,
0x29, 0xd7, 0x15, 0x2b, 0xfa, 0x01, 0x64, 0x2d, 0xd2, 0x25, 0x6d, 0x69, 0x39, 0xd6, 0xc1, 0x2e,
0x61, 0xb9, 0xa4, 0x84, 0xbb, 0x7e, 0xec, 0xe4, 0xd0, 0x33, 0x01, 0x54, 0x43, 0x22, 0xa1, 0x0d,
0x48, 0x59, 0x61, 0x38, 0xe5, 0xa6, 0xa5, 0x31, 0x5f, 0x9b, 0xa4, 0x63, 0x24, 0xf2, 0xa2, 0xb5,
0x30, 0x0a, 0x21, 0x22, 0x68, 0x40, 0x9b, 0x0e, 0xb5, 0x6c, 0xda, 0x36, 0x3a, 0xc4, 0x6e, 0x77,
0x78, 0x6e, 0xa6, 0xa8, 0x5d, 0x8e, 0xeb, 0x99, 0x60, 0xff, 0x8e, 0xdc, 0x46, 0x1b, 0x30, 0x1f,
0x92, 0xca, 0x0c, 0x99, 0x3d, 0x6e, 0x86, 0xcc, 0x05, 0x00, 0x82, 0x04, 0xbd, 0x03, 0x10, 0xe6,
0x60, 0x0e, 0x24, 0x5a, 0xe9, 0xf0, 0x6c, 0x8e, 0x2a, 0x13, 0x01, 0x40, 0xdf, 0x87, 0xd3, 0x3d,
0x9b, 0x1a, 0x8c, 0x74, 0x5b, 0x86, 0xb2, 0x9c, 0xc0, 0x4d, 0x1d, 0xdf, 0x9b, 0x0b, 0x3d, 0x9b,
0x36, 0x48, 0xb7, 0x55, 0x0d, 0x50, 0xd0, 0x37, 0xe0, 0x42, 0xa8, 0xbd, 0x43, 0x8d, 0x8e, 0xd3,
0xb5, 0x0c, 0x97, 0xb4, 0x0c, 0xd3, 0x19, 0x50, 0x9e, 0x4b, 0x4b, 0x9b, 0x9d, 0x0f, 0x48, 0xd6,
0xe9, 0x1d, 0xa7, 0x6b, 0xe9, 0xa4, 0xb5, 0x2a, 0x8e, 0xd1, 0x6b, 0x10, 0xaa, 0x6e, 0xd8, 0x16,
0xcb, 0xcd, 0x15, 0xe3, 0x97, 0x13, 0x7a, 0x3a, 0xd8, 0xac, 0x5b, 0x6c, 0x65, 0xe6, 0xbd, 0x87,
0x85, 0xa9, 0x4f, 0x1e, 0x16, 0xa6, 0x4a, 0xb7, 0x21, 0xbd, 0x8d, 0xbb, 0x2a, 0x8f, 0x08, 0x43,
0x37, 0x61, 0x16, 0xfb, 0x8b, 0x9c, 0x56, 0x8c, 0xbf, 0x30, 0x0f, 0x43, 0xd2, 0xd2, 0x6f, 0x35,
0x48, 0x56, 0xb7, 0x37, 0xb0, 0xed, 0xa2, 0x1a, 0x2c, 0x84, 0x81, 0x79, 0xd4, 0x94, 0x0e, 0x63,
0xd9, 0xcf, 0xe9, 0x35, 0x58, 0x08, 0x2e, 0xb0, 0x00, 0xc6, 0xbb, 0x57, 0x2e, 0x3e, 0x79, 0x74,
0xed, 0x55, 0x05, 0x13, 0x54, 0x92, 0x7d, 0x78, 0x77, 0xf7, 0xed, 0x47, 0x74, 0x7e, 0x13, 0xa6,
0x3d, 0x51, 0x19, 0xfa, 0x16, 0x9c, 0xea, 0x8b, 0x1f, 0x52, 0xd5, 0xd4, 0x8d, 0xa5, 0x89, 0x01,
0x2e, 0xe9, 0xa3, 0xe1, 0xe0, 0xf1, 0x95, 0xde, 0x8f, 0x01, 0x54, 0xb7, 0xb7, 0x37, 0x5d, 0xbb,
0xdf, 0x25, 0xfc, 0xd3, 0xd2, 0x7d, 0x0b, 0xce, 0x86, 0xba, 0x33, 0xd7, 0x3c, 0xbe, 0xfe, 0xa7,
0x03, 0xfe, 0x86, 0x6b, 0x1e, 0x08, 0x6b, 0x31, 0x1e, 0xc0, 0xc6, 0x8f, 0x0f, 0x5b, 0x65, 0x7c,
0xdc, 0xb2, 0xdf, 0x85, 0x54, 0x68, 0x0c, 0x86, 0xea, 0x30, 0xc3, 0xd5, 0x6f, 0x65, 0xe0, 0xd2,
0x64, 0x03, 0xfb, 0x6c, 0x51, 0x23, 0x07, 0xec, 0xa5, 0xff, 0x68, 0x00, 0x91, 0x1c, 0xf9, 0x6c,
0xc6, 0x18, 0xaa, 0x43, 0x52, 0x55, 0xe2, 0xf8, 0x49, 0x2b, 0xb1, 0x02, 0x88, 0x18, 0xf5, 0x67,
0x31, 0x38, 0xbd, 0xe5, 0x67, 0xef, 0x67, 0xdf, 0x06, 0x5b, 0x30, 0x4d, 0x28, 0x77, 0x6d, 0x69,
0x04, 0xe1, 0xf3, 0xaf, 0x4c, 0xf2, 0xf9, 0x01, 0x4a, 0xd5, 0x28, 0x77, 0x87, 0xd1, 0x08, 0xf0,
0xb1, 0x22, 0xf6, 0xf8, 0x55, 0x1c, 0x72, 0x93, 0x58, 0xc5, 0x6b, 0xd8, 0x74, 0x89, 0xdc, 0xf0,
0x2f, 0x19, 0x4d, 0x16, 0xcc, 0x79, 0x7f, 0x5b, 0xdd, 0x31, 0x3a, 0x88, 0x57, 0x99, 0x08, 0x2e,
0x41, 0x7a, 0xb2, 0x67, 0xd8, 0x7c, 0x88, 0x20, 0x6f, 0x99, 0x4d, 0xc8, 0xd8, 0xd4, 0xe6, 0x36,
0xee, 0x1a, 0x4d, 0xdc, 0xc5, 0xd4, 0xf4, 0x9f, 0xab, 0xc7, 0xba, 0x12, 0xe6, 0x15, 0x46, 0xc5,
0x83, 0x40, 0x35, 0x98, 0xf6, 0xd1, 0x12, 0xc7, 0x47, 0xf3, 0x79, 0xd1, 0x45, 0x48, 0x47, 0x2f,
0x06, 0xf9, 0xf4, 0x48, 0xe8, 0xa9, 0xc8, 0xbd, 0x70, 0xd8, 0xcd, 0x93, 0x7c, 0xe1, 0xcd, 0xa3,
0x5e, 0x77, 0xbf, 0x8e, 0xc3, 0x82, 0x4e, 0xac, 0xff, 0x7f, 0xb7, 0x6c, 0x00, 0x78, 0xa9, 0x2a,
0x2a, 0xa9, 0xf2, 0xcc, 0x09, 0xf2, 0x7d, 0xd6, 0x03, 0xa9, 0x32, 0xfe, 0xbf, 0xf2, 0xd0, 0x5f,
0x63, 0x90, 0x8e, 0x7a, 0xe8, 0x73, 0x79, 0x69, 0xa1, 0xb5, 0xb0, 0x4c, 0x25, 0x64, 0x99, 0xba,
0x32, 0xa9, 0x4c, 0x8d, 0x45, 0xf3, 0x21, 0xf5, 0xe9, 0x79, 0x1c, 0x92, 0x1b, 0xd8, 0xc5, 0x3d,
0x86, 0xd6, 0xc7, 0x1e, 0xb2, 0x5e, 0x23, 0xb9, 0x38, 0x16, 0xcc, 0x55, 0x35, 0x7d, 0xf1, 0x62,
0xf9, 0x97, 0x93, 0xde, 0xb1, 0x5f, 0x80, 0x79, 0xd1, 0x10, 0x87, 0x9d, 0xbd, 0x34, 0xee, 0x9c,
0xec, 0x6b, 0x03, 0xed, 0x19, 0x2a, 0x40, 0x4a, 0x90, 0x85, 0x75, 0x58, 0xd0, 0x40, 0x0f, 0xdf,
0xaf, 0x79, 0x3b, 0xe8, 0x1a, 0xa0, 0x4e, 0x30, 0x98, 0x30, 0x42, 0x43, 0x08, 0xba, 0x85, 0xf0,
0xc4, 0x27, 0x7f, 0x15, 0x40, 0x48, 0x61, 0x58, 0x84, 0x3a, 0x3d, 0xd5, 0xd5, 0xcd, 0x8a, 0x9d,
0xaa, 0xd8, 0x40, 0x3f, 0xd5, 0xbc, 0xf7, 0xf0, 0xbe, 0xb6, 0x59, 0xb5, 0x23, 0x9b, 0x47, 0x48,
0x8a, 0x7f, 0xef, 0x15, 0xf2, 0x43, 0xdc, 0xeb, 0xae, 0x94, 0x0e, 0xc0, 0x29, 0x1d, 0xd4, 0xc9,
0x8b, 0x87, 0xf3, 0x68, 0xdb, 0x8d, 0xea, 0x90, 0xdd, 0x21, 0x43, 0xc3, 0x75, 0xb8, 0x57, 0x68,
0x5a, 0x84, 0xa8, 0xc6, 0x65, 0xd1, 0xf7, 0x6d, 0x13, 0x33, 0x12, 0x79, 0xe7, 0xdb, 0xb4, 0x92,
0x10, 0xd2, 0xe9, 0xf3, 0x3b, 0x64, 0xa8, 0x2b, 0xbe, 0xdb, 0x84, 0xac, 0x5c, 0x12, 0x99, 0xb2,
0xfb, 0xfc, 0xa3, 0xab, 0x4a, 0xe8, 0x6b, 0xcc, 0xda, 0x59, 0xbe, 0x1f, 0xcc, 0xe6, 0x3c, 0xf7,
0x8a, 0x47, 0x2f, 0x0a, 0x2f, 0x20, 0x9d, 0xb0, 0xbe, 0x68, 0x1e, 0x45, 0xb3, 0x11, 0x69, 0x0a,
0xb4, 0x17, 0x37, 0x1b, 0x21, 0xff, 0x48, 0xb3, 0x11, 0x49, 0xcf, 0x6f, 0x86, 0xf5, 0x3f, 0x76,
0x98, 0x36, 0xd1, 0xc8, 0x54, 0x4c, 0x32, 0xeb, 0xa7, 0x4a, 0x7f, 0xd2, 0x60, 0x71, 0x2c, 0x92,
0x03, 0x91, 0x4d, 0x40, 0x6e, 0xe4, 0x50, 0x46, 0xc4, 0x50, 0x89, 0x7e, 0xb2, 0xc4, 0x58, 0x70,
0xc7, 0x2e, 0x81, 0x4f, 0xe7, 0x22, 0x53, 0x55, 0xec, 0x0f, 0x1a, 0x9c, 0x89, 0x0a, 0x10, 0xa8,
0xd2, 0x80, 0x74, 0xf4, 0xd3, 0x4a, 0x89, 0x4b, 0x47, 0x51, 0x22, 0x2a, 0xff, 0x08, 0x08, 0xda,
0x0e, 0xab, 0x85, 0x37, 0x14, 0xbc, 0x7e, 0x64, 0xa3, 0xf8, 0x82, 0x1d, 0x58, 0x35, 0x3c, 0xdf,
0xfc, 0x53, 0x83, 0xc4, 0x86, 0xe3, 0x74, 0xd1, 0x4f, 0x60, 0x81, 0x3a, 0xdc, 0x10, 0x99, 0x45,
0x2c, 0x43, 0xcd, 0x08, 0xbc, 0x4a, 0x5c, 0x7b, 0xa1, 0xad, 0xfe, 0xb1, 0x57, 0x18, 0xe7, 0x1c,
0x35, 0xa0, 0x1a, 0x45, 0x51, 0x87, 0x57, 0x24, 0xd1, 0xa6, 0x37, 0x46, 0x68, 0xc1, 0xdc, 0xe8,
0xe7, 0xbc, 0x6a, 0x7d, 0xeb, 0xb0, 0xcf, 0xcd, 0x1d, 0xfa, 0xa9, 0x74, 0x33, 0xf2, 0x9d, 0x95,
0x19, 0xe1, 0xb5, 0x7f, 0x09, 0xcf, 0xbd, 0x0b, 0xd9, 0xa0, 0x54, 0x6d, 0xc9, 0x39, 0x16, 0x13,
0xa1, 0xe1, 0x8d, 0xb4, 0xfc, 0x46, 0xa1, 0x18, 0x9d, 0xd8, 0xe2, 0xa6, 0x69, 0x97, 0xf7, 0xf1,
0x8c, 0x98, 0x53, 0xf1, 0x96, 0x1e, 0xc7, 0x60, 0x71, 0xd5, 0xa1, 0x4c, 0x0d, 0x73, 0x54, 0x42,
0x7b, 0x23, 0xd8, 0x21, 0xba, 0x32, 0x61, 0xd4, 0x94, 0x1e, 0x1f, 0x28, 0x6d, 0x43, 0x46, 0xdc,
0xac, 0xa6, 0x43, 0x5f, 0x72, 0x9e, 0x34, 0xe7, 0x74, 0x2d, 0x25, 0xd1, 0x0e, 0x19, 0x0a, 0x5c,
0x4a, 0xee, 0x8d, 0xe0, 0xc6, 0x4f, 0x86, 0x4b, 0xc9, 0xbd, 0x08, 0xee, 0x39, 0x48, 0xaa, 0x67,
0x55, 0x42, 0x3e, 0x1a, 0xd4, 0x0a, 0xdd, 0x84, 0xb8, 0xa8, 0x82, 0xa7, 0x8e, 0x51, 0x37, 0x04,
0x43, 0xe4, 0x36, 0x6b, 0xc0, 0xa2, 0x1a, 0x10, 0xb0, 0xf5, 0x96, 0xb4, 0x28, 0x91, 0x0a, 0xbd,
0x45, 0x86, 0x07, 0x4c, 0x0b, 0xd2, 0x47, 0x9a, 0x16, 0x5c, 0xfd, 0x9d, 0x06, 0x10, 0xce, 0xc5,
0xd0, 0x97, 0xe1, 0x7c, 0x65, 0x7d, 0xad, 0x6a, 0x34, 0x36, 0x6f, 0x6d, 0x6e, 0x35, 0x8c, 0xad,
0xb5, 0xc6, 0x46, 0x6d, 0xb5, 0x7e, 0xbb, 0x5e, 0xab, 0x66, 0xa7, 0xf2, 0x99, 0xdd, 0x07, 0xc5,
0xd4, 0x16, 0x65, 0x7d, 0x62, 0xda, 0x2d, 0x9b, 0x58, 0xe8, 0x8b, 0x70, 0x66, 0x94, 0x5a, 0xac,
0x6a, 0xd5, 0xac, 0x96, 0x4f, 0xef, 0x3e, 0x28, 0xce, 0x78, 0xad, 0x01, 0xb1, 0xd0, 0x65, 0x38,
0x3b, 0x4e, 0x57, 0x5f, 0x7b, 0x23, 0x1b, 0xcb, 0xcf, 0xed, 0x3e, 0x28, 0xce, 0x06, 0x3d, 0x04,
0x2a, 0x01, 0x8a, 0x52, 0x2a, 0xbc, 0x78, 0x1e, 0x76, 0x1f, 0x14, 0x93, 0x5e, 0xb6, 0xe4, 0x13,
0xef, 0xfd, 0x66, 0x69, 0xea, 0xea, 0x0f, 0x01, 0xea, 0xb4, 0xe5, 0x62, 0x53, 0x56, 0x85, 0x3c,
0x9c, 0xab, 0xaf, 0xdd, 0xd6, 0x6f, 0xad, 0x6e, 0xd6, 0xd7, 0xd7, 0x46, 0xc5, 0xde, 0x77, 0x56,
0x5d, 0xdf, 0xaa, 0xbc, 0x5d, 0x33, 0x1a, 0xf5, 0x37, 0xd6, 0xb2, 0x1a, 0x3a, 0x0f, 0xa7, 0x47,
0xce, 0xbe, 0xb3, 0xb6, 0x59, 0x7f, 0xa7, 0x96, 0x8d, 0x55, 0x6e, 0x7e, 0xfc, 0x74, 0x49, 0x7b,
0xfc, 0x74, 0x49, 0xfb, 0xfb, 0xd3, 0x25, 0xed, 0x83, 0x67, 0x4b, 0x53, 0x8f, 0x9f, 0x2d, 0x4d,
0xfd, 0xf9, 0xd9, 0xd2, 0xd4, 0xf7, 0x5e, 0x19, 0xc9, 0xc3, 0xf0, 0x26, 0x92, 0xff, 0xcc, 0x68,
0x26, 0x65, 0xd4, 0x7c, 0xf5, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x51, 0xe0, 0x99, 0x08, 0x44,
0x1a, 0x00, 0x00,
}
func (this *Pool) Description() (desc *github_com_cosmos_gogoproto_protoc_gen_gogo_descriptor.FileDescriptorSet) {
@ -1587,7 +1588,7 @@ func (this *Pool) Description() (desc *github_com_cosmos_gogoproto_protoc_gen_go
func StakingDescription() (desc *github_com_cosmos_gogoproto_protoc_gen_gogo_descriptor.FileDescriptorSet) {
d := &github_com_cosmos_gogoproto_protoc_gen_gogo_descriptor.FileDescriptorSet{}
var gzipped = []byte{
// 11497 bytes of a gzipped FileDescriptorSet
// 11501 bytes of a gzipped FileDescriptorSet
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0xbd, 0x6b, 0x94, 0x1c, 0xc7,
0x75, 0x1f, 0xbe, 0x3d, 0xef, 0xb9, 0xf3, 0xea, 0xad, 0x5d, 0x00, 0x83, 0x01, 0x89, 0x5d, 0x36,
0x45, 0x12, 0x04, 0xc9, 0x05, 0x09, 0x12, 0x20, 0xb9, 0x90, 0xc4, 0xff, 0xcc, 0xec, 0x00, 0x3b,
@ -2291,22 +2292,22 @@ func StakingDescription() (desc *github_com_cosmos_gogoproto_protoc_gen_gogo_des
0x3b, 0x81, 0x72, 0xd8, 0x1b, 0xd1, 0x7f, 0x4c, 0x7a, 0xee, 0x26, 0xc8, 0x37, 0x06, 0xcf, 0x2f,
0xd5, 0x20, 0x29, 0xce, 0x2b, 0x49, 0x53, 0x1e, 0x85, 0x0a, 0x8a, 0x93, 0xf3, 0x2a, 0x9f, 0x89,
0xc0, 0xe9, 0xaa, 0x6d, 0x39, 0x3c, 0x98, 0xc3, 0x07, 0x34, 0x0b, 0xc1, 0x1e, 0xa2, 0xc7, 0xc7,
0x85, 0x9a, 0x86, 0x03, 0x4a, 0x37, 0xa0, 0x40, 0x66, 0x56, 0xc3, 0xb6, 0xbe, 0xca, 0x78, 0x52,
0xce, 0x6e, 0xb7, 0x78, 0x8d, 0x6e, 0xe1, 0x43, 0x82, 0x6b, 0xe1, 0x3b, 0x21, 0xdc, 0xe8, 0xfd,
0xe1, 0x5a, 0xf8, 0x4e, 0x00, 0xd7, 0xdf, 0x2a, 0x8f, 0x85, 0xb6, 0xca, 0x2f, 0x43, 0x94, 0x58,
0xc1, 0xf8, 0x31, 0xec, 0x06, 0x61, 0x08, 0xcc, 0x66, 0x0d, 0x38, 0xcd, 0x03, 0x04, 0xce, 0xe6,
0x2e, 0x95, 0x28, 0xa6, 0x0d, 0x7a, 0x19, 0x1f, 0xde, 0x77, 0xb4, 0xe0, 0xfc, 0xcf, 0x4b, 0x00,
0x7e, 0x5c, 0x0c, 0x3d, 0x09, 0xa7, 0x2a, 0x9b, 0x1b, 0x2b, 0x5a, 0xa3, 0x59, 0x6e, 0x6e, 0x37,
0xc2, 0x7f, 0x32, 0x46, 0x3c, 0x82, 0xe5, 0x74, 0xb1, 0x61, 0xee, 0x9a, 0xb8, 0x85, 0x1e, 0x85,
0xf9, 0x30, 0x35, 0xf9, 0xaa, 0xad, 0xc8, 0x52, 0x29, 0x7b, 0xf7, 0xde, 0x62, 0x8a, 0x2d, 0x0d,
0x70, 0x0b, 0x9d, 0x83, 0x13, 0xc3, 0x74, 0xf5, 0x8d, 0x6b, 0x72, 0xa4, 0x94, 0xbb, 0x7b, 0x6f,
0x31, 0xed, 0xad, 0x21, 0x90, 0x02, 0x28, 0x48, 0xc9, 0xf1, 0xa2, 0x25, 0xb8, 0x7b, 0x6f, 0x31,
0xc1, 0x46, 0x4b, 0x29, 0xf6, 0xc1, 0x1f, 0x3b, 0x3b, 0x73, 0xfe, 0x9b, 0x00, 0xea, 0xd6, 0x6e,
0x4f, 0x37, 0xa8, 0x55, 0x28, 0xc1, 0xc9, 0xfa, 0xc6, 0x55, 0xb5, 0x5c, 0x6d, 0xd6, 0x37, 0x37,
0x06, 0xfe, 0xd2, 0x4d, 0x38, 0x6f, 0x65, 0x73, 0xbb, 0xb2, 0x56, 0xd3, 0x1a, 0xf5, 0x6b, 0x1b,
0x6c, 0xc7, 0x3f, 0x94, 0xf7, 0x9e, 0x8d, 0x66, 0x7d, 0xbd, 0x26, 0x47, 0x2a, 0x97, 0xc7, 0xee,
0x28, 0x3d, 0x10, 0x1a, 0x87, 0xfe, 0x4c, 0x14, 0xda, 0x46, 0xfa, 0x3f, 0x01, 0x00, 0x00, 0xff,
0xff, 0xdf, 0x19, 0x56, 0xfb, 0x2d, 0xa5, 0x00, 0x00,
0x84, 0x9a, 0xb2, 0xc3, 0x01, 0xa5, 0x1b, 0x50, 0x20, 0x33, 0xab, 0x61, 0x5b, 0x5f, 0x65, 0x3c,
0x29, 0x67, 0xb7, 0x5b, 0xbc, 0x46, 0xb7, 0xf0, 0x21, 0xc1, 0xb5, 0xf0, 0x9d, 0x10, 0x6e, 0xf4,
0xfe, 0x70, 0x2d, 0x7c, 0x27, 0x80, 0xeb, 0x6f, 0x95, 0xc7, 0x42, 0x5b, 0xe5, 0x97, 0x21, 0x4a,
0xac, 0x60, 0xfc, 0x18, 0x76, 0x83, 0x30, 0x04, 0x66, 0xb3, 0x06, 0x9c, 0xe6, 0x01, 0x02, 0x67,
0x73, 0x97, 0x4a, 0x14, 0xd3, 0x06, 0xbd, 0x8c, 0x0f, 0x47, 0x44, 0x0b, 0xb2, 0x53, 0x45, 0x0b,
0xce, 0xff, 0xbc, 0x04, 0xe0, 0xc7, 0xc5, 0xd0, 0x93, 0x70, 0xaa, 0xb2, 0xb9, 0xb1, 0xa2, 0x35,
0x9a, 0xe5, 0xe6, 0x76, 0x23, 0xfc, 0x27, 0x63, 0xc4, 0x23, 0x58, 0x4e, 0x17, 0x1b, 0xe6, 0xae,
0x89, 0x5b, 0xe8, 0x51, 0x98, 0x0f, 0x53, 0x93, 0xaf, 0xda, 0x8a, 0x2c, 0x95, 0xb2, 0x77, 0xef,
0x2d, 0xa6, 0xd8, 0xd2, 0x00, 0xb7, 0xd0, 0x39, 0x38, 0x31, 0x4c, 0x57, 0xdf, 0xb8, 0x26, 0x47,
0x4a, 0xb9, 0xbb, 0xf7, 0x16, 0xd3, 0xde, 0x1a, 0x02, 0x29, 0x80, 0x82, 0x94, 0x1c, 0x2f, 0x5a,
0x82, 0xbb, 0xf7, 0x16, 0x13, 0x6c, 0xb4, 0x94, 0x62, 0x1f, 0xfc, 0xb1, 0xb3, 0x33, 0xe7, 0xbf,
0x09, 0xa0, 0x6e, 0xed, 0xf6, 0x74, 0x83, 0x5a, 0x85, 0x12, 0x9c, 0xac, 0x6f, 0x5c, 0x55, 0xcb,
0xd5, 0x66, 0x7d, 0x73, 0x63, 0xe0, 0x2f, 0xdd, 0x84, 0xf3, 0x56, 0x36, 0xb7, 0x2b, 0x6b, 0x35,
0xad, 0x51, 0xbf, 0xb6, 0xc1, 0x76, 0xfc, 0x43, 0x79, 0xef, 0xd9, 0x68, 0xd6, 0xd7, 0x6b, 0x72,
0xa4, 0x72, 0x79, 0xec, 0x8e, 0xd2, 0x03, 0xa1, 0x71, 0xe8, 0xcf, 0x44, 0xa1, 0x6d, 0xa4, 0xff,
0x13, 0x00, 0x00, 0xff, 0xff, 0xb6, 0x1a, 0x0c, 0x35, 0x2d, 0xa5, 0x00, 0x00,
}
r := bytes.NewReader(gzipped)
gzipr, err := compress_gzip.NewReader(r)
@ -4326,8 +4327,8 @@ func (m *ValAddrsOfRotatedConsKeys) Size() (n int) {
var l int
_ = l
if len(m.Addresses) > 0 {
for _, s := range m.Addresses {
l = len(s)
for _, b := range m.Addresses {
l = len(b)
n += 1 + l + sovStaking(uint64(l))
}
}
@ -7787,7 +7788,7 @@ func (m *ConsPubKeyRotationHistory) Unmarshal(dAtA []byte) error {
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field OperatorAddress", wireType)
}
var stringLen uint64
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowStaking
@ -7797,23 +7798,25 @@ func (m *ConsPubKeyRotationHistory) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
if byteLen < 0 {
return ErrInvalidLengthStaking
}
postIndex := iNdEx + intStringLen
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthStaking
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.OperatorAddress = string(dAtA[iNdEx:postIndex])
m.OperatorAddress = append(m.OperatorAddress[:0], dAtA[iNdEx:postIndex]...)
if m.OperatorAddress == nil {
m.OperatorAddress = []byte{}
}
iNdEx = postIndex
case 2:
if wireType != 2 {
@ -7993,7 +7996,7 @@ func (m *ValAddrsOfRotatedConsKeys) Unmarshal(dAtA []byte) error {
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Addresses", wireType)
}
var stringLen uint64
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowStaking
@ -8003,23 +8006,23 @@ func (m *ValAddrsOfRotatedConsKeys) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
if byteLen < 0 {
return ErrInvalidLengthStaking
}
postIndex := iNdEx + intStringLen
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthStaking
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Addresses = append(m.Addresses, string(dAtA[iNdEx:postIndex]))
m.Addresses = append(m.Addresses, make([]byte, postIndex-iNdEx))
copy(m.Addresses[len(m.Addresses)-1], dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex

View File

@ -867,7 +867,7 @@ type MsgClient interface {
UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error)
// RotateConsPubKey defines an operation for rotating the consensus keys
// of a validator.
// Since: cosmos-sdk 0.48
// Since: cosmos-sdk 0.51
RotateConsPubKey(ctx context.Context, in *MsgRotateConsPubKey, opts ...grpc.CallOption) (*MsgRotateConsPubKeyResponse, error)
}
@ -977,7 +977,7 @@ type MsgServer interface {
UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error)
// RotateConsPubKey defines an operation for rotating the consensus keys
// of a validator.
// Since: cosmos-sdk 0.48
// Since: cosmos-sdk 0.51
RotateConsPubKey(context.Context, *MsgRotateConsPubKey) (*MsgRotateConsPubKeyResponse, error)
}