From 0a39fd8731126705139e4a972228d6d0bba0fa63 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Tue, 10 Sep 2024 16:26:36 -0400 Subject: [PATCH 01/16] add function to clear ballots --- .../zetachain/zetacore/observer/ballot.proto | 5 + .../zetachain/zetacore/observer/events.proto | 8 + proto/zetachain/zetacore/observer/query.proto | 6 +- testutil/keeper/mocks/emissions/observer.go | 5 + .../zetacore/observer/events_pb.d.ts | 39 ++ x/emissions/abci.go | 8 +- x/emissions/types/expected_keepers.go | 1 + x/observer/keeper/ballot.go | 27 +- x/observer/keeper/events.go | 12 + x/observer/keeper/grpc_query_ballot.go | 11 +- x/observer/types/ballot.go | 12 + x/observer/types/ballot.pb.go | 279 +++++++-- x/observer/types/events.pb.go | 424 ++++++++++++-- x/observer/types/query.pb.go | 534 ++++++------------ 14 files changed, 904 insertions(+), 467 deletions(-) diff --git a/proto/zetachain/zetacore/observer/ballot.proto b/proto/zetachain/zetacore/observer/ballot.proto index 8281572ad7..b423a98d80 100644 --- a/proto/zetachain/zetacore/observer/ballot.proto +++ b/proto/zetachain/zetacore/observer/ballot.proto @@ -41,3 +41,8 @@ message BallotListForHeight { int64 height = 1; repeated string ballots_index_list = 2; } + +message VoterList { + string voter_address = 1; + VoteType vote_type = 2; +} diff --git a/proto/zetachain/zetacore/observer/events.proto b/proto/zetachain/zetacore/observer/events.proto index ea2e0fc38a..ac946528bd 100644 --- a/proto/zetachain/zetacore/observer/events.proto +++ b/proto/zetachain/zetacore/observer/events.proto @@ -4,6 +4,7 @@ package zetachain.zetacore.observer; import "gogoproto/gogo.proto"; import "zetachain/zetacore/observer/crosschain_flags.proto"; import "zetachain/zetacore/observer/observer.proto"; +import "zetachain/zetacore/observer/ballot.proto"; option go_package = "github.com/zeta-chain/node/x/observer/types"; @@ -15,6 +16,13 @@ message EventBallotCreated { string ballot_type = 5; } +message EventBallotDeleted { + string msg_type_url = 1; + string ballot_identifier = 2; + string ballot_type = 3; + repeated VoterList voters = 4 [ (gogoproto.nullable) = false ]; +} + message EventKeygenBlockUpdated { string msg_type_url = 1; string keygen_block = 2; diff --git a/proto/zetachain/zetacore/observer/query.proto b/proto/zetachain/zetacore/observer/query.proto index 65d5afb7b1..1189824467 100644 --- a/proto/zetachain/zetacore/observer/query.proto +++ b/proto/zetachain/zetacore/observer/query.proto @@ -246,14 +246,10 @@ message QueryHasVotedRequest { message QueryHasVotedResponse { bool has_voted = 1; } message QueryBallotByIdentifierRequest { string ballot_identifier = 1; } -message VoterList { - string voter_address = 1; - VoteType vote_type = 2; -} message QueryBallotByIdentifierResponse { string ballot_identifier = 1; - repeated VoterList voters = 2; + repeated VoterList voters = 2 [ (gogoproto.nullable) = false ]; ObservationType observation_type = 3; BallotStatus ballot_status = 4; } diff --git a/testutil/keeper/mocks/emissions/observer.go b/testutil/keeper/mocks/emissions/observer.go index 501cc68d43..2a10eea3dd 100644 --- a/testutil/keeper/mocks/emissions/observer.go +++ b/testutil/keeper/mocks/emissions/observer.go @@ -15,6 +15,11 @@ type EmissionObserverKeeper struct { mock.Mock } +// ClearMaturedBallots provides a mock function with given fields: ctx, maturityBlocks +func (_m *EmissionObserverKeeper) ClearMaturedBallots(ctx types.Context, maturityBlocks int64) { + _m.Called(ctx, maturityBlocks) +} + // GetBallot provides a mock function with given fields: ctx, index func (_m *EmissionObserverKeeper) GetBallot(ctx types.Context, index string) (observertypes.Ballot, bool) { ret := _m.Called(ctx, index) diff --git a/typescript/zetachain/zetacore/observer/events_pb.d.ts b/typescript/zetachain/zetacore/observer/events_pb.d.ts index 5139b88e2e..61987af05d 100644 --- a/typescript/zetachain/zetacore/observer/events_pb.d.ts +++ b/typescript/zetachain/zetacore/observer/events_pb.d.ts @@ -51,6 +51,45 @@ export declare class EventBallotCreated extends Message { static equals(a: EventBallotCreated | PlainMessage | undefined, b: EventBallotCreated | PlainMessage | undefined): boolean; } +/** + * @generated from message zetachain.zetacore.observer.EventBallotDeleted + */ +export declare class EventBallotDeleted extends Message { + /** + * @generated from field: string msg_type_url = 1; + */ + msgTypeUrl: string; + + /** + * @generated from field: string ballot_identifier = 2; + */ + ballotIdentifier: string; + + /** + * @generated from field: string ballot_type = 3; + */ + ballotType: string; + + /** + * @generated from field: string votes_collected = 4; + */ + votesCollected: string; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "zetachain.zetacore.observer.EventBallotDeleted"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): EventBallotDeleted; + + static fromJson(jsonValue: JsonValue, options?: Partial): EventBallotDeleted; + + static fromJsonString(jsonString: string, options?: Partial): EventBallotDeleted; + + static equals(a: EventBallotDeleted | PlainMessage | undefined, b: EventBallotDeleted | PlainMessage | undefined): boolean; +} + /** * @generated from message zetachain.zetacore.observer.EventKeygenBlockUpdated */ diff --git a/x/emissions/abci.go b/x/emissions/abci.go index b4b75562ff..7909793027 100644 --- a/x/emissions/abci.go +++ b/x/emissions/abci.go @@ -6,6 +6,7 @@ import ( sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + observertypes "github.com/zeta-chain/node/x/observer/types" "github.com/zeta-chain/node/cmd/zetacored/config" "github.com/zeta-chain/node/x/emissions/keeper" @@ -102,11 +103,13 @@ func DistributeObserverRewards( if len(ballotIdentifiers) == 0 { return nil } + ballots := make([]observertypes.Ballot, 0, len(ballotIdentifiers)) for _, ballotIdentifier := range ballotIdentifiers { ballot, found := keeper.GetObserverKeeper().GetBallot(ctx, ballotIdentifier) if !found { continue } + ballots = append(ballots, ballot) totalRewardsUnits += ballot.BuildRewardsDistribution(rewardsDistributer) } rewardPerUnit := sdkmath.ZeroInt() @@ -161,8 +164,9 @@ func DistributeObserverRewards( } } types.EmitObserverEmissions(ctx, finalDistributionList) - // TODO : Delete Ballots after distribution - // https://github.com/zeta-chain/node/issues/942 + + // Clear the matured ballots + keeper.GetObserverKeeper().ClearMaturedBallots(ctx, ballots, params.BallotMaturityBlocks) return nil } diff --git a/x/emissions/types/expected_keepers.go b/x/emissions/types/expected_keepers.go index bf67b183be..d834dc0f1a 100644 --- a/x/emissions/types/expected_keepers.go +++ b/x/emissions/types/expected_keepers.go @@ -16,6 +16,7 @@ type AccountKeeper interface { type ObserverKeeper interface { GetBallot(ctx sdk.Context, index string) (val observertypes.Ballot, found bool) GetMaturedBallots(ctx sdk.Context, maturityBlocks int64) (val observertypes.BallotListForHeight, found bool) + ClearMaturedBallots(ctx sdk.Context, ballots []observertypes.Ballot, maturityBlocks int64) } // BankKeeper defines the expected interface needed to retrieve account balances. diff --git a/x/observer/keeper/ballot.go b/x/observer/keeper/ballot.go index 799f5c8281..4c8487d2f1 100644 --- a/x/observer/keeper/ballot.go +++ b/x/observer/keeper/ballot.go @@ -20,6 +20,16 @@ func (k Keeper) SetBallotList(ctx sdk.Context, ballotlist *types.BallotListForHe store.Set(types.BallotListKeyPrefix(ballotlist.Height), b) } +func (k Keeper) DeleteBallot(ctx sdk.Context, index string) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.VoterKey)) + store.Delete([]byte(index)) +} + +func (k Keeper) DeleteBallotList(ctx sdk.Context, height int64) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.BallotListKey)) + store.Delete(types.BallotListKeyPrefix(height)) +} + func (k Keeper) GetBallot(ctx sdk.Context, index string) (val types.Ballot, found bool) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.VoterKey)) b := store.Get(types.KeyPrefix(index)) @@ -41,7 +51,7 @@ func (k Keeper) GetBallotList(ctx sdk.Context, height int64) (val types.BallotLi } func (k Keeper) GetMaturedBallots(ctx sdk.Context, maturityBlocks int64) (val types.BallotListForHeight, found bool) { - return k.GetBallotList(ctx, ctx.BlockHeight()-maturityBlocks) + return k.GetBallotList(ctx, GetMaturedBallotHeight(ctx, maturityBlocks)) } func (k Keeper) GetAllBallots(ctx sdk.Context) (voters []*types.Ballot) { @@ -65,3 +75,18 @@ func (k Keeper) AddBallotToList(ctx sdk.Context, ballot types.Ballot) { list.BallotsIndexList = append(list.BallotsIndexList, ballot.BallotIdentifier) k.SetBallotList(ctx, &list) } + +// ClearMaturedBallots deletes all matured ballots and the list of ballots for a given height. +// It also emits an event for each ballot deleted. +func (k Keeper) ClearMaturedBallots(ctx sdk.Context, ballots []types.Ballot, maturityBlocks int64) { + for _, ballot := range ballots { + k.DeleteBallot(ctx, ballot.BallotIdentifier) + EmitEventBallotDeleted(ctx, ballot) + } + k.DeleteBallotList(ctx, GetMaturedBallotHeight(ctx, maturityBlocks)) + return +} + +func GetMaturedBallotHeight(ctx sdk.Context, maturityBlocks int64) int64 { + return ctx.BlockHeight() - maturityBlocks +} diff --git a/x/observer/keeper/events.go b/x/observer/keeper/events.go index d1ddbc44ff..090b4ed41a 100644 --- a/x/observer/keeper/events.go +++ b/x/observer/keeper/events.go @@ -21,6 +21,18 @@ func EmitEventBallotCreated(ctx sdk.Context, ballot types.Ballot, observationHas } } +func EmitEventBallotDeleted(ctx sdk.Context, ballot types.Ballot) { + err := ctx.EventManager().EmitTypedEvent(&types.EventBallotDeleted{ + MsgTypeUrl: "zetachain.zetacore.observer.internal.BallotDeleted", + BallotIdentifier: ballot.BallotIdentifier, + BallotType: ballot.ObservationType.String(), + Voters: ballot.GenerateVoterList(), + }) + if err != nil { + ctx.Logger().Error("failed to emit EventBallotDeleted : %s", err.Error()) + } +} + func EmitEventKeyGenBlockUpdated(ctx sdk.Context, keygen *types.Keygen) { err := ctx.EventManager().EmitTypedEvents(&types.EventKeygenBlockUpdated{ MsgTypeUrl: sdk.MsgTypeURL(&types.MsgUpdateKeygen{}), diff --git a/x/observer/keeper/grpc_query_ballot.go b/x/observer/keeper/grpc_query_ballot.go index 75ffd6ff07..85d76cdc21 100644 --- a/x/observer/keeper/grpc_query_ballot.go +++ b/x/observer/keeper/grpc_query_ballot.go @@ -41,18 +41,9 @@ func (k Keeper) BallotByIdentifier( return nil, status.Error(codes.NotFound, "not found ballot") } - votersList := make([]*types.VoterList, len(ballot.VoterList)) - for i, voterAddress := range ballot.VoterList { - voter := types.VoterList{ - VoterAddress: voterAddress, - VoteType: ballot.Votes[ballot.GetVoterIndex(voterAddress)], - } - votersList[i] = &voter - } - return &types.QueryBallotByIdentifierResponse{ BallotIdentifier: ballot.BallotIdentifier, - Voters: votersList, + Voters: ballot.GenerateVoterList(), ObservationType: ballot.ObservationType, BallotStatus: ballot.BallotStatus, }, nil diff --git a/x/observer/types/ballot.go b/x/observer/types/ballot.go index 6c04963cf9..8464f31032 100644 --- a/x/observer/types/ballot.go +++ b/x/observer/types/ballot.go @@ -115,3 +115,15 @@ func (m Ballot) BuildRewardsDistribution(rewardsMap map[string]int64) int64 { } return totalRewardUnits } + +func (m Ballot) GenerateVoterList() []VoterList { + votersList := make([]VoterList, len(m.VoterList)) + for i, voterAddress := range m.VoterList { + voter := VoterList{ + VoterAddress: voterAddress, + VoteType: m.Votes[m.GetVoterIndex(voterAddress)], + } + votersList[i] = voter + } + return votersList +} diff --git a/x/observer/types/ballot.pb.go b/x/observer/types/ballot.pb.go index 46d4a4d9e3..951f7eb2e4 100644 --- a/x/observer/types/ballot.pb.go +++ b/x/observer/types/ballot.pb.go @@ -228,11 +228,64 @@ func (m *BallotListForHeight) GetBallotsIndexList() []string { return nil } +type VoterList struct { + VoterAddress string `protobuf:"bytes,1,opt,name=voter_address,json=voterAddress,proto3" json:"voter_address,omitempty"` + VoteType VoteType `protobuf:"varint,2,opt,name=vote_type,json=voteType,proto3,enum=zetachain.zetacore.observer.VoteType" json:"vote_type,omitempty"` +} + +func (m *VoterList) Reset() { *m = VoterList{} } +func (m *VoterList) String() string { return proto.CompactTextString(m) } +func (*VoterList) ProtoMessage() {} +func (*VoterList) Descriptor() ([]byte, []int) { + return fileDescriptor_18c7141b763f2e87, []int{2} +} +func (m *VoterList) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *VoterList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_VoterList.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *VoterList) XXX_Merge(src proto.Message) { + xxx_messageInfo_VoterList.Merge(m, src) +} +func (m *VoterList) XXX_Size() int { + return m.Size() +} +func (m *VoterList) XXX_DiscardUnknown() { + xxx_messageInfo_VoterList.DiscardUnknown(m) +} + +var xxx_messageInfo_VoterList proto.InternalMessageInfo + +func (m *VoterList) GetVoterAddress() string { + if m != nil { + return m.VoterAddress + } + return "" +} + +func (m *VoterList) GetVoteType() VoteType { + if m != nil { + return m.VoteType + } + return VoteType_SuccessObservation +} + func init() { proto.RegisterEnum("zetachain.zetacore.observer.VoteType", VoteType_name, VoteType_value) proto.RegisterEnum("zetachain.zetacore.observer.BallotStatus", BallotStatus_name, BallotStatus_value) proto.RegisterType((*Ballot)(nil), "zetachain.zetacore.observer.Ballot") proto.RegisterType((*BallotListForHeight)(nil), "zetachain.zetacore.observer.BallotListForHeight") + proto.RegisterType((*VoterList)(nil), "zetachain.zetacore.observer.VoterList") } func init() { @@ -240,42 +293,44 @@ func init() { } var fileDescriptor_18c7141b763f2e87 = []byte{ - // 545 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0xc1, 0x6e, 0xd3, 0x4c, - 0x10, 0x8e, 0x93, 0x26, 0x7f, 0xb3, 0x7f, 0x69, 0xc2, 0x12, 0x45, 0x56, 0x10, 0x6e, 0x14, 0x89, - 0xca, 0xa4, 0xad, 0x2d, 0x15, 0x6e, 0xdc, 0x02, 0x44, 0x44, 0x42, 0x05, 0xdc, 0x0a, 0x54, 0x38, - 0x58, 0x8e, 0x3d, 0xc4, 0x2b, 0x5c, 0x6f, 0xb4, 0xbb, 0xa9, 0xda, 0x3c, 0x05, 0x0f, 0xc1, 0x81, - 0x47, 0xe9, 0xb1, 0x47, 0xc4, 0xa1, 0x82, 0xe4, 0x45, 0xd0, 0xee, 0xda, 0xad, 0x91, 0xa2, 0x9c, - 0x76, 0x67, 0xe6, 0x9b, 0x6f, 0x66, 0xe7, 0xdb, 0x41, 0xf6, 0x1c, 0x44, 0x10, 0xc6, 0x01, 0x49, - 0x5d, 0x75, 0xa3, 0x0c, 0x5c, 0x3a, 0xe6, 0xc0, 0xce, 0x81, 0xb9, 0xe3, 0x20, 0x49, 0xa8, 0x70, - 0xa6, 0x8c, 0x0a, 0x8a, 0x1f, 0xde, 0x22, 0x9d, 0x1c, 0xe9, 0xe4, 0xc8, 0x4e, 0x6b, 0x42, 0x27, - 0x54, 0xe1, 0x5c, 0x79, 0xd3, 0x29, 0x9d, 0xfe, 0x3a, 0xf2, 0xfc, 0xa2, 0xb1, 0xbd, 0x3f, 0x15, - 0x54, 0x1b, 0xa8, 0x7a, 0xb8, 0x85, 0xaa, 0x24, 0x8d, 0xe0, 0xc2, 0x34, 0xba, 0x86, 0x5d, 0xf7, - 0xb4, 0x81, 0xf7, 0xd0, 0x7d, 0xdd, 0x8f, 0x4f, 0x22, 0x48, 0x05, 0xf9, 0x42, 0x80, 0x99, 0x65, - 0x85, 0x68, 0xea, 0xc0, 0xe8, 0xd6, 0x8f, 0x1f, 0x21, 0x74, 0x4e, 0x05, 0x30, 0x3f, 0x21, 0x5c, - 0x98, 0x95, 0x6e, 0xc5, 0xae, 0x7b, 0x75, 0xe5, 0x79, 0x43, 0xb8, 0xc0, 0xcf, 0x51, 0x55, 0x1a, - 0xdc, 0xdc, 0xe8, 0x56, 0xec, 0xed, 0xc3, 0xc7, 0xce, 0x9a, 0xb7, 0x39, 0x1f, 0xa8, 0x80, 0x93, - 0xcb, 0x29, 0x78, 0x3a, 0x07, 0x7f, 0x44, 0x4d, 0x1d, 0x0b, 0x04, 0xa1, 0xa9, 0x2f, 0x2e, 0xa7, - 0x60, 0x56, 0xbb, 0x86, 0xbd, 0x7d, 0xb8, 0xbf, 0x96, 0xe7, 0xed, 0x5d, 0x92, 0xa2, 0x6b, 0xd0, - 0x7f, 0x1d, 0xf8, 0x14, 0x65, 0x0f, 0xf1, 0x45, 0xcc, 0x80, 0xc7, 0x34, 0x89, 0xcc, 0x9a, 0x7c, - 0xe0, 0xc0, 0xb9, 0xba, 0xd9, 0x29, 0xfd, 0xba, 0xd9, 0xd9, 0x9d, 0x10, 0x11, 0xcf, 0xc6, 0x4e, - 0x48, 0xcf, 0xdc, 0x90, 0xf2, 0x33, 0xca, 0xb3, 0xe3, 0x80, 0x47, 0x5f, 0x5d, 0xd9, 0x09, 0x77, - 0x5e, 0x42, 0xe8, 0x35, 0x34, 0xcf, 0x49, 0x4e, 0x83, 0x8f, 0xd0, 0xbd, 0x8c, 0x9a, 0x8b, 0x40, - 0xcc, 0xb8, 0xf9, 0x9f, 0x6a, 0xf8, 0xc9, 0xda, 0x86, 0xb5, 0x1c, 0xc7, 0x2a, 0xc1, 0xdb, 0x1a, - 0x17, 0x2c, 0xfc, 0x0c, 0xb5, 0x33, 0xbe, 0x90, 0x81, 0x9e, 0x43, 0x0c, 0x64, 0x12, 0x0b, 0x73, - 0xb3, 0x6b, 0xd8, 0x15, 0xaf, 0xa5, 0xa3, 0x2f, 0xb2, 0xe0, 0x6b, 0x15, 0xeb, 0x7d, 0x46, 0x0f, - 0x34, 0xa7, 0x14, 0x61, 0x48, 0x99, 0x76, 0xe3, 0x36, 0xaa, 0x65, 0xc9, 0x86, 0x4a, 0xce, 0x2c, - 0xbc, 0x8f, 0xb0, 0xa6, 0xe1, 0xbe, 0xfa, 0x02, 0x5a, 0xcc, 0xb2, 0x12, 0x33, 0x9b, 0x14, 0x1f, - 0xc9, 0x80, 0xa4, 0xeb, 0xbf, 0x47, 0x9b, 0xb9, 0x52, 0xb8, 0x8d, 0xf0, 0xf1, 0x2c, 0x0c, 0x81, - 0xf3, 0xc2, 0xd0, 0x9b, 0x25, 0xe9, 0x1f, 0x06, 0x24, 0x99, 0x31, 0x28, 0xfa, 0x0d, 0xdc, 0x40, - 0xff, 0x1f, 0x51, 0x71, 0x0a, 0x42, 0x32, 0x44, 0xcd, 0x72, 0x67, 0xe3, 0xc7, 0x77, 0xcb, 0xe8, - 0xcf, 0xd1, 0x56, 0x71, 0x06, 0x78, 0x17, 0xf5, 0xb4, 0x3d, 0x24, 0x69, 0x90, 0x90, 0x39, 0x44, - 0xfe, 0xca, 0x32, 0x2b, 0x70, 0x2b, 0xcb, 0xb6, 0x50, 0x53, 0xe3, 0x46, 0xe9, 0x3b, 0x46, 0x27, - 0x0c, 0x38, 0xcf, 0x6b, 0x0f, 0x5e, 0x5d, 0x2d, 0x2c, 0xe3, 0x7a, 0x61, 0x19, 0xbf, 0x17, 0x96, - 0xf1, 0x6d, 0x69, 0x95, 0xae, 0x97, 0x56, 0xe9, 0xe7, 0xd2, 0x2a, 0x7d, 0xda, 0x2b, 0x7c, 0x02, - 0x29, 0xda, 0x81, 0xde, 0xb0, 0x94, 0x46, 0xe0, 0x5e, 0xdc, 0xed, 0x97, 0xfa, 0x0d, 0xe3, 0x9a, - 0xda, 0xae, 0xa7, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x5c, 0x75, 0x1d, 0x77, 0xe8, 0x03, 0x00, - 0x00, + // 582 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0xc1, 0x6e, 0xd3, 0x40, + 0x10, 0x8d, 0x93, 0x36, 0x24, 0x43, 0xda, 0x84, 0x25, 0x8a, 0xac, 0x20, 0xdc, 0x28, 0x88, 0xca, + 0xa4, 0xad, 0x2d, 0x15, 0x6e, 0x9c, 0x08, 0x10, 0x11, 0x09, 0x15, 0x70, 0xab, 0xa2, 0xc2, 0xc1, + 0x72, 0xec, 0x25, 0x5e, 0xe1, 0x7a, 0xa3, 0xdd, 0x4d, 0xd4, 0xe6, 0x2b, 0xf8, 0x08, 0x0e, 0x7c, + 0x4a, 0x8f, 0x3d, 0x22, 0x0e, 0x15, 0x24, 0x3f, 0x82, 0xbc, 0x6b, 0xa7, 0x41, 0x8a, 0x22, 0x4e, + 0xde, 0x79, 0xf3, 0xe6, 0xed, 0x78, 0xde, 0x2c, 0x98, 0x53, 0x2c, 0x3c, 0x3f, 0xf4, 0x48, 0x6c, + 0xcb, 0x13, 0x65, 0xd8, 0xa6, 0x03, 0x8e, 0xd9, 0x04, 0x33, 0x7b, 0xe0, 0x45, 0x11, 0x15, 0xd6, + 0x88, 0x51, 0x41, 0xd1, 0x83, 0x05, 0xd3, 0xca, 0x98, 0x56, 0xc6, 0x6c, 0xd6, 0x87, 0x74, 0x48, + 0x25, 0xcf, 0x4e, 0x4e, 0xaa, 0xa4, 0xd9, 0x59, 0x27, 0x9e, 0x1d, 0x14, 0xb7, 0xfd, 0xa7, 0x00, + 0xc5, 0xae, 0xbc, 0x0f, 0xd5, 0x61, 0x93, 0xc4, 0x01, 0xbe, 0xd0, 0xb5, 0x96, 0x66, 0x96, 0x1d, + 0x15, 0xa0, 0x3d, 0xb8, 0xa7, 0xfa, 0x71, 0x49, 0x80, 0x63, 0x41, 0xbe, 0x10, 0xcc, 0xf4, 0xbc, + 0x64, 0xd4, 0x54, 0xa2, 0xbf, 0xc0, 0xd1, 0x43, 0x80, 0x09, 0x15, 0x98, 0xb9, 0x11, 0xe1, 0x42, + 0x2f, 0xb4, 0x0a, 0x66, 0xd9, 0x29, 0x4b, 0xe4, 0x2d, 0xe1, 0x02, 0x3d, 0x87, 0xcd, 0x24, 0xe0, + 0xfa, 0x46, 0xab, 0x60, 0x6e, 0x1f, 0x3e, 0xb6, 0xd6, 0xfc, 0x9b, 0x75, 0x4a, 0x05, 0x3e, 0xb9, + 0x1c, 0x61, 0x47, 0xd5, 0xa0, 0x8f, 0x50, 0x53, 0x39, 0x4f, 0x10, 0x1a, 0xbb, 0xe2, 0x72, 0x84, + 0xf5, 0xcd, 0x96, 0x66, 0x6e, 0x1f, 0xee, 0xaf, 0xd5, 0x79, 0x77, 0x5b, 0x24, 0xe5, 0xaa, 0xf4, + 0x5f, 0x00, 0x9d, 0x41, 0xfa, 0x23, 0xae, 0x08, 0x19, 0xe6, 0x21, 0x8d, 0x02, 0xbd, 0x98, 0xfc, + 0x60, 0xd7, 0xba, 0xba, 0xd9, 0xc9, 0xfd, 0xba, 0xd9, 0xd9, 0x1d, 0x12, 0x11, 0x8e, 0x07, 0x96, + 0x4f, 0xcf, 0x6d, 0x9f, 0xf2, 0x73, 0xca, 0xd3, 0xcf, 0x01, 0x0f, 0xbe, 0xda, 0x49, 0x27, 0xdc, + 0x7a, 0x85, 0x7d, 0xa7, 0xaa, 0x74, 0x4e, 0x32, 0x19, 0x74, 0x04, 0x5b, 0xa9, 0x34, 0x17, 0x9e, + 0x18, 0x73, 0xfd, 0x8e, 0x6c, 0xf8, 0xc9, 0xda, 0x86, 0x95, 0x1d, 0xc7, 0xb2, 0xc0, 0xa9, 0x0c, + 0x96, 0x22, 0xf4, 0x0c, 0x1a, 0xa9, 0x9e, 0xcf, 0xb0, 0x9a, 0x43, 0x88, 0xc9, 0x30, 0x14, 0x7a, + 0xa9, 0xa5, 0x99, 0x05, 0xa7, 0xae, 0xb2, 0x2f, 0xd3, 0xe4, 0x1b, 0x99, 0x6b, 0x7f, 0x86, 0xfb, + 0x4a, 0x33, 0x31, 0xa1, 0x47, 0x99, 0x82, 0x51, 0x03, 0x8a, 0x69, 0xb1, 0x26, 0x8b, 0xd3, 0x08, + 0xed, 0x03, 0x52, 0x32, 0xdc, 0x95, 0x2b, 0xa0, 0xcc, 0xcc, 0x4b, 0x33, 0xd3, 0x49, 0xf1, 0x7e, + 0x92, 0x48, 0xe4, 0xda, 0x02, 0xca, 0xa7, 0x0b, 0x83, 0x1f, 0xc1, 0x96, 0xf2, 0xdf, 0x0b, 0x02, + 0x86, 0x39, 0x4f, 0x57, 0xa9, 0x22, 0xc1, 0x17, 0x0a, 0x43, 0x5d, 0x90, 0x2b, 0xa1, 0x1c, 0xcc, + 0xcb, 0x81, 0xfc, 0xe7, 0x26, 0x94, 0x26, 0xe9, 0xa9, 0xf3, 0x01, 0x4a, 0x19, 0x8a, 0x1a, 0x80, + 0x8e, 0xc7, 0xbe, 0x8f, 0x39, 0x5f, 0xb2, 0xba, 0x96, 0x4b, 0xf0, 0x9e, 0x47, 0xa2, 0x31, 0xc3, + 0xcb, 0xb8, 0x86, 0xaa, 0x70, 0xf7, 0x88, 0x8a, 0x33, 0x2c, 0x12, 0x85, 0xa0, 0x96, 0x6f, 0x6e, + 0xfc, 0xf8, 0x6e, 0x68, 0x9d, 0x29, 0x54, 0x96, 0x27, 0x8f, 0x76, 0xa1, 0xad, 0xe2, 0x1e, 0x89, + 0xbd, 0x88, 0x4c, 0x71, 0xe0, 0xae, 0xbc, 0x66, 0x05, 0x6f, 0xe5, 0xb5, 0x75, 0xa8, 0x29, 0x5e, + 0x3f, 0x7e, 0xcf, 0xe8, 0x30, 0x19, 0x45, 0x76, 0x77, 0xf7, 0xf5, 0xd5, 0xcc, 0xd0, 0xae, 0x67, + 0x86, 0xf6, 0x7b, 0x66, 0x68, 0xdf, 0xe6, 0x46, 0xee, 0x7a, 0x6e, 0xe4, 0x7e, 0xce, 0x8d, 0xdc, + 0xa7, 0xbd, 0xa5, 0xd5, 0x4b, 0x26, 0x73, 0xa0, 0xde, 0x75, 0x4c, 0x03, 0x6c, 0x5f, 0xdc, 0xbe, + 0x6a, 0xb9, 0x83, 0x83, 0xa2, 0x7c, 0xd3, 0x4f, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0xd9, 0x7c, + 0x81, 0x01, 0x5e, 0x04, 0x00, 0x00, } func (m *Ballot) Marshal() (dAtA []byte, err error) { @@ -404,6 +459,41 @@ func (m *BallotListForHeight) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *VoterList) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *VoterList) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *VoterList) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.VoteType != 0 { + i = encodeVarintBallot(dAtA, i, uint64(m.VoteType)) + i-- + dAtA[i] = 0x10 + } + if len(m.VoterAddress) > 0 { + i -= len(m.VoterAddress) + copy(dAtA[i:], m.VoterAddress) + i = encodeVarintBallot(dAtA, i, uint64(len(m.VoterAddress))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintBallot(dAtA []byte, offset int, v uint64) int { offset -= sovBallot(v) base := offset @@ -474,6 +564,22 @@ func (m *BallotListForHeight) Size() (n int) { return n } +func (m *VoterList) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.VoterAddress) + if l > 0 { + n += 1 + l + sovBallot(uint64(l)) + } + if m.VoteType != 0 { + n += 1 + sovBallot(uint64(m.VoteType)) + } + return n +} + func sovBallot(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -887,6 +993,107 @@ func (m *BallotListForHeight) Unmarshal(dAtA []byte) error { } return nil } +func (m *VoterList) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBallot + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: VoterList: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: VoterList: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VoterAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBallot + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthBallot + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthBallot + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.VoterAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteType", wireType) + } + m.VoteType = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBallot + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.VoteType |= VoteType(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipBallot(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBallot + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipBallot(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/observer/types/events.pb.go b/x/observer/types/events.pb.go index 7fe970546f..24e2281e0e 100644 --- a/x/observer/types/events.pb.go +++ b/x/observer/types/events.pb.go @@ -99,6 +99,74 @@ func (m *EventBallotCreated) GetBallotType() string { return "" } +type EventBallotDeleted struct { + MsgTypeUrl string `protobuf:"bytes,1,opt,name=msg_type_url,json=msgTypeUrl,proto3" json:"msg_type_url,omitempty"` + BallotIdentifier string `protobuf:"bytes,2,opt,name=ballot_identifier,json=ballotIdentifier,proto3" json:"ballot_identifier,omitempty"` + BallotType string `protobuf:"bytes,3,opt,name=ballot_type,json=ballotType,proto3" json:"ballot_type,omitempty"` + Voters []VoterList `protobuf:"bytes,4,rep,name=voters,proto3" json:"voters"` +} + +func (m *EventBallotDeleted) Reset() { *m = EventBallotDeleted{} } +func (m *EventBallotDeleted) String() string { return proto.CompactTextString(m) } +func (*EventBallotDeleted) ProtoMessage() {} +func (*EventBallotDeleted) Descriptor() ([]byte, []int) { + return fileDescriptor_067e682d8234d605, []int{1} +} +func (m *EventBallotDeleted) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventBallotDeleted) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventBallotDeleted.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *EventBallotDeleted) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventBallotDeleted.Merge(m, src) +} +func (m *EventBallotDeleted) XXX_Size() int { + return m.Size() +} +func (m *EventBallotDeleted) XXX_DiscardUnknown() { + xxx_messageInfo_EventBallotDeleted.DiscardUnknown(m) +} + +var xxx_messageInfo_EventBallotDeleted proto.InternalMessageInfo + +func (m *EventBallotDeleted) GetMsgTypeUrl() string { + if m != nil { + return m.MsgTypeUrl + } + return "" +} + +func (m *EventBallotDeleted) GetBallotIdentifier() string { + if m != nil { + return m.BallotIdentifier + } + return "" +} + +func (m *EventBallotDeleted) GetBallotType() string { + if m != nil { + return m.BallotType + } + return "" +} + +func (m *EventBallotDeleted) GetVoters() []VoterList { + if m != nil { + return m.Voters + } + return nil +} + type EventKeygenBlockUpdated struct { MsgTypeUrl string `protobuf:"bytes,1,opt,name=msg_type_url,json=msgTypeUrl,proto3" json:"msg_type_url,omitempty"` KeygenBlock string `protobuf:"bytes,2,opt,name=keygen_block,json=keygenBlock,proto3" json:"keygen_block,omitempty"` @@ -109,7 +177,7 @@ func (m *EventKeygenBlockUpdated) Reset() { *m = EventKeygenBlockUpdated func (m *EventKeygenBlockUpdated) String() string { return proto.CompactTextString(m) } func (*EventKeygenBlockUpdated) ProtoMessage() {} func (*EventKeygenBlockUpdated) Descriptor() ([]byte, []int) { - return fileDescriptor_067e682d8234d605, []int{1} + return fileDescriptor_067e682d8234d605, []int{2} } func (m *EventKeygenBlockUpdated) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -171,7 +239,7 @@ func (m *EventNewObserverAdded) Reset() { *m = EventNewObserverAdded{} } func (m *EventNewObserverAdded) String() string { return proto.CompactTextString(m) } func (*EventNewObserverAdded) ProtoMessage() {} func (*EventNewObserverAdded) Descriptor() ([]byte, []int) { - return fileDescriptor_067e682d8234d605, []int{2} + return fileDescriptor_067e682d8234d605, []int{3} } func (m *EventNewObserverAdded) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -245,7 +313,7 @@ func (m *EventCCTXDisabled) Reset() { *m = EventCCTXDisabled{} } func (m *EventCCTXDisabled) String() string { return proto.CompactTextString(m) } func (*EventCCTXDisabled) ProtoMessage() {} func (*EventCCTXDisabled) Descriptor() ([]byte, []int) { - return fileDescriptor_067e682d8234d605, []int{3} + return fileDescriptor_067e682d8234d605, []int{4} } func (m *EventCCTXDisabled) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -305,7 +373,7 @@ func (m *EventCCTXEnabled) Reset() { *m = EventCCTXEnabled{} } func (m *EventCCTXEnabled) String() string { return proto.CompactTextString(m) } func (*EventCCTXEnabled) ProtoMessage() {} func (*EventCCTXEnabled) Descriptor() ([]byte, []int) { - return fileDescriptor_067e682d8234d605, []int{4} + return fileDescriptor_067e682d8234d605, []int{5} } func (m *EventCCTXEnabled) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -364,7 +432,7 @@ func (m *EventGasPriceIncreaseFlagsUpdated) Reset() { *m = EventGasPrice func (m *EventGasPriceIncreaseFlagsUpdated) String() string { return proto.CompactTextString(m) } func (*EventGasPriceIncreaseFlagsUpdated) ProtoMessage() {} func (*EventGasPriceIncreaseFlagsUpdated) Descriptor() ([]byte, []int) { - return fileDescriptor_067e682d8234d605, []int{5} + return fileDescriptor_067e682d8234d605, []int{6} } func (m *EventGasPriceIncreaseFlagsUpdated) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -409,6 +477,7 @@ func (m *EventGasPriceIncreaseFlagsUpdated) GetGasPriceIncreaseFlags() *GasPrice func init() { proto.RegisterType((*EventBallotCreated)(nil), "zetachain.zetacore.observer.EventBallotCreated") + proto.RegisterType((*EventBallotDeleted)(nil), "zetachain.zetacore.observer.EventBallotDeleted") proto.RegisterType((*EventKeygenBlockUpdated)(nil), "zetachain.zetacore.observer.EventKeygenBlockUpdated") proto.RegisterType((*EventNewObserverAdded)(nil), "zetachain.zetacore.observer.EventNewObserverAdded") proto.RegisterType((*EventCCTXDisabled)(nil), "zetachain.zetacore.observer.EventCCTXDisabled") @@ -421,44 +490,48 @@ func init() { } var fileDescriptor_067e682d8234d605 = []byte{ - // 586 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x54, 0x41, 0x6f, 0xd3, 0x4c, - 0x10, 0x8d, 0xdb, 0x7e, 0x9f, 0x60, 0x53, 0x68, 0x62, 0x51, 0xea, 0x06, 0xc9, 0xb4, 0x91, 0x90, - 0x4a, 0x0b, 0x8e, 0x14, 0x4e, 0x20, 0x2e, 0x24, 0x84, 0x12, 0x81, 0x68, 0x15, 0xb5, 0x12, 0xe2, - 0x62, 0xad, 0xed, 0xa9, 0x6d, 0xc5, 0xd9, 0x8d, 0x76, 0xd7, 0x85, 0x70, 0xe7, 0x0a, 0x5c, 0xf9, - 0x15, 0xfc, 0x0d, 0x8e, 0x3d, 0x72, 0xe0, 0x80, 0x92, 0x3f, 0x82, 0x76, 0xd7, 0x76, 0x82, 0x12, - 0x45, 0xb9, 0x71, 0x5b, 0xcd, 0xbc, 0xf7, 0xf6, 0xbd, 0x59, 0x7b, 0xd0, 0xc1, 0x47, 0x10, 0xd8, - 0x8f, 0x70, 0x4c, 0x1a, 0xea, 0x44, 0x19, 0x34, 0xa8, 0xc7, 0x81, 0x5d, 0x02, 0x6b, 0xc0, 0x25, - 0x10, 0xc1, 0x9d, 0x21, 0xa3, 0x82, 0x9a, 0x77, 0x0a, 0xa4, 0x93, 0x23, 0x9d, 0x1c, 0x59, 0xbb, - 0x15, 0xd2, 0x90, 0x2a, 0x5c, 0x43, 0x9e, 0x34, 0xa5, 0xd6, 0x5c, 0x26, 0xee, 0x33, 0xca, 0xb9, - 0x6a, 0xba, 0x17, 0x09, 0x0e, 0xb3, 0x6b, 0x6a, 0x87, 0xcb, 0x38, 0xf9, 0x41, 0x63, 0xeb, 0xbf, - 0x0c, 0x64, 0x76, 0xa4, 0xc7, 0x16, 0x4e, 0x12, 0x2a, 0xda, 0x0c, 0xb0, 0x80, 0xc0, 0xdc, 0x43, - 0x9b, 0x03, 0x1e, 0xba, 0x62, 0x34, 0x04, 0x37, 0x65, 0x89, 0x65, 0xec, 0x19, 0x07, 0xd7, 0x7b, - 0x68, 0xc0, 0xc3, 0xb3, 0xd1, 0x10, 0xce, 0x59, 0x62, 0x1e, 0xa1, 0xaa, 0xa7, 0x28, 0x6e, 0x1c, - 0x00, 0x11, 0xf1, 0x45, 0x0c, 0xcc, 0x5a, 0x53, 0xb0, 0x8a, 0x6e, 0x74, 0x8b, 0xba, 0x79, 0x1f, - 0x55, 0xf4, 0xbd, 0x58, 0xc4, 0x94, 0xb8, 0x11, 0xe6, 0x91, 0xb5, 0xae, 0xb0, 0x5b, 0x33, 0xf5, - 0x97, 0x98, 0x47, 0x52, 0x77, 0x16, 0xaa, 0x62, 0x58, 0x1b, 0x5a, 0x77, 0xa6, 0xd1, 0x96, 0x75, - 0xf3, 0x2e, 0x2a, 0x67, 0x26, 0xa4, 0x53, 0xeb, 0x3f, 0xed, 0x52, 0x97, 0xa4, 0xd1, 0xfa, 0x27, - 0x03, 0xed, 0xa8, 0x78, 0xaf, 0x60, 0x14, 0x02, 0x69, 0x25, 0xd4, 0xef, 0x9f, 0x0f, 0x83, 0x15, - 0x33, 0xee, 0xa3, 0xcd, 0xbe, 0xe2, 0xb9, 0x9e, 0x24, 0x66, 0xf1, 0xca, 0xfd, 0xa9, 0x96, 0x79, - 0x0f, 0xdd, 0xcc, 0x20, 0xc3, 0xd4, 0xeb, 0xc3, 0x88, 0x67, 0xb9, 0x6e, 0xe8, 0xea, 0xa9, 0x2e, - 0xd6, 0xbf, 0xad, 0xa1, 0x6d, 0xe5, 0xe3, 0x0d, 0xbc, 0x3f, 0xc9, 0x5e, 0xe0, 0x59, 0x10, 0xac, - 0xe4, 0xa2, 0x18, 0x1e, 0x30, 0x17, 0x07, 0x01, 0x03, 0xce, 0x33, 0x27, 0x5b, 0x74, 0x2a, 0x25, - 0xcb, 0xe6, 0x53, 0x54, 0x53, 0x2f, 0x9e, 0xc4, 0x40, 0x84, 0x1b, 0x32, 0x4c, 0x04, 0x40, 0x41, - 0xd2, 0xce, 0xac, 0x29, 0xe2, 0x58, 0x03, 0x72, 0xf6, 0x13, 0xb4, 0xbb, 0x80, 0xad, 0x73, 0x65, - 0x4f, 0xb0, 0x33, 0x47, 0xd6, 0x09, 0xcd, 0xc7, 0x68, 0xb7, 0x30, 0x99, 0x60, 0x2e, 0xf4, 0xc4, - 0x5c, 0x9f, 0xa6, 0x44, 0xa8, 0x77, 0xd9, 0xe8, 0xdd, 0xce, 0x01, 0xaf, 0x31, 0x17, 0x6a, 0x7a, - 0x6d, 0xd9, 0xad, 0x7f, 0x31, 0x50, 0x55, 0xcd, 0xa6, 0xdd, 0x3e, 0x7b, 0xfb, 0x3c, 0xe6, 0xd8, - 0x4b, 0x56, 0x9a, 0xcb, 0x21, 0xaa, 0xc4, 0xbc, 0x4b, 0x3c, 0x9a, 0x92, 0xa0, 0x43, 0x14, 0x4b, - 0xcd, 0xe5, 0x5a, 0x6f, 0xae, 0x6e, 0x3e, 0x40, 0xd5, 0x98, 0x9f, 0xa4, 0xe2, 0x2f, 0xf0, 0xba, - 0x02, 0xcf, 0x37, 0xea, 0x9f, 0x0d, 0x54, 0x29, 0x1c, 0xe5, 0x12, 0xff, 0xd2, 0xd0, 0x77, 0x03, - 0xed, 0x2b, 0x43, 0xc7, 0x98, 0x9f, 0xb2, 0xd8, 0x87, 0x2e, 0xf1, 0x19, 0x60, 0x0e, 0x2f, 0xe4, - 0x6f, 0xbf, 0xfa, 0x07, 0x1d, 0xa1, 0xed, 0x70, 0x91, 0x82, 0xb2, 0x59, 0x6e, 0x36, 0x9d, 0x25, - 0x0b, 0xca, 0x59, 0x78, 0x77, 0x6f, 0xb1, 0x60, 0xab, 0xf3, 0x63, 0x6c, 0x1b, 0x57, 0x63, 0xdb, - 0xf8, 0x3d, 0xb6, 0x8d, 0xaf, 0x13, 0xbb, 0x74, 0x35, 0xb1, 0x4b, 0x3f, 0x27, 0x76, 0xe9, 0xdd, - 0x51, 0x18, 0x8b, 0x28, 0xf5, 0x1c, 0x9f, 0x0e, 0xd4, 0x7a, 0x7a, 0xa8, 0x37, 0x15, 0xa1, 0x01, - 0x34, 0x3e, 0x4c, 0xf7, 0x94, 0x4c, 0xc1, 0xbd, 0xff, 0xd5, 0x96, 0x7a, 0xf4, 0x27, 0x00, 0x00, - 0xff, 0xff, 0xfb, 0x7d, 0x42, 0xa2, 0x64, 0x05, 0x00, 0x00, + // 641 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x54, 0x41, 0x4f, 0x13, 0x41, + 0x14, 0xee, 0xd2, 0x4a, 0x74, 0x8a, 0x52, 0x36, 0x22, 0x4b, 0x4d, 0x0a, 0x34, 0xd1, 0x20, 0x68, + 0x9b, 0xd4, 0x93, 0xc6, 0x8b, 0x2d, 0x88, 0x44, 0x22, 0xa4, 0x01, 0x63, 0xbc, 0x6c, 0x66, 0x77, + 0x1f, 0xdb, 0x49, 0x97, 0x99, 0x66, 0x66, 0x16, 0xad, 0x77, 0xaf, 0xea, 0xd5, 0x5f, 0xe1, 0xdf, + 0x20, 0x9e, 0x38, 0x7a, 0x30, 0xc6, 0xc0, 0x1f, 0x31, 0x33, 0xb3, 0xbb, 0x05, 0xda, 0x34, 0xbd, + 0x18, 0x6f, 0x9b, 0xf7, 0xbe, 0xef, 0x9b, 0xef, 0x7b, 0x7d, 0x7d, 0x68, 0xf5, 0x23, 0x48, 0xec, + 0x77, 0x30, 0xa1, 0x75, 0xfd, 0xc5, 0x38, 0xd4, 0x99, 0x27, 0x80, 0x1f, 0x03, 0xaf, 0xc3, 0x31, + 0x50, 0x29, 0x6a, 0x3d, 0xce, 0x24, 0xb3, 0xef, 0x66, 0xc8, 0x5a, 0x8a, 0xac, 0xa5, 0xc8, 0xf2, + 0xed, 0x90, 0x85, 0x4c, 0xe3, 0xea, 0xea, 0xcb, 0x50, 0xca, 0x8d, 0x71, 0xe2, 0x3e, 0x67, 0x42, + 0xe8, 0xa6, 0x7b, 0x18, 0xe1, 0x30, 0x79, 0xa6, 0xbc, 0x36, 0x8e, 0x93, 0x7e, 0x24, 0xd8, 0xb1, + 0xe6, 0x3d, 0x1c, 0x45, 0x4c, 0x1a, 0x64, 0xf5, 0x97, 0x85, 0xec, 0x4d, 0x95, 0xa6, 0xa9, 0xab, + 0x2d, 0x0e, 0x58, 0x42, 0x60, 0x2f, 0xa3, 0x99, 0x23, 0x11, 0xba, 0xb2, 0xdf, 0x03, 0x37, 0xe6, + 0x91, 0x63, 0x2d, 0x5b, 0xab, 0x37, 0xda, 0xe8, 0x48, 0x84, 0xfb, 0xfd, 0x1e, 0x1c, 0xf0, 0xc8, + 0x5e, 0x47, 0x73, 0x46, 0xc8, 0x25, 0x01, 0x50, 0x49, 0x0e, 0x09, 0x70, 0x67, 0x4a, 0xc3, 0x4a, + 0xa6, 0xb1, 0x9d, 0xd5, 0xed, 0x07, 0xa8, 0x64, 0x9e, 0xc7, 0x92, 0x30, 0xea, 0x76, 0xb0, 0xe8, + 0x38, 0x79, 0x8d, 0x9d, 0xbd, 0x50, 0x7f, 0x89, 0x45, 0x47, 0xe9, 0x5e, 0x84, 0xea, 0x10, 0x4e, + 0xc1, 0xe8, 0x5e, 0x68, 0xb4, 0x54, 0xdd, 0x5e, 0x42, 0xc5, 0xc4, 0x84, 0x72, 0xea, 0x5c, 0x33, + 0x2e, 0x4d, 0x49, 0x19, 0xad, 0xfe, 0xb8, 0x1c, 0x6f, 0x03, 0x22, 0xf8, 0x07, 0xf1, 0xae, 0xd8, + 0xc8, 0x5f, 0xb5, 0x61, 0x6f, 0xa0, 0xe9, 0x63, 0x26, 0x81, 0x0b, 0xa7, 0xb0, 0x9c, 0x5f, 0x2d, + 0x36, 0xee, 0xd7, 0xc6, 0xec, 0x4c, 0xed, 0x8d, 0x82, 0xee, 0x10, 0x21, 0x9b, 0x85, 0x93, 0xdf, + 0x4b, 0xb9, 0x76, 0xc2, 0xad, 0x7e, 0xb2, 0xd0, 0x82, 0x0e, 0xf3, 0x0a, 0xfa, 0x21, 0xd0, 0x66, + 0xc4, 0xfc, 0xee, 0x41, 0x2f, 0x98, 0xf0, 0x07, 0x5b, 0x41, 0x33, 0x5d, 0xcd, 0x73, 0x3d, 0x45, + 0x4c, 0xc2, 0x14, 0xbb, 0x03, 0x2d, 0xfb, 0x1e, 0xba, 0x95, 0x40, 0x7a, 0xb1, 0xd7, 0x85, 0xbe, + 0x48, 0xa2, 0xdc, 0x34, 0xd5, 0x3d, 0x53, 0xac, 0x7e, 0x9b, 0x42, 0xf3, 0xda, 0xc7, 0x6b, 0x78, + 0xbf, 0x9b, 0x98, 0x7e, 0x1e, 0x04, 0x13, 0xb9, 0xc8, 0x36, 0x01, 0xb8, 0x8b, 0x83, 0x80, 0x83, + 0x10, 0x89, 0x93, 0x59, 0x36, 0x90, 0x52, 0x65, 0xfb, 0x19, 0x2a, 0xeb, 0xd9, 0x44, 0x04, 0xa8, + 0x74, 0x43, 0x8e, 0xa9, 0x04, 0xc8, 0x48, 0xc6, 0x99, 0x33, 0x40, 0x6c, 0x19, 0x40, 0xca, 0x7e, + 0x8a, 0x16, 0x47, 0xb0, 0x4d, 0xae, 0x64, 0x9f, 0x16, 0x86, 0xc8, 0x26, 0xa1, 0xfd, 0x04, 0x2d, + 0x66, 0x26, 0x23, 0x2c, 0xa4, 0x99, 0x98, 0xeb, 0xb3, 0x98, 0x4a, 0xbd, 0x64, 0x85, 0xf6, 0x9d, + 0x14, 0xb0, 0x83, 0x85, 0xd4, 0xd3, 0x6b, 0xa9, 0x6e, 0xf5, 0x8b, 0x85, 0xe6, 0xf4, 0x6c, 0x5a, + 0xad, 0xfd, 0xb7, 0x1b, 0x44, 0x60, 0x2f, 0x9a, 0x68, 0x2e, 0x6b, 0xa8, 0x44, 0xc4, 0x36, 0xf5, + 0x58, 0x4c, 0x83, 0x4d, 0xaa, 0x59, 0x7a, 0x2e, 0xd7, 0xdb, 0x43, 0x75, 0xfb, 0x21, 0x9a, 0x23, + 0x62, 0x37, 0x96, 0x97, 0xc0, 0x79, 0x0d, 0x1e, 0x6e, 0x54, 0x3f, 0x5b, 0xa8, 0x94, 0x39, 0x4a, + 0x25, 0xfe, 0xa7, 0xa1, 0xef, 0x16, 0x5a, 0xd1, 0x86, 0xb6, 0xb0, 0xd8, 0xe3, 0xc4, 0x87, 0x6d, + 0xea, 0x73, 0xc0, 0x02, 0x5e, 0xa8, 0x6b, 0x37, 0xf9, 0x42, 0x77, 0xd0, 0x7c, 0x38, 0x4a, 0x41, + 0xdb, 0x2c, 0x36, 0x1a, 0x63, 0xff, 0x63, 0x23, 0xdf, 0x6e, 0x8f, 0x16, 0x6c, 0x6e, 0x9e, 0x9c, + 0x55, 0xac, 0xd3, 0xb3, 0x8a, 0xf5, 0xe7, 0xac, 0x62, 0x7d, 0x3d, 0xaf, 0xe4, 0x4e, 0xcf, 0x2b, + 0xb9, 0x9f, 0xe7, 0x95, 0xdc, 0xbb, 0xf5, 0x90, 0xc8, 0x4e, 0xec, 0xd5, 0x7c, 0x76, 0xa4, 0x2f, + 0xed, 0x23, 0x73, 0x74, 0x29, 0x0b, 0xa0, 0xfe, 0x61, 0x70, 0x72, 0x55, 0x0a, 0xe1, 0x4d, 0xeb, + 0x93, 0xfb, 0xf8, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x49, 0x3c, 0x6d, 0x5b, 0x06, 0x00, + 0x00, } func (m *EventBallotCreated) Marshal() (dAtA []byte, err error) { @@ -519,6 +592,64 @@ func (m *EventBallotCreated) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *EventBallotDeleted) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *EventBallotDeleted) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventBallotDeleted) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Voters) > 0 { + for iNdEx := len(m.Voters) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Voters[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + if len(m.BallotType) > 0 { + i -= len(m.BallotType) + copy(dAtA[i:], m.BallotType) + i = encodeVarintEvents(dAtA, i, uint64(len(m.BallotType))) + i-- + dAtA[i] = 0x1a + } + if len(m.BallotIdentifier) > 0 { + i -= len(m.BallotIdentifier) + copy(dAtA[i:], m.BallotIdentifier) + i = encodeVarintEvents(dAtA, i, uint64(len(m.BallotIdentifier))) + i-- + dAtA[i] = 0x12 + } + if len(m.MsgTypeUrl) > 0 { + i -= len(m.MsgTypeUrl) + copy(dAtA[i:], m.MsgTypeUrl) + i = encodeVarintEvents(dAtA, i, uint64(len(m.MsgTypeUrl))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *EventKeygenBlockUpdated) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -801,6 +932,33 @@ func (m *EventBallotCreated) Size() (n int) { return n } +func (m *EventBallotDeleted) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.MsgTypeUrl) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.BallotIdentifier) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + l = len(m.BallotType) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + if len(m.Voters) > 0 { + for _, e := range m.Voters { + l = e.Size() + n += 1 + l + sovEvents(uint64(l)) + } + } + return n +} + func (m *EventKeygenBlockUpdated) Size() (n int) { if m == nil { return 0 @@ -1121,6 +1279,186 @@ func (m *EventBallotCreated) Unmarshal(dAtA []byte) error { } return nil } +func (m *EventBallotDeleted) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: EventBallotDeleted: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventBallotDeleted: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MsgTypeUrl", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MsgTypeUrl = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BallotIdentifier", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BallotIdentifier = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BallotType", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BallotType = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Voters", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Voters = append(m.Voters, VoterList{}) + if err := m.Voters[len(m.Voters)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *EventKeygenBlockUpdated) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/x/observer/types/query.pb.go b/x/observer/types/query.pb.go index 4f0216d03c..1999ea0d33 100644 --- a/x/observer/types/query.pb.go +++ b/x/observer/types/query.pb.go @@ -1092,61 +1092,9 @@ func (m *QueryBallotByIdentifierRequest) GetBallotIdentifier() string { return "" } -type VoterList struct { - VoterAddress string `protobuf:"bytes,1,opt,name=voter_address,json=voterAddress,proto3" json:"voter_address,omitempty"` - VoteType VoteType `protobuf:"varint,2,opt,name=vote_type,json=voteType,proto3,enum=zetachain.zetacore.observer.VoteType" json:"vote_type,omitempty"` -} - -func (m *VoterList) Reset() { *m = VoterList{} } -func (m *VoterList) String() string { return proto.CompactTextString(m) } -func (*VoterList) ProtoMessage() {} -func (*VoterList) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{23} -} -func (m *VoterList) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *VoterList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_VoterList.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *VoterList) XXX_Merge(src proto.Message) { - xxx_messageInfo_VoterList.Merge(m, src) -} -func (m *VoterList) XXX_Size() int { - return m.Size() -} -func (m *VoterList) XXX_DiscardUnknown() { - xxx_messageInfo_VoterList.DiscardUnknown(m) -} - -var xxx_messageInfo_VoterList proto.InternalMessageInfo - -func (m *VoterList) GetVoterAddress() string { - if m != nil { - return m.VoterAddress - } - return "" -} - -func (m *VoterList) GetVoteType() VoteType { - if m != nil { - return m.VoteType - } - return VoteType_SuccessObservation -} - type QueryBallotByIdentifierResponse struct { BallotIdentifier string `protobuf:"bytes,1,opt,name=ballot_identifier,json=ballotIdentifier,proto3" json:"ballot_identifier,omitempty"` - Voters []*VoterList `protobuf:"bytes,2,rep,name=voters,proto3" json:"voters,omitempty"` + Voters []VoterList `protobuf:"bytes,2,rep,name=voters,proto3" json:"voters"` ObservationType ObservationType `protobuf:"varint,3,opt,name=observation_type,json=observationType,proto3,enum=zetachain.zetacore.observer.ObservationType" json:"observation_type,omitempty"` BallotStatus BallotStatus `protobuf:"varint,4,opt,name=ballot_status,json=ballotStatus,proto3,enum=zetachain.zetacore.observer.BallotStatus" json:"ballot_status,omitempty"` } @@ -1155,7 +1103,7 @@ func (m *QueryBallotByIdentifierResponse) Reset() { *m = QueryBallotById func (m *QueryBallotByIdentifierResponse) String() string { return proto.CompactTextString(m) } func (*QueryBallotByIdentifierResponse) ProtoMessage() {} func (*QueryBallotByIdentifierResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{24} + return fileDescriptor_25b2aa420449a0c0, []int{23} } func (m *QueryBallotByIdentifierResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1191,7 +1139,7 @@ func (m *QueryBallotByIdentifierResponse) GetBallotIdentifier() string { return "" } -func (m *QueryBallotByIdentifierResponse) GetVoters() []*VoterList { +func (m *QueryBallotByIdentifierResponse) GetVoters() []VoterList { if m != nil { return m.Voters } @@ -1219,7 +1167,7 @@ func (m *QueryObserverSet) Reset() { *m = QueryObserverSet{} } func (m *QueryObserverSet) String() string { return proto.CompactTextString(m) } func (*QueryObserverSet) ProtoMessage() {} func (*QueryObserverSet) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{25} + return fileDescriptor_25b2aa420449a0c0, []int{24} } func (m *QueryObserverSet) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1256,7 +1204,7 @@ func (m *QueryObserverSetResponse) Reset() { *m = QueryObserverSetRespon func (m *QueryObserverSetResponse) String() string { return proto.CompactTextString(m) } func (*QueryObserverSetResponse) ProtoMessage() {} func (*QueryObserverSetResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{26} + return fileDescriptor_25b2aa420449a0c0, []int{25} } func (m *QueryObserverSetResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1299,7 +1247,7 @@ func (m *QuerySupportedChains) Reset() { *m = QuerySupportedChains{} } func (m *QuerySupportedChains) String() string { return proto.CompactTextString(m) } func (*QuerySupportedChains) ProtoMessage() {} func (*QuerySupportedChains) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{27} + return fileDescriptor_25b2aa420449a0c0, []int{26} } func (m *QuerySupportedChains) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1336,7 +1284,7 @@ func (m *QuerySupportedChainsResponse) Reset() { *m = QuerySupportedChai func (m *QuerySupportedChainsResponse) String() string { return proto.CompactTextString(m) } func (*QuerySupportedChainsResponse) ProtoMessage() {} func (*QuerySupportedChainsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{28} + return fileDescriptor_25b2aa420449a0c0, []int{27} } func (m *QuerySupportedChainsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1380,7 +1328,7 @@ func (m *QueryGetChainParamsForChainRequest) Reset() { *m = QueryGetChai func (m *QueryGetChainParamsForChainRequest) String() string { return proto.CompactTextString(m) } func (*QueryGetChainParamsForChainRequest) ProtoMessage() {} func (*QueryGetChainParamsForChainRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{29} + return fileDescriptor_25b2aa420449a0c0, []int{28} } func (m *QueryGetChainParamsForChainRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1424,7 +1372,7 @@ func (m *QueryGetChainParamsForChainResponse) Reset() { *m = QueryGetCha func (m *QueryGetChainParamsForChainResponse) String() string { return proto.CompactTextString(m) } func (*QueryGetChainParamsForChainResponse) ProtoMessage() {} func (*QueryGetChainParamsForChainResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{30} + return fileDescriptor_25b2aa420449a0c0, []int{29} } func (m *QueryGetChainParamsForChainResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1467,7 +1415,7 @@ func (m *QueryGetChainParamsRequest) Reset() { *m = QueryGetChainParamsR func (m *QueryGetChainParamsRequest) String() string { return proto.CompactTextString(m) } func (*QueryGetChainParamsRequest) ProtoMessage() {} func (*QueryGetChainParamsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{31} + return fileDescriptor_25b2aa420449a0c0, []int{30} } func (m *QueryGetChainParamsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1504,7 +1452,7 @@ func (m *QueryGetChainParamsResponse) Reset() { *m = QueryGetChainParams func (m *QueryGetChainParamsResponse) String() string { return proto.CompactTextString(m) } func (*QueryGetChainParamsResponse) ProtoMessage() {} func (*QueryGetChainParamsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{32} + return fileDescriptor_25b2aa420449a0c0, []int{31} } func (m *QueryGetChainParamsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1548,7 +1496,7 @@ func (m *QueryGetNodeAccountRequest) Reset() { *m = QueryGetNodeAccountR func (m *QueryGetNodeAccountRequest) String() string { return proto.CompactTextString(m) } func (*QueryGetNodeAccountRequest) ProtoMessage() {} func (*QueryGetNodeAccountRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{33} + return fileDescriptor_25b2aa420449a0c0, []int{32} } func (m *QueryGetNodeAccountRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1592,7 +1540,7 @@ func (m *QueryGetNodeAccountResponse) Reset() { *m = QueryGetNodeAccount func (m *QueryGetNodeAccountResponse) String() string { return proto.CompactTextString(m) } func (*QueryGetNodeAccountResponse) ProtoMessage() {} func (*QueryGetNodeAccountResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{34} + return fileDescriptor_25b2aa420449a0c0, []int{33} } func (m *QueryGetNodeAccountResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1636,7 +1584,7 @@ func (m *QueryAllNodeAccountRequest) Reset() { *m = QueryAllNodeAccountR func (m *QueryAllNodeAccountRequest) String() string { return proto.CompactTextString(m) } func (*QueryAllNodeAccountRequest) ProtoMessage() {} func (*QueryAllNodeAccountRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{35} + return fileDescriptor_25b2aa420449a0c0, []int{34} } func (m *QueryAllNodeAccountRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1681,7 +1629,7 @@ func (m *QueryAllNodeAccountResponse) Reset() { *m = QueryAllNodeAccount func (m *QueryAllNodeAccountResponse) String() string { return proto.CompactTextString(m) } func (*QueryAllNodeAccountResponse) ProtoMessage() {} func (*QueryAllNodeAccountResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{36} + return fileDescriptor_25b2aa420449a0c0, []int{35} } func (m *QueryAllNodeAccountResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1731,7 +1679,7 @@ func (m *QueryGetCrosschainFlagsRequest) Reset() { *m = QueryGetCrosscha func (m *QueryGetCrosschainFlagsRequest) String() string { return proto.CompactTextString(m) } func (*QueryGetCrosschainFlagsRequest) ProtoMessage() {} func (*QueryGetCrosschainFlagsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{37} + return fileDescriptor_25b2aa420449a0c0, []int{36} } func (m *QueryGetCrosschainFlagsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1768,7 +1716,7 @@ func (m *QueryGetCrosschainFlagsResponse) Reset() { *m = QueryGetCrossch func (m *QueryGetCrosschainFlagsResponse) String() string { return proto.CompactTextString(m) } func (*QueryGetCrosschainFlagsResponse) ProtoMessage() {} func (*QueryGetCrosschainFlagsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{38} + return fileDescriptor_25b2aa420449a0c0, []int{37} } func (m *QueryGetCrosschainFlagsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1811,7 +1759,7 @@ func (m *QueryGetKeygenRequest) Reset() { *m = QueryGetKeygenRequest{} } func (m *QueryGetKeygenRequest) String() string { return proto.CompactTextString(m) } func (*QueryGetKeygenRequest) ProtoMessage() {} func (*QueryGetKeygenRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{39} + return fileDescriptor_25b2aa420449a0c0, []int{38} } func (m *QueryGetKeygenRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1848,7 +1796,7 @@ func (m *QueryGetKeygenResponse) Reset() { *m = QueryGetKeygenResponse{} func (m *QueryGetKeygenResponse) String() string { return proto.CompactTextString(m) } func (*QueryGetKeygenResponse) ProtoMessage() {} func (*QueryGetKeygenResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{40} + return fileDescriptor_25b2aa420449a0c0, []int{39} } func (m *QueryGetKeygenResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1891,7 +1839,7 @@ func (m *QueryShowObserverCountRequest) Reset() { *m = QueryShowObserver func (m *QueryShowObserverCountRequest) String() string { return proto.CompactTextString(m) } func (*QueryShowObserverCountRequest) ProtoMessage() {} func (*QueryShowObserverCountRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{41} + return fileDescriptor_25b2aa420449a0c0, []int{40} } func (m *QueryShowObserverCountRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1928,7 +1876,7 @@ func (m *QueryShowObserverCountResponse) Reset() { *m = QueryShowObserve func (m *QueryShowObserverCountResponse) String() string { return proto.CompactTextString(m) } func (*QueryShowObserverCountResponse) ProtoMessage() {} func (*QueryShowObserverCountResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{42} + return fileDescriptor_25b2aa420449a0c0, []int{41} } func (m *QueryShowObserverCountResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1972,7 +1920,7 @@ func (m *QueryBlameByIdentifierRequest) Reset() { *m = QueryBlameByIdent func (m *QueryBlameByIdentifierRequest) String() string { return proto.CompactTextString(m) } func (*QueryBlameByIdentifierRequest) ProtoMessage() {} func (*QueryBlameByIdentifierRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{43} + return fileDescriptor_25b2aa420449a0c0, []int{42} } func (m *QueryBlameByIdentifierRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2016,7 +1964,7 @@ func (m *QueryBlameByIdentifierResponse) Reset() { *m = QueryBlameByIden func (m *QueryBlameByIdentifierResponse) String() string { return proto.CompactTextString(m) } func (*QueryBlameByIdentifierResponse) ProtoMessage() {} func (*QueryBlameByIdentifierResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{44} + return fileDescriptor_25b2aa420449a0c0, []int{43} } func (m *QueryBlameByIdentifierResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2060,7 +2008,7 @@ func (m *QueryAllBlameRecordsRequest) Reset() { *m = QueryAllBlameRecord func (m *QueryAllBlameRecordsRequest) String() string { return proto.CompactTextString(m) } func (*QueryAllBlameRecordsRequest) ProtoMessage() {} func (*QueryAllBlameRecordsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{45} + return fileDescriptor_25b2aa420449a0c0, []int{44} } func (m *QueryAllBlameRecordsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2105,7 +2053,7 @@ func (m *QueryAllBlameRecordsResponse) Reset() { *m = QueryAllBlameRecor func (m *QueryAllBlameRecordsResponse) String() string { return proto.CompactTextString(m) } func (*QueryAllBlameRecordsResponse) ProtoMessage() {} func (*QueryAllBlameRecordsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{46} + return fileDescriptor_25b2aa420449a0c0, []int{45} } func (m *QueryAllBlameRecordsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2157,7 +2105,7 @@ func (m *QueryBlameByChainAndNonceRequest) Reset() { *m = QueryBlameByCh func (m *QueryBlameByChainAndNonceRequest) String() string { return proto.CompactTextString(m) } func (*QueryBlameByChainAndNonceRequest) ProtoMessage() {} func (*QueryBlameByChainAndNonceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{47} + return fileDescriptor_25b2aa420449a0c0, []int{46} } func (m *QueryBlameByChainAndNonceRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2208,7 +2156,7 @@ func (m *QueryBlameByChainAndNonceResponse) Reset() { *m = QueryBlameByC func (m *QueryBlameByChainAndNonceResponse) String() string { return proto.CompactTextString(m) } func (*QueryBlameByChainAndNonceResponse) ProtoMessage() {} func (*QueryBlameByChainAndNonceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{48} + return fileDescriptor_25b2aa420449a0c0, []int{47} } func (m *QueryBlameByChainAndNonceResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2268,7 +2216,6 @@ func init() { proto.RegisterType((*QueryHasVotedRequest)(nil), "zetachain.zetacore.observer.QueryHasVotedRequest") proto.RegisterType((*QueryHasVotedResponse)(nil), "zetachain.zetacore.observer.QueryHasVotedResponse") proto.RegisterType((*QueryBallotByIdentifierRequest)(nil), "zetachain.zetacore.observer.QueryBallotByIdentifierRequest") - proto.RegisterType((*VoterList)(nil), "zetachain.zetacore.observer.VoterList") proto.RegisterType((*QueryBallotByIdentifierResponse)(nil), "zetachain.zetacore.observer.QueryBallotByIdentifierResponse") proto.RegisterType((*QueryObserverSet)(nil), "zetachain.zetacore.observer.QueryObserverSet") proto.RegisterType((*QueryObserverSetResponse)(nil), "zetachain.zetacore.observer.QueryObserverSetResponse") @@ -2301,151 +2248,150 @@ func init() { } var fileDescriptor_25b2aa420449a0c0 = []byte{ - // 2300 bytes of a gzipped FileDescriptorProto + // 2274 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x5a, 0xcf, 0x6f, 0x1b, 0xc7, 0x15, 0xf6, 0x4a, 0x89, 0x22, 0x8d, 0x6c, 0xfd, 0x18, 0xcb, 0xb6, 0x42, 0x3b, 0xb2, 0xbc, 0x92, - 0x63, 0x59, 0x96, 0xb8, 0xb6, 0xec, 0xd4, 0xbf, 0xe2, 0xd8, 0xa2, 0x6b, 0x49, 0x76, 0x12, 0xdb, + 0x63, 0x59, 0x96, 0xb8, 0xb6, 0xec, 0xd4, 0xbf, 0xe2, 0xda, 0xa2, 0x63, 0x49, 0x76, 0x12, 0xdb, 0x21, 0xdd, 0x06, 0x30, 0xda, 0xb2, 0x4b, 0xee, 0x90, 0xdc, 0x7a, 0xb5, 0xc3, 0xec, 0x8c, 0x9c, 0x30, 0xaa, 0x80, 0xa2, 0xb7, 0xe6, 0x50, 0x14, 0x28, 0xd0, 0xde, 0x8a, 0x02, 0x45, 0x8f, 0x05, - 0x8a, 0x00, 0x41, 0x0b, 0x14, 0x3d, 0xe4, 0xd4, 0x1c, 0x7a, 0x48, 0xd1, 0xa2, 0xe8, 0xa9, 0x35, + 0x8a, 0x00, 0x01, 0x0a, 0x14, 0x39, 0xe4, 0xd4, 0x1c, 0x7a, 0x48, 0xd1, 0xa2, 0xe8, 0xa9, 0x35, 0xec, 0xfe, 0x21, 0xc5, 0xce, 0xbc, 0x25, 0x77, 0x97, 0xbb, 0xcb, 0x21, 0xad, 0x9e, 0xc8, 0x9d, - 0x99, 0xf7, 0xe6, 0xfb, 0xde, 0xce, 0xbc, 0xf9, 0x66, 0x66, 0xd1, 0x99, 0x4f, 0x09, 0x37, 0xab, + 0x9d, 0xf7, 0xe6, 0xfb, 0xde, 0xcc, 0xbc, 0xf9, 0x66, 0x66, 0xd1, 0x99, 0x4f, 0x09, 0x37, 0xab, 0x0d, 0xd3, 0x76, 0x0d, 0xf1, 0x8f, 0x7a, 0xc4, 0xa0, 0x15, 0x46, 0xbc, 0xa7, 0xc4, 0x33, 0x3e, - 0xda, 0x21, 0x5e, 0x2b, 0xdf, 0xf4, 0x28, 0xa7, 0xf8, 0x78, 0xbb, 0x61, 0x3e, 0x68, 0x98, 0x0f, - 0x1a, 0xe6, 0x96, 0xab, 0x94, 0x6d, 0x53, 0x66, 0x54, 0x4c, 0x46, 0xa4, 0x95, 0xf1, 0xf4, 0x42, + 0xda, 0x21, 0x5e, 0x2b, 0xdf, 0xf4, 0x28, 0xa7, 0xf8, 0x78, 0xbb, 0x62, 0x3e, 0xa8, 0x98, 0x0f, + 0x2a, 0xe6, 0x96, 0xab, 0x94, 0x6d, 0x53, 0x66, 0x54, 0x4c, 0x46, 0xa4, 0x95, 0xf1, 0xf4, 0x42, 0x85, 0x70, 0xf3, 0x82, 0xd1, 0x34, 0xeb, 0xb6, 0x6b, 0x72, 0x9b, 0xba, 0xd2, 0x51, 0x6e, 0xa6, 0x4e, 0xeb, 0x54, 0xfc, 0x35, 0xfc, 0x7f, 0x50, 0x7a, 0xa2, 0x4e, 0x69, 0xdd, 0x21, 0x86, 0xd9, - 0xb4, 0x0d, 0xd3, 0x75, 0x29, 0x17, 0x26, 0x0c, 0x6a, 0x97, 0xb2, 0x50, 0x56, 0x4c, 0xc7, 0xa1, - 0x1c, 0x5a, 0x66, 0xf2, 0xa9, 0x38, 0xe6, 0x36, 0x81, 0x86, 0xf9, 0xac, 0x86, 0xa2, 0xbc, 0xec, - 0x52, 0xb7, 0x4a, 0x02, 0x08, 0x6b, 0x99, 0xed, 0x3d, 0xca, 0x98, 0x34, 0xaa, 0x39, 0x66, 0x5d, - 0x09, 0xf6, 0x13, 0xd2, 0xaa, 0x13, 0x57, 0x05, 0x8d, 0x4b, 0x2d, 0x52, 0x36, 0xab, 0x55, 0xba, - 0xe3, 0x06, 0x34, 0x97, 0xb3, 0xda, 0x07, 0x7f, 0x54, 0x50, 0x34, 0x4d, 0xcf, 0xdc, 0x0e, 0xf0, - 0x9e, 0xcf, 0x6c, 0x49, 0x5c, 0xcb, 0x76, 0xeb, 0xd1, 0xa8, 0x9c, 0xce, 0xb2, 0xe0, 0x8c, 0x65, - 0xc0, 0x6d, 0x3e, 0xa9, 0xcb, 0x38, 0x33, 0xf8, 0xe9, 0xd1, 0xb6, 0xe9, 0x51, 0x5a, 0x63, 0xf0, - 0x03, 0x6d, 0x2f, 0xf5, 0xe8, 0xbe, 0x5c, 0xdb, 0x71, 0x2d, 0x56, 0xde, 0xb6, 0xeb, 0x9e, 0xc9, - 0x29, 0x04, 0x44, 0x3f, 0x8d, 0x16, 0x3e, 0xf0, 0xc7, 0xe8, 0x23, 0xc6, 0x36, 0xfc, 0xfa, 0xf7, - 0xa1, 0xfa, 0xae, 0x5b, 0xa3, 0xeb, 0x8e, 0x53, 0x24, 0x1f, 0xed, 0x10, 0xc6, 0xf5, 0x9f, 0x6a, - 0x68, 0x31, 0xbb, 0x1d, 0x6b, 0x52, 0x97, 0x11, 0x5c, 0x43, 0x87, 0xbb, 0xfb, 0x62, 0xb3, 0xda, - 0xfc, 0xf0, 0xd2, 0xf8, 0xda, 0xf9, 0x7c, 0xc6, 0xc4, 0xc9, 0x83, 0xeb, 0xb0, 0xe7, 0xc2, 0x2b, - 0x5f, 0xfd, 0xfb, 0xe4, 0x81, 0xe2, 0x34, 0x8f, 0xf5, 0xca, 0xf4, 0x1b, 0x68, 0x3e, 0x15, 0x0f, - 0x80, 0xc6, 0xaf, 0xa3, 0x51, 0x39, 0x0e, 0x6d, 0x6b, 0x56, 0x9b, 0xd7, 0x96, 0x86, 0x8b, 0xaf, - 0x89, 0xe7, 0xbb, 0x96, 0xfe, 0x13, 0x0d, 0x9d, 0xca, 0xb0, 0x07, 0x32, 0x16, 0xc2, 0xdd, 0x64, - 0x84, 0xab, 0xc1, 0xb9, 0x4c, 0xc5, 0xb9, 0xe8, 0x97, 0x51, 0x4e, 0x40, 0xd9, 0x24, 0xfc, 0xb6, - 0xef, 0xee, 0xbe, 0x18, 0x54, 0x0a, 0x24, 0x28, 0x3a, 0x9e, 0x68, 0x08, 0xe8, 0x1f, 0xa2, 0xf1, - 0x50, 0x31, 0xc0, 0x5e, 0xca, 0x84, 0x1d, 0x6a, 0x0f, 0x70, 0xc3, 0x2e, 0x74, 0x0b, 0x90, 0xae, - 0x3b, 0x4e, 0x02, 0xd2, 0x0d, 0x84, 0x3a, 0x09, 0x0e, 0xba, 0x7b, 0x33, 0x2f, 0xb3, 0x61, 0xde, - 0xcf, 0x86, 0x79, 0x99, 0x43, 0x21, 0x1b, 0xe6, 0x1f, 0x9a, 0x75, 0x02, 0xb6, 0xc5, 0x90, 0xa5, - 0xfe, 0x47, 0x0d, 0x78, 0xc5, 0xbb, 0x49, 0xe3, 0x35, 0xfc, 0x92, 0xbc, 0xf0, 0x66, 0x04, 0xf9, - 0x90, 0x40, 0x7e, 0xa6, 0x27, 0x72, 0x09, 0x27, 0x02, 0xbd, 0x86, 0x4e, 0x04, 0xc8, 0x1f, 0xca, - 0x14, 0xf1, 0xff, 0x09, 0xd1, 0x97, 0x1a, 0x7a, 0x23, 0xa5, 0x23, 0x08, 0xd2, 0x87, 0x68, 0x22, - 0x9a, 0xa4, 0x20, 0x4e, 0xcb, 0x99, 0x71, 0x8a, 0xf8, 0x82, 0x48, 0x1d, 0x6a, 0x86, 0x0b, 0xf7, - 0x2f, 0x56, 0xc1, 0x0c, 0x8e, 0xf6, 0xd9, 0x12, 0xef, 0x45, 0x61, 0xf0, 0xff, 0x10, 0x26, 0x70, - 0xb2, 0x79, 0x46, 0x14, 0xb4, 0x7d, 0x88, 0x82, 0x3e, 0x83, 0x70, 0x30, 0xf5, 0x1e, 0x95, 0x4a, - 0x41, 0x96, 0x7c, 0x80, 0x0e, 0x47, 0x4a, 0x01, 0xc5, 0x15, 0x34, 0xfc, 0xa8, 0x54, 0x82, 0xae, - 0xe7, 0xb3, 0xf3, 0x46, 0xa9, 0x04, 0x1d, 0xfa, 0x26, 0xfa, 0x1d, 0xf4, 0x7a, 0xdb, 0x21, 0x63, - 0xeb, 0x96, 0xe5, 0x11, 0xd6, 0x1e, 0x4c, 0x4b, 0x68, 0xaa, 0x62, 0xf3, 0x2a, 0xb5, 0xdd, 0x72, - 0x3b, 0x48, 0x43, 0x22, 0x48, 0x13, 0x50, 0x7e, 0x1b, 0x62, 0x75, 0xab, 0x93, 0x61, 0xc2, 0x6e, - 0x00, 0xde, 0x14, 0x1a, 0x26, 0xbc, 0x21, 0xe0, 0x8d, 0x15, 0xfd, 0xbf, 0x7e, 0x49, 0x85, 0x57, - 0x85, 0xb3, 0xb1, 0xa2, 0xff, 0x57, 0xff, 0x4c, 0x43, 0xcb, 0xdd, 0x2e, 0x0a, 0xad, 0x0d, 0xdb, - 0x35, 0x1d, 0xfb, 0x53, 0x62, 0x6d, 0x11, 0xbb, 0xde, 0xe0, 0x01, 0xb4, 0x35, 0x74, 0xa4, 0x16, - 0xd4, 0x94, 0x7d, 0x96, 0xe5, 0x86, 0xa8, 0x87, 0x97, 0x78, 0xb8, 0x5d, 0xf9, 0x98, 0x70, 0x53, - 0x9a, 0xf6, 0x41, 0xe7, 0x03, 0x74, 0x4e, 0x09, 0x4b, 0x1f, 0xfc, 0xbe, 0x8f, 0x8e, 0x06, 0xcb, - 0xc1, 0x96, 0xcd, 0x38, 0xf5, 0x5a, 0xfb, 0x3d, 0x65, 0x7f, 0xab, 0xa1, 0x63, 0x5d, 0x5d, 0x00, - 0xc2, 0x75, 0x34, 0xea, 0xaf, 0x33, 0x8e, 0xcd, 0x38, 0x4c, 0x53, 0xd5, 0x51, 0xf2, 0x1a, 0x67, - 0xec, 0x3d, 0x9b, 0xf1, 0xfd, 0x9b, 0x96, 0x0d, 0x34, 0x23, 0x60, 0x6e, 0x99, 0xec, 0xdb, 0x94, - 0x13, 0x2b, 0x88, 0xc3, 0x39, 0x34, 0x2d, 0xc5, 0x65, 0xd9, 0xb6, 0x88, 0xcb, 0xed, 0x9a, 0x4d, - 0x3c, 0x88, 0xe9, 0x94, 0xac, 0xb8, 0xdb, 0x2e, 0xc7, 0x0b, 0xe8, 0xd0, 0x53, 0xca, 0x89, 0x57, - 0x36, 0xe5, 0xcb, 0x81, 0x50, 0x1f, 0x14, 0x85, 0xf0, 0xc2, 0xf4, 0x4b, 0xe8, 0x48, 0xac, 0x27, - 0x08, 0xc7, 0x71, 0x34, 0xd6, 0x30, 0x59, 0xd9, 0x6f, 0x2c, 0xa7, 0xfd, 0x68, 0x71, 0xb4, 0x01, - 0x8d, 0xf4, 0xf7, 0xd1, 0x9c, 0xb0, 0x2a, 0x88, 0x3e, 0x0b, 0xad, 0x4e, 0xaf, 0x83, 0x20, 0xd5, - 0x39, 0x1a, 0xf3, 0xfd, 0x7a, 0x22, 0x88, 0x5d, 0xb0, 0xb5, 0x6e, 0xd8, 0xb8, 0x80, 0xc6, 0xfc, - 0xe7, 0x32, 0x6f, 0x35, 0x89, 0xe0, 0x35, 0xb1, 0x76, 0x3a, 0xf3, 0x6d, 0xf9, 0xfe, 0x1f, 0xb5, - 0x9a, 0xa4, 0x38, 0xfa, 0x14, 0xfe, 0xe9, 0x7f, 0x18, 0x42, 0x27, 0x53, 0x59, 0x40, 0x14, 0xfa, - 0x0a, 0xf8, 0x3b, 0x68, 0x44, 0x80, 0xf4, 0x23, 0x3d, 0x2c, 0x46, 0x68, 0x2f, 0x44, 0x82, 0x71, - 0x11, 0xac, 0xf0, 0x87, 0x68, 0x4a, 0xd6, 0x8a, 0x41, 0x20, 0xb9, 0x0d, 0x0b, 0x6e, 0x2b, 0x99, - 0x9e, 0x1e, 0x74, 0x8c, 0x04, 0xc5, 0x49, 0x1a, 0x2d, 0xc0, 0xf7, 0xd1, 0x21, 0x60, 0xc1, 0xb8, - 0xc9, 0x77, 0xd8, 0xec, 0x2b, 0xc2, 0xeb, 0xd9, 0x4c, 0xaf, 0x32, 0x2a, 0x25, 0x61, 0x50, 0x3c, - 0x58, 0x09, 0x3d, 0xe9, 0x18, 0x4d, 0x89, 0xc0, 0x3d, 0x80, 0xb6, 0x25, 0xc2, 0xf5, 0x2b, 0x68, - 0x36, 0x5e, 0xd6, 0x8e, 0xe2, 0x09, 0x34, 0x16, 0xb8, 0x95, 0x4b, 0xe0, 0x58, 0xb1, 0x53, 0xa0, - 0x1f, 0x85, 0xc1, 0x5e, 0xda, 0x69, 0x36, 0xa9, 0xc7, 0x89, 0x25, 0x52, 0x0c, 0xd3, 0x2b, 0xb0, - 0x8e, 0xc7, 0xca, 0xdb, 0x5e, 0x0b, 0x68, 0x44, 0xea, 0x74, 0x98, 0xae, 0x8b, 0x49, 0x74, 0x9a, - 0x4f, 0xea, 0x79, 0x50, 0xf3, 0xc2, 0x1c, 0xa6, 0x2c, 0x58, 0xea, 0x37, 0x91, 0x1e, 0x51, 0x6f, - 0x0f, 0xc5, 0xee, 0x63, 0x83, 0x7a, 0xaa, 0x2b, 0xa0, 0x07, 0xd2, 0x3d, 0xcd, 0x01, 0x60, 0x7d, - 0x17, 0x1d, 0x94, 0x1e, 0xe4, 0xf6, 0x46, 0x5d, 0x07, 0x4a, 0x7f, 0xc5, 0xf1, 0x6a, 0xe7, 0x41, - 0x3f, 0x11, 0xd3, 0xaa, 0xd0, 0x06, 0xd6, 0x3f, 0x37, 0x26, 0x48, 0x83, 0x5a, 0x40, 0xf2, 0x20, - 0x11, 0xc9, 0x8a, 0x2a, 0x12, 0x31, 0x60, 0x23, 0x68, 0xd6, 0x3a, 0x68, 0xee, 0x53, 0x8b, 0xac, - 0xcb, 0x6d, 0x61, 0x10, 0xba, 0x19, 0xf4, 0xaa, 0xed, 0x5a, 0xe4, 0x13, 0x98, 0x34, 0xf2, 0x41, - 0xff, 0x41, 0x07, 0x63, 0xc4, 0xa6, 0x13, 0xad, 0xf0, 0x16, 0x53, 0x29, 0x5a, 0x61, 0x3f, 0xe3, - 0x6e, 0xe7, 0x21, 0xac, 0x97, 0x13, 0xf0, 0xed, 0xd7, 0xca, 0xf2, 0x79, 0x48, 0x2f, 0x27, 0x51, - 0xba, 0x87, 0xc6, 0x43, 0xc5, 0x4a, 0x7a, 0x39, 0xc2, 0x28, 0xf4, 0xb0, 0x7f, 0xcb, 0xcc, 0x3c, - 0xa4, 0x71, 0x7f, 0xa8, 0xb4, 0x0f, 0x0c, 0x36, 0x1c, 0xb3, 0xde, 0x1e, 0x4c, 0x3f, 0xd2, 0x20, - 0x47, 0x26, 0x35, 0x01, 0x6a, 0xdf, 0x45, 0x53, 0xf1, 0xe3, 0x06, 0xb5, 0x51, 0x15, 0xf5, 0x07, - 0x33, 0x73, 0xb2, 0x1a, 0x2d, 0xd6, 0x8f, 0xc1, 0x0a, 0xb5, 0x49, 0xf8, 0xbb, 0xe2, 0x84, 0x22, - 0xc0, 0xf6, 0x2d, 0x90, 0x0b, 0xa1, 0x0a, 0x40, 0x74, 0x1d, 0x8d, 0xc8, 0xc3, 0x0c, 0xc0, 0xb1, - 0x90, 0x89, 0x03, 0x8c, 0xc1, 0x44, 0x3f, 0x09, 0xaa, 0xbe, 0xd4, 0xa0, 0x1f, 0x07, 0xc9, 0xec, - 0x76, 0x68, 0xc8, 0xf8, 0x31, 0x99, 0x4b, 0x6b, 0x01, 0x00, 0xbe, 0x87, 0x0e, 0x3b, 0x26, 0xe3, - 0xe5, 0xa0, 0x8f, 0x72, 0x78, 0x1c, 0xe7, 0x33, 0xd1, 0xbc, 0x67, 0x32, 0x1e, 0x75, 0x3a, 0xed, - 0xc4, 0x8b, 0xf4, 0x7b, 0x80, 0xb1, 0xe0, 0x98, 0xdb, 0x24, 0x69, 0xf9, 0x3d, 0x8b, 0xa6, 0xc4, - 0xd9, 0x52, 0xf7, 0xb2, 0x35, 0x29, 0xca, 0x43, 0x8b, 0x6f, 0x35, 0x58, 0xcb, 0xbb, 0x7d, 0xb5, - 0x95, 0x11, 0x02, 0x67, 0x6e, 0x8d, 0x02, 0x09, 0x3d, 0x7b, 0xed, 0xf0, 0x9b, 0x17, 0xc7, 0x64, - 0x57, 0x6e, 0x8d, 0xea, 0xa4, 0x33, 0x3b, 0x64, 0x1d, 0xa9, 0x52, 0xcf, 0xda, 0xf7, 0x2d, 0xd9, - 0xef, 0xb5, 0xce, 0xde, 0x2f, 0xda, 0x0f, 0x50, 0xd9, 0x8c, 0x51, 0x19, 0x56, 0xa3, 0x02, 0x63, - 0xb3, 0x43, 0x68, 0xff, 0xe6, 0x60, 0x09, 0x76, 0x60, 0x10, 0x7e, 0x91, 0x6a, 0xd7, 0x5d, 0x4b, - 0x6c, 0x71, 0x7a, 0xaf, 0x3f, 0x7e, 0x7e, 0x15, 0x9b, 0x2a, 0x50, 0xe9, 0xf2, 0x41, 0xaf, 0xc1, - 0xbe, 0x2c, 0xd9, 0x69, 0xca, 0x6b, 0x1d, 0xee, 0xfb, 0xb5, 0xae, 0xfd, 0x66, 0x11, 0xbd, 0x2a, - 0x3a, 0xc2, 0x7f, 0xd6, 0xd0, 0x68, 0xa0, 0x21, 0xf1, 0x85, 0x4c, 0x2f, 0x49, 0xca, 0x36, 0xb7, - 0xd6, 0x8f, 0x89, 0x24, 0xa0, 0xdf, 0xfb, 0xf1, 0xdf, 0xff, 0xfb, 0xf3, 0xa1, 0x6f, 0xe2, 0x82, - 0x38, 0x6b, 0x5b, 0x95, 0xc7, 0x6e, 0xed, 0xd3, 0xb6, 0xb6, 0x7a, 0x35, 0x76, 0xbb, 0x24, 0xdc, - 0x9e, 0xb1, 0x1b, 0xd1, 0x98, 0x7b, 0xf8, 0x9f, 0x1a, 0xc2, 0xdd, 0x3a, 0x10, 0x5f, 0xef, 0x0d, - 0x2b, 0x55, 0x03, 0xe7, 0xde, 0x1e, 0xcc, 0x18, 0xd8, 0xdd, 0x11, 0xec, 0x6e, 0xe2, 0x1b, 0x89, - 0xec, 0x80, 0x52, 0xa5, 0x15, 0x62, 0x95, 0x44, 0x14, 0xff, 0x4a, 0x43, 0xe3, 0x21, 0x4d, 0x86, - 0x57, 0x7b, 0x83, 0x0a, 0x35, 0xcf, 0xbd, 0xd5, 0x57, 0xf3, 0x36, 0xf8, 0xb3, 0x02, 0xfc, 0x02, - 0x3e, 0x95, 0x08, 0xbe, 0x9d, 0x16, 0x19, 0xe1, 0xf8, 0x77, 0x1a, 0x9a, 0x8c, 0x49, 0x3c, 0x95, - 0x01, 0x14, 0x33, 0xc9, 0x5d, 0xed, 0xdb, 0xa4, 0x0d, 0x76, 0x45, 0x80, 0x7d, 0x13, 0x2f, 0x26, - 0x82, 0x65, 0x31, 0x6c, 0xff, 0xd1, 0xd0, 0xd1, 0x64, 0xb5, 0x87, 0x6f, 0xf6, 0xc6, 0x90, 0x29, - 0x34, 0x73, 0xb7, 0x06, 0x77, 0x00, 0x5c, 0x0a, 0x82, 0xcb, 0xdb, 0xf8, 0x5a, 0x22, 0x97, 0x3a, - 0xe1, 0xe5, 0xb0, 0xfa, 0x2b, 0xd7, 0xa8, 0x27, 0x0b, 0x8c, 0xdd, 0x20, 0xc3, 0xec, 0xe1, 0xcf, - 0x35, 0x34, 0x11, 0xed, 0x06, 0x5f, 0xee, 0x17, 0x58, 0xc0, 0xe8, 0x4a, 0xff, 0x86, 0xc0, 0x64, - 0x55, 0x30, 0x39, 0x83, 0x4f, 0x2b, 0x31, 0xf1, 0x41, 0x47, 0x44, 0x92, 0x1a, 0xe2, 0x6e, 0x45, - 0xa8, 0x88, 0x38, 0x41, 0xe3, 0xe9, 0xe7, 0x05, 0xe2, 0x65, 0xbc, 0x94, 0x88, 0x38, 0xa4, 0x49, - 0x8d, 0x5d, 0x21, 0x83, 0xf7, 0xfc, 0xb1, 0x3f, 0x11, 0xf2, 0xb4, 0xee, 0x38, 0x2a, 0xb8, 0x13, - 0x95, 0xac, 0x0a, 0xee, 0x64, 0x6d, 0xaa, 0x2f, 0x09, 0xdc, 0x3a, 0x9e, 0xef, 0x85, 0x1b, 0xff, - 0x49, 0x43, 0x93, 0x31, 0xd9, 0xa6, 0x92, 0x22, 0x53, 0xf5, 0xa5, 0x4a, 0x8a, 0x4c, 0x57, 0x9e, - 0x3d, 0x86, 0x48, 0x5c, 0x94, 0xe2, 0x5f, 0x68, 0x68, 0x44, 0x8a, 0x3d, 0xbc, 0xa6, 0xd4, 0x6f, - 0x44, 0x6f, 0xe6, 0x2e, 0xf6, 0x65, 0x03, 0x10, 0x17, 0x04, 0xc4, 0x37, 0xf0, 0xf1, 0x44, 0x88, - 0x52, 0x72, 0xe2, 0xbf, 0x68, 0x68, 0xba, 0x4b, 0x4c, 0xe2, 0x6b, 0x0a, 0x19, 0x2d, 0x45, 0xa3, - 0xe6, 0xae, 0x0f, 0x64, 0x0b, 0x98, 0xaf, 0x0a, 0xcc, 0x17, 0xf1, 0x85, 0x30, 0xe6, 0xee, 0xeb, - 0x2c, 0xd6, 0xa0, 0x1f, 0xc7, 0x14, 0x2e, 0xfe, 0x9b, 0x86, 0xa6, 0xbb, 0x84, 0xa4, 0x0a, 0x93, - 0x34, 0x25, 0xab, 0xc2, 0x24, 0x55, 0xb9, 0xea, 0xb7, 0x05, 0x93, 0x1b, 0xf8, 0x7a, 0xf2, 0x1a, - 0x2a, 0xd4, 0x4f, 0x7c, 0x09, 0x8d, 0xc9, 0xe6, 0x3d, 0x5f, 0xda, 0xe0, 0x4d, 0xc2, 0x63, 0x92, - 0x12, 0xab, 0xcd, 0xb7, 0x04, 0xb5, 0xab, 0xb2, 0x54, 0xa5, 0xe8, 0x57, 0x7d, 0x4d, 0x10, 0x5a, - 0xc1, 0xcb, 0xa9, 0x49, 0xd1, 0x74, 0x9c, 0xb2, 0xe4, 0xe0, 0x01, 0xd0, 0x67, 0x1a, 0x3a, 0x22, - 0x9c, 0xb1, 0x98, 0x12, 0xc4, 0x37, 0x94, 0x63, 0x9b, 0x24, 0x4b, 0x73, 0xef, 0x0c, 0x6a, 0x0e, - 0x64, 0xb6, 0x04, 0x99, 0x02, 0xbe, 0x95, 0xfd, 0x76, 0xe4, 0x14, 0x36, 0x5d, 0x4b, 0x5e, 0x1f, - 0x84, 0x56, 0x2a, 0x63, 0x57, 0x94, 0xec, 0xe1, 0x2f, 0x35, 0x74, 0x28, 0x72, 0x10, 0x8d, 0xbf, - 0xa1, 0x34, 0x59, 0xbb, 0xce, 0xf3, 0x73, 0x97, 0xfb, 0xb6, 0x03, 0x32, 0x37, 0x05, 0x99, 0xab, - 0xf8, 0x72, 0xea, 0x9b, 0xe1, 0x8c, 0x05, 0x7a, 0xd3, 0xd8, 0x8d, 0x9f, 0xb2, 0xef, 0xe1, 0x5f, - 0x0e, 0xa1, 0xb9, 0xec, 0xc3, 0x74, 0xbc, 0xd9, 0x27, 0xb8, 0xb4, 0xab, 0x81, 0xdc, 0xd6, 0xcb, - 0x3b, 0x02, 0xda, 0x15, 0x41, 0xfb, 0x3b, 0xf8, 0xb1, 0x0a, 0xed, 0x72, 0x43, 0x9c, 0xb9, 0xdb, - 0x55, 0xd3, 0x31, 0x76, 0x13, 0xef, 0x26, 0xf6, 0x92, 0x22, 0xf3, 0x99, 0x26, 0xee, 0x6e, 0xb0, - 0xa1, 0x86, 0xba, 0x7d, 0x15, 0x94, 0x3b, 0xaf, 0x6e, 0x00, 0x74, 0xe6, 0x05, 0x9d, 0x1c, 0x9e, - 0x4d, 0xa4, 0xe3, 0x83, 0xf8, 0xb5, 0x86, 0x50, 0xe7, 0xf6, 0x00, 0x2b, 0x2c, 0x0a, 0x5d, 0xd7, - 0x19, 0xb9, 0x4b, 0xfd, 0x19, 0x01, 0xb6, 0x33, 0x02, 0xdb, 0x29, 0x7c, 0x32, 0x11, 0x1b, 0xef, - 0x60, 0xfa, 0x42, 0x43, 0x53, 0x91, 0xeb, 0x33, 0x5f, 0x57, 0xa8, 0x25, 0x9d, 0xa4, 0x0b, 0xd3, - 0xdc, 0xb5, 0x41, 0x4c, 0x01, 0xf4, 0xb2, 0x00, 0xbd, 0x88, 0xf5, 0x44, 0xd0, 0xd1, 0x5b, 0xcd, - 0xbf, 0x6a, 0x68, 0x26, 0xe9, 0x26, 0x51, 0x25, 0x4f, 0x65, 0x5c, 0x60, 0xaa, 0xe4, 0xa9, 0xac, - 0x0b, 0x4c, 0xfd, 0x2d, 0xc1, 0xc1, 0xc0, 0xab, 0xbd, 0x39, 0x84, 0x65, 0xf4, 0x17, 0x5a, 0xe4, - 0x8e, 0xbc, 0x1f, 0x0d, 0x1d, 0x8d, 0xff, 0x95, 0xfe, 0x0d, 0x01, 0xf9, 0x45, 0x81, 0x7c, 0x15, - 0x9f, 0x4b, 0x16, 0x48, 0x1d, 0x8b, 0x30, 0x6e, 0x5f, 0x94, 0x86, 0x9c, 0xa9, 0x8b, 0xd2, 0xc1, - 0xa0, 0x27, 0x7f, 0x60, 0xd0, 0x43, 0x94, 0x86, 0xa0, 0xfb, 0xea, 0x69, 0x26, 0xe9, 0x0b, 0x12, - 0x95, 0x61, 0x93, 0xf1, 0xe5, 0x8a, 0xca, 0xb0, 0xc9, 0xfa, 0x70, 0xa5, 0xc7, 0x76, 0xa0, 0x2e, - 0xf2, 0x6b, 0xc4, 0x1a, 0xff, 0x43, 0x43, 0xc7, 0x52, 0xbe, 0xed, 0xc1, 0xb7, 0x06, 0x43, 0xd3, - 0xf9, 0x7c, 0x28, 0xb7, 0xfe, 0x12, 0x1e, 0x80, 0xd2, 0x25, 0x41, 0x29, 0x8f, 0x57, 0xd2, 0x28, - 0xad, 0x3b, 0x4e, 0xdc, 0x07, 0x2b, 0xdc, 0xf9, 0xea, 0xf9, 0x9c, 0xf6, 0xf5, 0xf3, 0x39, 0xed, - 0xd9, 0xf3, 0x39, 0xed, 0x67, 0x2f, 0xe6, 0x0e, 0x7c, 0xfd, 0x62, 0xee, 0xc0, 0xbf, 0x5e, 0xcc, - 0x1d, 0x78, 0x7c, 0xae, 0x6e, 0xf3, 0xc6, 0x4e, 0x25, 0x5f, 0xa5, 0xdb, 0x61, 0x8f, 0xfe, 0x96, - 0xc3, 0xf8, 0x24, 0x94, 0xdb, 0x5a, 0x4d, 0xc2, 0x2a, 0x23, 0xe2, 0x63, 0xa9, 0x8b, 0xff, 0x0b, - 0x00, 0x00, 0xff, 0xff, 0x77, 0x67, 0x2d, 0x08, 0x22, 0x28, 0x00, 0x00, + 0xb4, 0x0d, 0xd3, 0x75, 0x29, 0x17, 0x26, 0x0c, 0xde, 0x2e, 0x65, 0xa1, 0xac, 0x98, 0x8e, 0x43, + 0x39, 0xd4, 0xcc, 0xe4, 0x53, 0x71, 0xcc, 0x6d, 0x02, 0x15, 0xf3, 0x59, 0x15, 0x45, 0x79, 0xd9, + 0xa5, 0x6e, 0x95, 0x04, 0x10, 0xd6, 0x32, 0xeb, 0x7b, 0x94, 0x31, 0x69, 0x54, 0x73, 0xcc, 0xba, + 0x12, 0xec, 0x27, 0xa4, 0x55, 0x27, 0xae, 0x0a, 0x1a, 0x97, 0x5a, 0xa4, 0x6c, 0x56, 0xab, 0x74, + 0xc7, 0x0d, 0x68, 0x2e, 0x67, 0xd5, 0x0f, 0xfe, 0xa8, 0xa0, 0x68, 0x9a, 0x9e, 0xb9, 0x1d, 0xe0, + 0x3d, 0x9f, 0x59, 0x93, 0xb8, 0x96, 0xed, 0xd6, 0xa3, 0x51, 0x39, 0x9d, 0x65, 0xc1, 0x19, 0xcb, + 0x80, 0xdb, 0x7c, 0x52, 0x97, 0x71, 0x66, 0xf0, 0xd3, 0xa3, 0x6e, 0xd3, 0xa3, 0xb4, 0xc6, 0xe0, + 0x07, 0xea, 0x5e, 0xea, 0xd1, 0x7c, 0xb9, 0xb6, 0xe3, 0x5a, 0xac, 0xbc, 0x6d, 0xd7, 0x3d, 0x93, + 0x53, 0x08, 0x88, 0x7e, 0x1a, 0x2d, 0x7c, 0xe0, 0x8f, 0xd1, 0x47, 0x8c, 0x6d, 0xf8, 0xef, 0xdf, + 0x87, 0xd7, 0x77, 0xdd, 0x1a, 0x5d, 0x77, 0x9c, 0x22, 0xf9, 0x68, 0x87, 0x30, 0xae, 0xff, 0x5c, + 0x43, 0x8b, 0xd9, 0xf5, 0x58, 0x93, 0xba, 0x8c, 0xe0, 0x1a, 0x3a, 0xdc, 0xdd, 0x16, 0x9b, 0xd5, + 0xe6, 0x87, 0x97, 0xc6, 0xd7, 0xce, 0xe7, 0x33, 0x26, 0x4e, 0x1e, 0x5c, 0x87, 0x3d, 0x17, 0x5e, + 0xf9, 0xfa, 0xdf, 0x27, 0x0f, 0x14, 0xa7, 0x79, 0xac, 0x55, 0xa6, 0xdf, 0x40, 0xf3, 0xa9, 0x78, + 0x00, 0x34, 0x7e, 0x1d, 0x8d, 0xca, 0x71, 0x68, 0x5b, 0xb3, 0xda, 0xbc, 0xb6, 0x34, 0x5c, 0x7c, + 0x4d, 0x3c, 0xdf, 0xb5, 0xf4, 0x9f, 0x69, 0xe8, 0x54, 0x86, 0x3d, 0x90, 0xb1, 0x10, 0xee, 0x26, + 0x23, 0x5c, 0x0d, 0xce, 0x65, 0x2a, 0xce, 0x45, 0xbf, 0x8c, 0x72, 0x02, 0xca, 0x26, 0xe1, 0xb7, + 0x7d, 0x77, 0xf7, 0xc5, 0xa0, 0x52, 0x20, 0x41, 0xd1, 0xf1, 0x44, 0x43, 0x40, 0xff, 0x10, 0x8d, + 0x87, 0x8a, 0x01, 0xf6, 0x52, 0x26, 0xec, 0x50, 0x7d, 0x80, 0x1b, 0x76, 0xa1, 0x5b, 0x80, 0x74, + 0xdd, 0x71, 0x12, 0x90, 0x6e, 0x20, 0xd4, 0x49, 0x70, 0xd0, 0xdc, 0x9b, 0x79, 0x99, 0x0d, 0xf3, + 0x7e, 0x36, 0xcc, 0xcb, 0x1c, 0x0a, 0xd9, 0x30, 0xff, 0xd0, 0xac, 0x13, 0xb0, 0x2d, 0x86, 0x2c, + 0xf5, 0x3f, 0x69, 0xc0, 0x2b, 0xde, 0x4c, 0x1a, 0xaf, 0xe1, 0x97, 0xe4, 0x85, 0x37, 0x23, 0xc8, + 0x87, 0x04, 0xf2, 0x33, 0x3d, 0x91, 0x4b, 0x38, 0x11, 0xe8, 0x35, 0x74, 0x22, 0x40, 0xfe, 0x50, + 0xa6, 0x88, 0xff, 0x4f, 0x88, 0xbe, 0xd2, 0xd0, 0x1b, 0x29, 0x0d, 0x41, 0x90, 0x3e, 0x44, 0x13, + 0xd1, 0x24, 0x05, 0x71, 0x5a, 0xce, 0x8c, 0x53, 0xc4, 0x17, 0x44, 0xea, 0x50, 0x33, 0x5c, 0xb8, + 0x7f, 0xb1, 0x0a, 0x66, 0x70, 0xb4, 0xcd, 0x96, 0xe8, 0x17, 0x85, 0xc1, 0xff, 0x63, 0x98, 0xc0, + 0xc9, 0xe6, 0x19, 0x51, 0xd0, 0xf6, 0x21, 0x0a, 0xfa, 0x0c, 0xc2, 0xc1, 0xd4, 0x7b, 0x54, 0x2a, + 0x05, 0x59, 0xf2, 0x01, 0x3a, 0x1c, 0x29, 0x05, 0x14, 0x57, 0xd0, 0xf0, 0xa3, 0x52, 0x09, 0x9a, + 0x9e, 0xcf, 0xce, 0x1b, 0xa5, 0x12, 0x34, 0xe8, 0x9b, 0xe8, 0x77, 0xd0, 0xeb, 0x6d, 0x87, 0x8c, + 0xad, 0x5b, 0x96, 0x47, 0x58, 0x7b, 0x30, 0x2d, 0xa1, 0xa9, 0x8a, 0xcd, 0xab, 0xd4, 0x76, 0xcb, + 0xed, 0x20, 0x0d, 0x89, 0x20, 0x4d, 0x40, 0xf9, 0x6d, 0x88, 0xd5, 0xad, 0x4e, 0x86, 0x09, 0xbb, + 0x01, 0x78, 0x53, 0x68, 0x98, 0xf0, 0x86, 0x80, 0x37, 0x56, 0xf4, 0xff, 0xfa, 0x25, 0x15, 0x5e, + 0x15, 0xce, 0xc6, 0x8a, 0xfe, 0x5f, 0xfd, 0x33, 0x0d, 0x2d, 0x77, 0xbb, 0x28, 0xb4, 0x36, 0x6c, + 0xd7, 0x74, 0xec, 0x4f, 0x89, 0xb5, 0x45, 0xec, 0x7a, 0x83, 0x07, 0xd0, 0xd6, 0xd0, 0x91, 0x5a, + 0xf0, 0xa6, 0xec, 0xb3, 0x2c, 0x37, 0xc4, 0x7b, 0xe8, 0xc4, 0xc3, 0xed, 0x97, 0x8f, 0x09, 0x37, + 0xa5, 0x69, 0x1f, 0x74, 0x3e, 0x40, 0xe7, 0x94, 0xb0, 0xf4, 0xc1, 0xef, 0x87, 0xe8, 0x68, 0xb0, + 0x1c, 0x6c, 0xd9, 0x8c, 0x53, 0xaf, 0xb5, 0xdf, 0x53, 0xf6, 0xf7, 0x1a, 0x3a, 0xd6, 0xd5, 0x04, + 0x20, 0x5c, 0x47, 0xa3, 0xfe, 0x3a, 0xe3, 0xd8, 0x8c, 0xc3, 0x34, 0x55, 0x1d, 0x25, 0xaf, 0x71, + 0xc6, 0xde, 0xb3, 0x19, 0xdf, 0xbf, 0x69, 0xd9, 0x40, 0x33, 0x02, 0xe6, 0x96, 0xc9, 0xbe, 0x4b, + 0x39, 0xb1, 0x82, 0x38, 0x9c, 0x43, 0xd3, 0x52, 0x5c, 0x96, 0x6d, 0x8b, 0xb8, 0xdc, 0xae, 0xd9, + 0xc4, 0x83, 0x98, 0x4e, 0xc9, 0x17, 0x77, 0xdb, 0xe5, 0x78, 0x01, 0x1d, 0x7a, 0x4a, 0x39, 0xf1, + 0xca, 0xa6, 0xec, 0x1c, 0x08, 0xf5, 0x41, 0x51, 0x08, 0x1d, 0xa6, 0x5f, 0x42, 0x47, 0x62, 0x2d, + 0x41, 0x38, 0x8e, 0xa3, 0xb1, 0x86, 0xc9, 0xca, 0x7e, 0x65, 0x39, 0xed, 0x47, 0x8b, 0xa3, 0x0d, + 0xa8, 0xa4, 0xbf, 0x8f, 0xe6, 0x84, 0x55, 0x41, 0xb4, 0x59, 0x68, 0x75, 0x5a, 0x1d, 0x04, 0xa9, + 0xfe, 0xe5, 0x10, 0x3a, 0x99, 0xea, 0x0f, 0xf0, 0xf4, 0x45, 0xfd, 0x1d, 0x34, 0x22, 0x58, 0xfa, + 0x9c, 0x87, 0xc5, 0x58, 0xc9, 0xea, 0x49, 0x9f, 0x93, 0xe7, 0x77, 0x20, 0xf4, 0x27, 0xd8, 0xe2, + 0x0f, 0xd1, 0x94, 0xac, 0x23, 0x3a, 0xa5, 0xcc, 0x5b, 0x4d, 0x32, 0x3b, 0x3c, 0xaf, 0x2d, 0x4d, + 0xac, 0xad, 0x64, 0xfa, 0x7b, 0xd0, 0x31, 0x7a, 0xd4, 0x6a, 0x92, 0xe2, 0x24, 0x8d, 0x16, 0xe0, + 0xfb, 0xe8, 0x10, 0x70, 0x61, 0xdc, 0xe4, 0x3b, 0x6c, 0xf6, 0x15, 0xe1, 0xf5, 0x6c, 0xa6, 0x57, + 0x19, 0x9b, 0x92, 0x30, 0x28, 0x1e, 0xac, 0x84, 0x9e, 0x74, 0x8c, 0xa6, 0x44, 0xf8, 0x1e, 0x40, + 0xdd, 0x12, 0xe1, 0xfa, 0x15, 0x34, 0x1b, 0x2f, 0x6b, 0xc7, 0xf2, 0x04, 0x1a, 0x0b, 0xdc, 0xca, + 0x25, 0x69, 0xac, 0xd8, 0x29, 0xd0, 0x8f, 0xc2, 0xe0, 0x2b, 0xed, 0x34, 0x9b, 0xd4, 0xe3, 0xc4, + 0x12, 0x53, 0x9e, 0xe9, 0x15, 0x58, 0x57, 0x63, 0xe5, 0x6d, 0xaf, 0x05, 0x34, 0x22, 0x75, 0x33, + 0x4c, 0x9f, 0xc5, 0x24, 0x3a, 0xcd, 0x27, 0xf5, 0x3c, 0xa8, 0x6b, 0x61, 0x1e, 0x84, 0x5c, 0x96, + 0xe9, 0x37, 0x91, 0x1e, 0x51, 0x53, 0x0f, 0xc5, 0x6e, 0x60, 0x83, 0x7a, 0xaa, 0x2b, 0x92, 0x07, + 0x52, 0x3a, 0xcd, 0x01, 0x60, 0x7d, 0x17, 0x1d, 0x94, 0x1e, 0xe4, 0x76, 0x43, 0x5d, 0x97, 0x49, + 0x7f, 0xc5, 0xf1, 0x6a, 0xe7, 0x41, 0x3f, 0x11, 0xd3, 0x8e, 0x50, 0x07, 0xd6, 0x23, 0x37, 0x26, + 0x10, 0x83, 0xb7, 0x80, 0xe4, 0x41, 0x22, 0x92, 0x15, 0x55, 0x24, 0xfe, 0xb0, 0x8d, 0xa2, 0x59, + 0xeb, 0xa0, 0xb9, 0x4f, 0x2d, 0xb2, 0x2e, 0xb7, 0x69, 0x41, 0xe8, 0x66, 0xd0, 0xab, 0xb6, 0x6b, + 0x91, 0x4f, 0x60, 0xea, 0xc8, 0x07, 0xfd, 0x47, 0x1d, 0x8c, 0x11, 0x9b, 0x4e, 0xb4, 0xc2, 0x5b, + 0x3e, 0xa5, 0x68, 0x85, 0xfd, 0x8c, 0xbb, 0x9d, 0x87, 0xb0, 0x7e, 0x4d, 0xc0, 0xb7, 0x5f, 0x99, + 0xfe, 0xf3, 0x90, 0x7e, 0x4d, 0xa2, 0x74, 0x0f, 0x8d, 0x87, 0x8a, 0x95, 0xf4, 0x6b, 0x84, 0x51, + 0xe8, 0x61, 0xff, 0xd2, 0xfe, 0x3c, 0xa4, 0x55, 0x7f, 0xa8, 0xb4, 0x37, 0xf0, 0x1b, 0xfe, 0xfe, + 0x3d, 0x18, 0x4c, 0x3f, 0xd1, 0x20, 0x53, 0x26, 0x55, 0x01, 0x6a, 0xdf, 0x47, 0x53, 0xf1, 0xed, + 0xbf, 0xda, 0xa8, 0x8a, 0xfa, 0x83, 0x99, 0x39, 0x59, 0x8d, 0x16, 0xeb, 0xc7, 0x60, 0xc5, 0xd8, + 0x24, 0xfc, 0x5d, 0x71, 0x62, 0x10, 0x60, 0xfb, 0x0e, 0x2c, 0xdf, 0xa1, 0x17, 0x80, 0xe8, 0x3a, + 0x1a, 0x91, 0x87, 0x0b, 0x80, 0x63, 0x21, 0x13, 0x07, 0x18, 0x83, 0x89, 0x7e, 0x12, 0x54, 0x76, + 0xa9, 0x41, 0x3f, 0x0e, 0x92, 0xd9, 0xed, 0xd0, 0x90, 0xf1, 0x63, 0x32, 0x97, 0x56, 0x03, 0x00, + 0xfc, 0x00, 0x1d, 0x76, 0x4c, 0xc6, 0xcb, 0x41, 0x1b, 0xe5, 0xf0, 0x38, 0xce, 0x67, 0xa2, 0x79, + 0xcf, 0x64, 0x3c, 0xea, 0x74, 0xda, 0x89, 0x17, 0xe9, 0xf7, 0x00, 0x63, 0xc1, 0x31, 0xb7, 0x49, + 0xd2, 0x72, 0x78, 0x16, 0x4d, 0x89, 0xb3, 0x9e, 0xee, 0xc5, 0x6b, 0x52, 0x94, 0x87, 0x16, 0xc3, + 0x6a, 0xb0, 0xb6, 0x76, 0xfb, 0x6a, 0x2b, 0x15, 0x04, 0xce, 0xdc, 0x1a, 0x05, 0x12, 0x7a, 0xf6, + 0xda, 0xe1, 0x57, 0x2f, 0x8e, 0xc9, 0xa6, 0xdc, 0x1a, 0xd5, 0x49, 0x67, 0x76, 0xc8, 0x77, 0xa4, + 0x4a, 0x3d, 0x6b, 0xdf, 0xb7, 0x48, 0x7f, 0xd4, 0x3a, 0x7b, 0xb1, 0x68, 0x3b, 0x40, 0x65, 0x33, + 0x46, 0x65, 0x58, 0x8d, 0x0a, 0x8c, 0xcd, 0x0e, 0xa1, 0xfd, 0x9b, 0x83, 0x25, 0xd8, 0x11, 0x41, + 0xf8, 0x45, 0xaa, 0x5d, 0x77, 0x2d, 0xb1, 0xe5, 0xe8, 0xbd, 0xfe, 0xf8, 0xf9, 0x55, 0x6c, 0x72, + 0x40, 0x35, 0xcb, 0x07, 0xbd, 0x06, 0xfb, 0xa4, 0x64, 0xa7, 0x29, 0xdd, 0x3a, 0xdc, 0x77, 0xb7, + 0xae, 0xfd, 0x6e, 0x11, 0xbd, 0x2a, 0x1a, 0xc2, 0x5f, 0x6a, 0x68, 0x34, 0xd0, 0x74, 0xf8, 0x42, + 0xa6, 0x97, 0x24, 0xa5, 0x99, 0x5b, 0xeb, 0xc7, 0x44, 0x12, 0xd0, 0xef, 0xfd, 0xf4, 0xef, 0xff, + 0xfd, 0xe5, 0xd0, 0x3b, 0xb8, 0x20, 0xce, 0xbe, 0x56, 0xe5, 0x31, 0x58, 0xfb, 0xf4, 0xab, 0xad, + 0x26, 0x8d, 0xdd, 0x2e, 0x21, 0xb7, 0x67, 0xec, 0x46, 0xa4, 0xea, 0x1e, 0xfe, 0xa7, 0x86, 0x70, + 0xb7, 0x1a, 0xc4, 0xd7, 0x7b, 0xc3, 0x4a, 0xd5, 0xa4, 0xb9, 0xb7, 0x07, 0x33, 0x06, 0x76, 0x77, + 0x04, 0xbb, 0x9b, 0xf8, 0x46, 0x22, 0x3b, 0xa0, 0x54, 0x69, 0x85, 0x58, 0x25, 0x11, 0xc5, 0xbf, + 0xd1, 0xd0, 0x78, 0x48, 0x93, 0xe1, 0xd5, 0xde, 0xa0, 0x42, 0xd5, 0x73, 0x6f, 0xf5, 0x55, 0xbd, + 0x0d, 0xfe, 0xac, 0x00, 0xbf, 0x80, 0x4f, 0x25, 0x82, 0x6f, 0xa7, 0x45, 0x46, 0x38, 0xfe, 0x83, + 0x86, 0x26, 0x63, 0x12, 0x4f, 0x65, 0x00, 0xc5, 0x4c, 0x72, 0x57, 0xfb, 0x36, 0x69, 0x83, 0x5d, + 0x11, 0x60, 0xdf, 0xc4, 0x8b, 0x89, 0x60, 0x59, 0x0c, 0xdb, 0x7f, 0x34, 0x74, 0x34, 0x59, 0xed, + 0xe1, 0x9b, 0xbd, 0x31, 0x64, 0x0a, 0xcd, 0xdc, 0xad, 0xc1, 0x1d, 0x00, 0x97, 0x82, 0xe0, 0xf2, + 0x36, 0xbe, 0x96, 0xc8, 0xa5, 0x4e, 0x78, 0x39, 0xac, 0xfe, 0xca, 0x35, 0xea, 0xc9, 0x02, 0x63, + 0x37, 0xc8, 0x30, 0x7b, 0xf8, 0x73, 0x0d, 0x4d, 0x44, 0x9b, 0xc1, 0x97, 0xfb, 0x05, 0x16, 0x30, + 0xba, 0xd2, 0xbf, 0x21, 0x30, 0x59, 0x15, 0x4c, 0xce, 0xe0, 0xd3, 0x4a, 0x4c, 0x7c, 0xd0, 0x11, + 0x91, 0xa4, 0x86, 0xb8, 0x5b, 0x11, 0x2a, 0x22, 0x4e, 0xd0, 0x78, 0xfa, 0x79, 0x81, 0x78, 0x19, + 0x2f, 0x25, 0x22, 0x0e, 0x69, 0x52, 0x63, 0x57, 0xc8, 0xe0, 0x3d, 0x7f, 0xec, 0x4f, 0x84, 0x3c, + 0xad, 0x3b, 0x8e, 0x0a, 0xee, 0x44, 0x25, 0xab, 0x82, 0x3b, 0x59, 0x9b, 0xea, 0x4b, 0x02, 0xb7, + 0x8e, 0xe7, 0x7b, 0xe1, 0xc6, 0x7f, 0xd6, 0xd0, 0x64, 0x4c, 0xb6, 0xa9, 0xa4, 0xc8, 0x54, 0x7d, + 0xa9, 0x92, 0x22, 0xd3, 0x95, 0x67, 0x8f, 0x21, 0x12, 0x17, 0xa5, 0xf8, 0x57, 0x1a, 0x1a, 0x91, + 0x62, 0x0f, 0xaf, 0x29, 0xb5, 0x1b, 0xd1, 0x9b, 0xb9, 0x8b, 0x7d, 0xd9, 0x00, 0xc4, 0x05, 0x01, + 0xf1, 0x0d, 0x7c, 0x3c, 0x11, 0xa2, 0x94, 0x9c, 0xf8, 0x2f, 0x1a, 0x9a, 0xee, 0x12, 0x93, 0xf8, + 0x9a, 0x42, 0x46, 0x4b, 0xd1, 0xa8, 0xb9, 0xeb, 0x03, 0xd9, 0x02, 0xe6, 0xab, 0x02, 0xf3, 0x45, + 0x7c, 0x21, 0x8c, 0xb9, 0xfb, 0x7a, 0x89, 0x35, 0xe8, 0xc7, 0x31, 0x85, 0x8b, 0xff, 0xa6, 0xa1, + 0xe9, 0x2e, 0x21, 0xa9, 0xc2, 0x24, 0x4d, 0xc9, 0xaa, 0x30, 0x49, 0x55, 0xae, 0xfa, 0x6d, 0xc1, + 0xe4, 0x06, 0xbe, 0x9e, 0xbc, 0x86, 0x0a, 0xf5, 0x13, 0x5f, 0x42, 0x63, 0xb2, 0x79, 0xcf, 0x97, + 0x36, 0x78, 0x93, 0xf0, 0x98, 0xa4, 0xc4, 0x6a, 0xf3, 0x2d, 0x41, 0xed, 0xaa, 0x2c, 0x55, 0x29, + 0xfa, 0x55, 0x5f, 0x13, 0x84, 0x56, 0xf0, 0x72, 0x6a, 0x52, 0x34, 0x1d, 0xa7, 0x2c, 0x39, 0x78, + 0x00, 0xf4, 0x99, 0x86, 0x8e, 0x08, 0x67, 0x2c, 0xa6, 0x04, 0xf1, 0x0d, 0xe5, 0xd8, 0x26, 0xc9, + 0xd2, 0xdc, 0xb7, 0x07, 0x35, 0x07, 0x32, 0x5b, 0x82, 0x4c, 0x01, 0xdf, 0xca, 0xee, 0x1d, 0x39, + 0x85, 0x4d, 0xd7, 0x92, 0xc7, 0xf9, 0xa1, 0x95, 0xca, 0xd8, 0x15, 0x25, 0x7b, 0xf8, 0x2b, 0x0d, + 0x1d, 0x8a, 0x1c, 0x0c, 0xe3, 0x6f, 0x29, 0x4d, 0xd6, 0xae, 0xf3, 0xf5, 0xdc, 0xe5, 0xbe, 0xed, + 0x80, 0xcc, 0x4d, 0x41, 0xe6, 0x2a, 0xbe, 0x9c, 0xda, 0x33, 0x9c, 0xb1, 0x40, 0x6f, 0x1a, 0xbb, + 0xf1, 0x53, 0xef, 0x3d, 0xfc, 0xeb, 0x21, 0x34, 0x97, 0x7d, 0xb8, 0x8d, 0x37, 0xfb, 0x04, 0x97, + 0x76, 0x54, 0x9f, 0xdb, 0x7a, 0x79, 0x47, 0x40, 0xbb, 0x22, 0x68, 0x7f, 0x0f, 0x3f, 0x56, 0xa1, + 0x5d, 0x6e, 0x88, 0x33, 0x70, 0xbb, 0x6a, 0x3a, 0xc6, 0x6e, 0xe2, 0x5d, 0xc1, 0x5e, 0x52, 0x64, + 0x3e, 0xd3, 0xc4, 0x5d, 0x0a, 0x36, 0xd4, 0x50, 0xb7, 0xaf, 0x66, 0x72, 0xe7, 0xd5, 0x0d, 0x80, + 0xce, 0xbc, 0xa0, 0x93, 0xc3, 0xb3, 0x89, 0x74, 0x7c, 0x10, 0xbf, 0xd5, 0x10, 0xea, 0x9c, 0xe6, + 0x63, 0x85, 0x45, 0xa1, 0xeb, 0x7a, 0x21, 0x77, 0xa9, 0x3f, 0x23, 0xc0, 0x76, 0x46, 0x60, 0x3b, + 0x85, 0x4f, 0x26, 0x62, 0xe3, 0x1d, 0x4c, 0x5f, 0x68, 0x68, 0x2a, 0x72, 0x9d, 0xe5, 0xeb, 0x0a, + 0xb5, 0xa4, 0x93, 0x74, 0x81, 0x99, 0xbb, 0x36, 0x88, 0x29, 0x80, 0x5e, 0x16, 0xa0, 0x17, 0xb1, + 0x9e, 0x08, 0x3a, 0x7a, 0xcb, 0xf8, 0x57, 0x0d, 0xcd, 0x24, 0xdd, 0xec, 0xa9, 0xe4, 0xa9, 0x8c, + 0x0b, 0x45, 0x95, 0x3c, 0x95, 0x75, 0xa1, 0xa8, 0xbf, 0x25, 0x38, 0x18, 0x78, 0xb5, 0x37, 0x87, + 0xb0, 0x8c, 0xfe, 0x42, 0x8b, 0xdc, 0x59, 0xf7, 0xa3, 0xa1, 0xa3, 0xf1, 0xbf, 0xd2, 0xbf, 0x21, + 0x20, 0xbf, 0x28, 0x90, 0xaf, 0xe2, 0x73, 0xc9, 0x02, 0xa9, 0x63, 0x11, 0xc6, 0xed, 0x8b, 0xd2, + 0x90, 0x33, 0x75, 0x51, 0x3a, 0x18, 0xf4, 0xe4, 0x0b, 0xff, 0x1e, 0xa2, 0x34, 0x04, 0xdd, 0x57, + 0x4f, 0x33, 0x49, 0x5f, 0x74, 0xa8, 0x0c, 0x9b, 0x8c, 0x2f, 0x49, 0x54, 0x86, 0x4d, 0xd6, 0x87, + 0x24, 0x3d, 0xb6, 0x03, 0x75, 0x91, 0x5f, 0x23, 0xd6, 0xf8, 0x1f, 0x1a, 0x3a, 0x96, 0xf2, 0xad, + 0x0d, 0xbe, 0x35, 0x18, 0x9a, 0xce, 0xe7, 0x3c, 0xb9, 0xf5, 0x97, 0xf0, 0x00, 0x94, 0x2e, 0x09, + 0x4a, 0x79, 0xbc, 0x92, 0x46, 0x69, 0xdd, 0x71, 0xe2, 0x3e, 0x58, 0xe1, 0xce, 0xd7, 0xcf, 0xe7, + 0xb4, 0x6f, 0x9e, 0xcf, 0x69, 0xcf, 0x9e, 0xcf, 0x69, 0xbf, 0x78, 0x31, 0x77, 0xe0, 0x9b, 0x17, + 0x73, 0x07, 0xfe, 0xf5, 0x62, 0xee, 0xc0, 0xe3, 0x73, 0x75, 0x9b, 0x37, 0x76, 0x2a, 0xf9, 0x2a, + 0xdd, 0x0e, 0x7b, 0xf4, 0xb7, 0x1c, 0xc6, 0x27, 0xa1, 0xdc, 0xd6, 0x6a, 0x12, 0x56, 0x19, 0x11, + 0x1f, 0x2f, 0x5d, 0xfc, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x10, 0x87, 0xac, 0x67, 0xb2, 0x27, + 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -4178,41 +4124,6 @@ func (m *QueryBallotByIdentifierRequest) MarshalToSizedBuffer(dAtA []byte) (int, return len(dAtA) - i, nil } -func (m *VoterList) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *VoterList) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *VoterList) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.VoteType != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.VoteType)) - i-- - dAtA[i] = 0x10 - } - if len(m.VoterAddress) > 0 { - i -= len(m.VoterAddress) - copy(dAtA[i:], m.VoterAddress) - i = encodeVarintQuery(dAtA, i, uint64(len(m.VoterAddress))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - func (m *QueryBallotByIdentifierResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -5366,22 +5277,6 @@ func (m *QueryBallotByIdentifierRequest) Size() (n int) { return n } -func (m *VoterList) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.VoterAddress) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - if m.VoteType != 0 { - n += 1 + sovQuery(uint64(m.VoteType)) - } - return n -} - func (m *QueryBallotByIdentifierResponse) Size() (n int) { if m == nil { return 0 @@ -7710,107 +7605,6 @@ func (m *QueryBallotByIdentifierRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *VoterList) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: VoterList: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: VoterList: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field VoterAddress", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.VoterAddress = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field VoteType", wireType) - } - m.VoteType = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.VoteType |= VoteType(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipQuery(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func (m *QueryBallotByIdentifierResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -7901,7 +7695,7 @@ func (m *QueryBallotByIdentifierResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Voters = append(m.Voters, &VoterList{}) + m.Voters = append(m.Voters, VoterList{}) if err := m.Voters[len(m.Voters)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } From 16d21c4dedf616257bacaf75de9ce107f90104d3 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Tue, 10 Sep 2024 18:14:27 -0400 Subject: [PATCH 02/16] add unit tests --- testutil/keeper/mocks/emissions/observer.go | 6 +- x/observer/keeper/ballot_test.go | 190 ++++++++++++++++++++ x/observer/keeper/events_test.go | 75 ++++++++ x/observer/keeper/grpc_query_ballot_test.go | 2 +- x/observer/types/ballot.go | 1 + x/observer/types/ballot_test.go | 105 +++++++++++ 6 files changed, 375 insertions(+), 4 deletions(-) create mode 100644 x/observer/keeper/events_test.go diff --git a/testutil/keeper/mocks/emissions/observer.go b/testutil/keeper/mocks/emissions/observer.go index 2a10eea3dd..fd50cf5fbe 100644 --- a/testutil/keeper/mocks/emissions/observer.go +++ b/testutil/keeper/mocks/emissions/observer.go @@ -15,9 +15,9 @@ type EmissionObserverKeeper struct { mock.Mock } -// ClearMaturedBallots provides a mock function with given fields: ctx, maturityBlocks -func (_m *EmissionObserverKeeper) ClearMaturedBallots(ctx types.Context, maturityBlocks int64) { - _m.Called(ctx, maturityBlocks) +// ClearMaturedBallots provides a mock function with given fields: ctx, ballots, maturityBlocks +func (_m *EmissionObserverKeeper) ClearMaturedBallots(ctx types.Context, ballots []observertypes.Ballot, maturityBlocks int64) { + _m.Called(ctx, ballots, maturityBlocks) } // GetBallot provides a mock function with given fields: ctx, index diff --git a/x/observer/keeper/ballot_test.go b/x/observer/keeper/ballot_test.go index 2f88571558..a5d2d0eafe 100644 --- a/x/observer/keeper/ballot_test.go +++ b/x/observer/keeper/ballot_test.go @@ -118,3 +118,193 @@ func TestKeeper_GetAllBallots(t *testing.T) { require.Equal(t, 1, len(ballots)) require.Equal(t, b, ballots[0]) } + +func TestKeeper_DeleteBallot(t *testing.T) { + t.Run("delete existing ballot", func(t *testing.T) { + //Arrange + k, ctx, _, _ := keepertest.ObserverKeeper(t) + identifier := sample.ZetaIndex(t) + b := &types.Ballot{ + BallotIdentifier: identifier, + } + k.SetBallot(ctx, b) + _, found := k.GetBallot(ctx, identifier) + require.True(t, found) + + //Act + k.DeleteBallot(ctx, identifier) + + //Assert + _, found = k.GetBallot(ctx, identifier) + require.False(t, found) + }) + + t.Run("delete non-existing ballot,nothing happens", func(t *testing.T) { + //Arrange + k, ctx, _, _ := keepertest.ObserverKeeper(t) + identifier := sample.ZetaIndex(t) + numberOfBallots := 10 + for i := 0; i < numberOfBallots; i++ { + k.SetBallot(ctx, &types.Ballot{ + BallotIdentifier: sample.ZetaIndex(t), + }) + } + + require.Len(t, k.GetAllBallots(ctx), numberOfBallots) + + //Act + k.DeleteBallot(ctx, identifier) + + //Assert + _, found := k.GetBallot(ctx, identifier) + require.False(t, found) + require.Len(t, k.GetAllBallots(ctx), numberOfBallots) + }) +} + +func TestKeeper_DeleteBallotList(t *testing.T) { + t.Run("delete existing ballot list", func(t *testing.T) { + //Arrange + k, ctx, _, _ := keepertest.ObserverKeeper(t) + numberOfBallotLists := 10 + for i := 0; i < numberOfBallotLists; i++ { + k.AddBallotToList(ctx, types.Ballot{ + Index: sample.ZetaIndex(t), + BallotCreationHeight: 1, + }) + } + + _, found := k.GetBallotList(ctx, 1) + require.True(t, found) + + //Act + k.DeleteBallotList(ctx, 1) + + //Assert + _, found = k.GetBallotList(ctx, 1) + require.False(t, found) + }) + + t.Run("delete non-existing ballot list, nothing happens", func(t *testing.T) { + //Arrange + k, ctx, _, _ := keepertest.ObserverKeeper(t) + numberOfBallotLists := 10 + for i := 0; i < numberOfBallotLists; i++ { + k.AddBallotToList(ctx, types.Ballot{ + Index: sample.ZetaIndex(t), + BallotCreationHeight: 1, + }) + } + + _, found := k.GetBallotList(ctx, 1) + require.True(t, found) + + //Act + k.DeleteBallotList(ctx, 2) + + //Assert + _, found = k.GetBallotList(ctx, 1) + require.True(t, found) + }) +} + +func TestKeeper_ClearMaturedBallots(t *testing.T) { + t.Run("clear matured ballots successfully", func(t *testing.T) { + //Arrange + k, ctx, _, _ := keepertest.ObserverKeeper(t) + numberOfBallots := 10 + ballots := make([]types.Ballot, numberOfBallots) + for i := 0; i < numberOfBallots; i++ { + b := types.Ballot{ + BallotIdentifier: sample.ZetaIndex(t), + BallotCreationHeight: 1, + } + k.AddBallotToList(ctx, b) + k.SetBallot(ctx, &b) + ballots[i] = b + } + _, found := k.GetBallotList(ctx, 1) + require.True(t, found) + require.Equal(t, numberOfBallots, len(k.GetAllBallots(ctx))) + + //Act + k.ClearMaturedBallots(ctx, ballots, 0) + + //Assert + for _, b := range ballots { + _, found = k.GetBallot(ctx, b.BallotIdentifier) + require.False(t, found) + } + _, found = k.GetBallotList(ctx, 0) + require.False(t, found) + eventCount := 0 + for _, event := range ctx.EventManager().Events() { + if event.Type == "zetachain.zetacore.observer.EventBallotDeleted" { + eventCount++ + } + } + require.Equal(t, numberOfBallots, eventCount) + }) + + t.Run("clear only ballotList if no ballots are found", func(t *testing.T) { + //Arrange + k, ctx, _, _ := keepertest.ObserverKeeper(t) + numberOfBallots := 10 + ballots := make([]types.Ballot, numberOfBallots) + for i := 0; i < numberOfBallots; i++ { + b := types.Ballot{ + BallotIdentifier: sample.ZetaIndex(t), + BallotCreationHeight: 1, + } + k.AddBallotToList(ctx, b) + ballots[i] = b + } + _, found := k.GetBallotList(ctx, 1) + require.True(t, found) + require.Equal(t, 0, len(k.GetAllBallots(ctx))) + + //Act + k.ClearMaturedBallots(ctx, []types.Ballot{}, 0) + + //Assert + _, found = k.GetBallotList(ctx, 1) + require.False(t, found) + require.Equal(t, 0, len(k.GetAllBallots(ctx))) + }) + + t.Run("clear only ballots successfully if ballotList is not found", func(t *testing.T) { + //Arrange + k, ctx, _, _ := keepertest.ObserverKeeper(t) + numberOfBallots := 10 + ballots := make([]types.Ballot, numberOfBallots) + for i := 0; i < numberOfBallots; i++ { + b := types.Ballot{ + BallotIdentifier: sample.ZetaIndex(t), + BallotCreationHeight: 1, + } + k.SetBallot(ctx, &b) + ballots[i] = b + } + require.Equal(t, numberOfBallots, len(k.GetAllBallots(ctx))) + _, found := k.GetBallotList(ctx, 1) + require.False(t, found) + + //Act + k.ClearMaturedBallots(ctx, ballots, 0) + + //Assert + for _, b := range ballots { + _, found := k.GetBallot(ctx, b.BallotIdentifier) + require.False(t, found) + } + _, found = k.GetBallotList(ctx, 1) + require.False(t, found) + eventCount := 0 + for _, event := range ctx.EventManager().Events() { + if event.Type == "zetachain.zetacore.observer.EventBallotDeleted" { + eventCount++ + } + } + require.Equal(t, numberOfBallots, eventCount) + }) +} diff --git a/x/observer/keeper/events_test.go b/x/observer/keeper/events_test.go new file mode 100644 index 0000000000..6f286e141e --- /dev/null +++ b/x/observer/keeper/events_test.go @@ -0,0 +1,75 @@ +package keeper_test + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" + keepertest "github.com/zeta-chain/node/testutil/keeper" + "github.com/zeta-chain/node/testutil/sample" + "github.com/zeta-chain/node/x/observer/keeper" + "github.com/zeta-chain/node/x/observer/types" +) + +func TestEmitEventBallotDeleted(t *testing.T) { + tt := []struct { + name string + ballotIdentifier string + ballotType types.ObservationType + voters []string + voteType []types.VoteType + }{ + { + name: "successfull votes only", + ballotIdentifier: sample.ZetaIndex(t), + ballotType: types.ObservationType_InboundTx, + voters: []string{"voter1", "voter2"}, + voteType: []types.VoteType{types.VoteType_SuccessObservation, types.VoteType_SuccessObservation}, + }, + + { + name: "failed votes only", + ballotIdentifier: sample.ZetaIndex(t), + ballotType: types.ObservationType_InboundTx, + voters: []string{"voter1", "voter2"}, + voteType: []types.VoteType{types.VoteType_FailureObservation, types.VoteType_FailureObservation}, + }, + } + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + _, ctx, _, _ := keepertest.ObserverKeeper(t) + ballot := types.Ballot{ + BallotIdentifier: tc.ballotIdentifier, + ObservationType: tc.ballotType, + VoterList: tc.voters, + Votes: tc.voteType, + } + keeper.EmitEventBallotDeleted(ctx, ballot) + for _, event := range ctx.EventManager().Events() { + for _, attr := range event.Attributes { + if attr.Key == "ballot_identifier" { + require.Equal(t, tc.ballotIdentifier, RemoveQuotes(attr.Value)) + } + if attr.Key == "ballot_type" { + require.Equal(t, tc.ballotType.String(), RemoveQuotes(attr.Value)) + } + if attr.Key == "voters" { + expectedString := "" + for _, voter := range ballot.GenerateVoterList() { + st := fmt.Sprintf("{\"voter_address\":\"%s\",\"vote_type\":\"%s\"}", voter.VoterAddress, voter.VoteType) + expectedString += st + expectedString += "," + } + expectedString = expectedString[:len(expectedString)-1] + require.Equal(t, expectedString, RemoveQuotes(attr.Value)) + } + } + } + + }) + } +} + +func RemoveQuotes(s string) string { + return s[1 : len(s)-1] +} diff --git a/x/observer/keeper/grpc_query_ballot_test.go b/x/observer/keeper/grpc_query_ballot_test.go index fe34971a64..48b76b40e7 100644 --- a/x/observer/keeper/grpc_query_ballot_test.go +++ b/x/observer/keeper/grpc_query_ballot_test.go @@ -124,7 +124,7 @@ func TestKeeper_BallotByIdentifier(t *testing.T) { require.NoError(t, err) require.Equal(t, &types.QueryBallotByIdentifierResponse{ BallotIdentifier: ballot.BallotIdentifier, - Voters: []*types.VoterList{ + Voters: []types.VoterList{ { VoterAddress: voter, VoteType: types.VoteType_SuccessObservation, diff --git a/x/observer/types/ballot.go b/x/observer/types/ballot.go index 8464f31032..967a5d5749 100644 --- a/x/observer/types/ballot.go +++ b/x/observer/types/ballot.go @@ -125,5 +125,6 @@ func (m Ballot) GenerateVoterList() []VoterList { } votersList[i] = voter } + return votersList } diff --git a/x/observer/types/ballot_test.go b/x/observer/types/ballot_test.go index 3f428e99d4..5cba1713ab 100644 --- a/x/observer/types/ballot_test.go +++ b/x/observer/types/ballot_test.go @@ -477,5 +477,110 @@ func Test_BuildRewardsDistribution(t *testing.T) { require.Equal(t, test.expectedMap, rewardsMap) }) } +} + +func TestBallot_GenerateVoterList(t *testing.T) { + tt := []struct { + name string + voters []string + votes []VoteType + expectedVoterList []VoterList + }{ + { + name: "Success observation", + voters: []string{"Observer1", "Observer2", "Observer3", "Observer4"}, + votes: []VoteType{ + VoteType_SuccessObservation, + VoteType_SuccessObservation, + VoteType_SuccessObservation, + VoteType_SuccessObservation, + }, + expectedVoterList: []VoterList{ + { + VoterAddress: "Observer1", + VoteType: VoteType_SuccessObservation, + }, + { + VoterAddress: "Observer2", + VoteType: VoteType_SuccessObservation, + }, + { + VoterAddress: "Observer3", + VoteType: VoteType_SuccessObservation, + }, + { + VoterAddress: "Observer4", + VoteType: VoteType_SuccessObservation, + }, + }, + }, + { + name: "Failure observation", + voters: []string{"Observer1", "Observer2", "Observer3", "Observer4"}, + votes: []VoteType{ + VoteType_FailureObservation, + VoteType_FailureObservation, + VoteType_FailureObservation, + VoteType_FailureObservation, + }, + expectedVoterList: []VoterList{ + { + VoterAddress: "Observer1", + VoteType: VoteType_FailureObservation, + }, + { + VoterAddress: "Observer2", + VoteType: VoteType_FailureObservation, + }, + { + VoterAddress: "Observer3", + VoteType: VoteType_FailureObservation, + }, + { + VoterAddress: "Observer4", + VoteType: VoteType_FailureObservation, + }, + }, + }, + + { + name: "mixed observation", + voters: []string{"Observer1", "Observer2", "Observer3", "Observer4"}, + votes: []VoteType{ + VoteType_FailureObservation, + VoteType_FailureObservation, + VoteType_SuccessObservation, + VoteType_SuccessObservation, + }, + expectedVoterList: []VoterList{ + { + VoterAddress: "Observer1", + VoteType: VoteType_FailureObservation, + }, + { + VoterAddress: "Observer2", + VoteType: VoteType_FailureObservation, + }, + { + VoterAddress: "Observer3", + VoteType: VoteType_SuccessObservation, + }, + { + VoterAddress: "Observer4", + VoteType: VoteType_SuccessObservation, + }, + }, + }, + } + for _, test := range tt { + t.Run(test.name, func(t *testing.T) { + ballot := Ballot{ + VoterList: test.voters, + Votes: test.votes, + } + voterList := ballot.GenerateVoterList() + require.Equal(t, test.expectedVoterList, voterList) + }) + } } From 9adb64e3f5fe92147c1d49262758e6f018c16e86 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Wed, 11 Sep 2024 12:31:54 -0400 Subject: [PATCH 03/16] refactor abci tests --- changelog.md | 1 + .../zetacore/observer/ballot_pb.d.ts | 29 +++++++++++++++++ .../zetacore/observer/events_pb.d.ts | 5 +-- .../zetachain/zetacore/observer/query_pb.d.ts | 31 +------------------ x/emissions/abci.go | 2 +- x/emissions/abci_test.go | 22 ++++++++++++- x/observer/keeper/events_test.go | 6 +++- 7 files changed, 61 insertions(+), 35 deletions(-) diff --git a/changelog.md b/changelog.md index 091479dea1..9609ca7bd7 100644 --- a/changelog.md +++ b/changelog.md @@ -26,6 +26,7 @@ * [2725](https://github.com/zeta-chain/node/pull/2725) - refactor SetCctxAndNonceToCctxAndInboundHashToCctx to receive tsspubkey as an argument * [2802](https://github.com/zeta-chain/node/pull/2802) - set default liquidity cap for new ZRC20s * [2826](https://github.com/zeta-chain/node/pull/2826) - remove unused code from emissions module and add new parameter for fixed block reward amount +* [2863](https://github.com/zeta-chain/node/pull/2863) - delete ballots after they mature ### Tests diff --git a/typescript/zetachain/zetacore/observer/ballot_pb.d.ts b/typescript/zetachain/zetacore/observer/ballot_pb.d.ts index 286d51d5aa..5867a3c604 100644 --- a/typescript/zetachain/zetacore/observer/ballot_pb.d.ts +++ b/typescript/zetachain/zetacore/observer/ballot_pb.d.ts @@ -142,3 +142,32 @@ export declare class BallotListForHeight extends Message { static equals(a: BallotListForHeight | PlainMessage | undefined, b: BallotListForHeight | PlainMessage | undefined): boolean; } +/** + * @generated from message zetachain.zetacore.observer.VoterList + */ +export declare class VoterList extends Message { + /** + * @generated from field: string voter_address = 1; + */ + voterAddress: string; + + /** + * @generated from field: zetachain.zetacore.observer.VoteType vote_type = 2; + */ + voteType: VoteType; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "zetachain.zetacore.observer.VoterList"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): VoterList; + + static fromJson(jsonValue: JsonValue, options?: Partial): VoterList; + + static fromJsonString(jsonString: string, options?: Partial): VoterList; + + static equals(a: VoterList | PlainMessage | undefined, b: VoterList | PlainMessage | undefined): boolean; +} + diff --git a/typescript/zetachain/zetacore/observer/events_pb.d.ts b/typescript/zetachain/zetacore/observer/events_pb.d.ts index 61987af05d..cd9824a0d6 100644 --- a/typescript/zetachain/zetacore/observer/events_pb.d.ts +++ b/typescript/zetachain/zetacore/observer/events_pb.d.ts @@ -5,6 +5,7 @@ import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf"; import { Message, proto3 } from "@bufbuild/protobuf"; +import type { VoterList } from "./ballot_pb.js"; import type { GasPriceIncreaseFlags } from "./crosschain_flags_pb.js"; /** @@ -71,9 +72,9 @@ export declare class EventBallotDeleted extends Message { ballotType: string; /** - * @generated from field: string votes_collected = 4; + * @generated from field: repeated zetachain.zetacore.observer.VoterList voters = 4; */ - votesCollected: string; + voters: VoterList[]; constructor(data?: PartialMessage); diff --git a/typescript/zetachain/zetacore/observer/query_pb.d.ts b/typescript/zetachain/zetacore/observer/query_pb.d.ts index 65f151c3be..7ce071ea83 100644 --- a/typescript/zetachain/zetacore/observer/query_pb.d.ts +++ b/typescript/zetachain/zetacore/observer/query_pb.d.ts @@ -10,7 +10,7 @@ import type { ChainNonces } from "./chain_nonces_pb.js"; import type { PageRequest, PageResponse } from "../../../cosmos/base/query/v1beta1/pagination_pb.js"; import type { PendingNonces } from "./pending_nonces_pb.js"; import type { TSS } from "./tss_pb.js"; -import type { BallotStatus, VoteType } from "./ballot_pb.js"; +import type { BallotStatus, VoterList } from "./ballot_pb.js"; import type { LastObserverCount, ObservationType } from "./observer_pb.js"; import type { Chain } from "../pkg/chains/chains_pb.js"; import type { ChainParams, ChainParamsList } from "./params_pb.js"; @@ -596,35 +596,6 @@ export declare class QueryBallotByIdentifierRequest extends Message | undefined, b: QueryBallotByIdentifierRequest | PlainMessage | undefined): boolean; } -/** - * @generated from message zetachain.zetacore.observer.VoterList - */ -export declare class VoterList extends Message { - /** - * @generated from field: string voter_address = 1; - */ - voterAddress: string; - - /** - * @generated from field: zetachain.zetacore.observer.VoteType vote_type = 2; - */ - voteType: VoteType; - - constructor(data?: PartialMessage); - - static readonly runtime: typeof proto3; - static readonly typeName = "zetachain.zetacore.observer.VoterList"; - static readonly fields: FieldList; - - static fromBinary(bytes: Uint8Array, options?: Partial): VoterList; - - static fromJson(jsonValue: JsonValue, options?: Partial): VoterList; - - static fromJsonString(jsonString: string, options?: Partial): VoterList; - - static equals(a: VoterList | PlainMessage | undefined, b: VoterList | PlainMessage | undefined): boolean; -} - /** * @generated from message zetachain.zetacore.observer.QueryBallotByIdentifierResponse */ diff --git a/x/emissions/abci.go b/x/emissions/abci.go index 7909793027..4ab0e4da24 100644 --- a/x/emissions/abci.go +++ b/x/emissions/abci.go @@ -6,11 +6,11 @@ import ( sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - observertypes "github.com/zeta-chain/node/x/observer/types" "github.com/zeta-chain/node/cmd/zetacored/config" "github.com/zeta-chain/node/x/emissions/keeper" "github.com/zeta-chain/node/x/emissions/types" + observertypes "github.com/zeta-chain/node/x/observer/types" ) func BeginBlocker(ctx sdk.Context, keeper keeper.Keeper) { diff --git a/x/emissions/abci_test.go b/x/emissions/abci_test.go index 2ef62ed7b5..95bd9b45ac 100644 --- a/x/emissions/abci_test.go +++ b/x/emissions/abci_test.go @@ -203,7 +203,8 @@ func TestBeginBlocker(t *testing.T) { }) t.Run("successfully distribute rewards", func(t *testing.T) { - numberOfTestBlocks := 100 + //Arrange + numberOfTestBlocks := 10 k, ctx, sk, zk := keepertest.EmissionsKeeper(t) observerSet := sample.ObserverSet(10) zk.ObserverKeeper.SetObserverSet(ctx, observerSet) @@ -238,6 +239,9 @@ func TestBeginBlocker(t *testing.T) { params, found := k.GetParams(ctx) require.True(t, found) + // Set the ballot maturity blocks to numberOfTestBlocks so that the ballot mature at the end of the for loop which produces blocks + params.BallotMaturityBlocks = int64(numberOfTestBlocks) + err = k.SetParams(ctx, params) // Get the rewards distribution, this is a fixed amount based on total block rewards and distribution percentages validatorRewardsForABlock, observerRewardsForABlock, tssSignerRewardsForABlock := emissionstypes.GetRewardsDistributions( @@ -247,6 +251,11 @@ func TestBeginBlocker(t *testing.T) { distributedRewards := observerRewardsForABlock.Add(validatorRewardsForABlock).Add(tssSignerRewardsForABlock) require.True(t, blockRewards.TruncateInt().GT(distributedRewards)) + require.Len(t, zk.ObserverKeeper.GetAllBallots(ctx), len(ballotList)) + _, found = zk.ObserverKeeper.GetBallotList(ctx, 0) + require.True(t, found) + + // Act for i := 0; i < numberOfTestBlocks; i++ { emissionPoolBeforeBlockDistribution := sk.BankKeeper.GetBalance(ctx, emissionPool, config.BaseDenom).Amount // produce a block @@ -277,12 +286,23 @@ func TestBeginBlocker(t *testing.T) { ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) } + // Assert + + // 1. Assert Observer rewards, these are distributed at the block in which the ballots mature. + // numberOfTestBlocks is the same maturity blocks for the ballots + // We can simplify the calculation as the rewards are distributed equally among all the observers rewardPerUnit := observerRewardsForABlock.Quo( sdk.NewInt(int64(len(ballotList) * len(observerSet.ObserverList))), ) emissionAmount := rewardPerUnit.Mul(sdk.NewInt(int64(len(ballotList)))) + // 2 . Assert ballots and ballot list are deleted on maturity + require.Len(t, zk.ObserverKeeper.GetAllBallots(ctx), 0) + _, found = zk.ObserverKeeper.GetBallotList(ctx, 0) + require.False(t, found) + + //3. Assert amounts in undistributed pools // Check if the rewards are distributed equally among all the observers for _, observer := range observerSet.ObserverList { observerEmission, found := k.GetWithdrawableEmission(ctx, observer) diff --git a/x/observer/keeper/events_test.go b/x/observer/keeper/events_test.go index 6f286e141e..2fcda72609 100644 --- a/x/observer/keeper/events_test.go +++ b/x/observer/keeper/events_test.go @@ -56,7 +56,11 @@ func TestEmitEventBallotDeleted(t *testing.T) { if attr.Key == "voters" { expectedString := "" for _, voter := range ballot.GenerateVoterList() { - st := fmt.Sprintf("{\"voter_address\":\"%s\",\"vote_type\":\"%s\"}", voter.VoterAddress, voter.VoteType) + st := fmt.Sprintf( + "{\"voter_address\":\"%s\",\"vote_type\":\"%s\"}", + voter.VoterAddress, + voter.VoteType, + ) expectedString += st expectedString += "," } From 4779bda9d3a944f69b7c59c97642e00420069ca3 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Wed, 11 Sep 2024 16:58:32 -0400 Subject: [PATCH 04/16] refactor generate voter list method --- x/observer/keeper/ballot.go | 5 +- x/observer/keeper/ballot_test.go | 102 ++++++++++++++++++++----- x/observer/keeper/events.go | 11 ++- x/observer/keeper/events_test.go | 70 +++++++++++------ x/observer/keeper/grpc_query_ballot.go | 6 +- x/observer/types/ballot.go | 16 ++-- x/observer/types/ballot_test.go | 22 +++++- x/observer/types/errors.go | 2 + 8 files changed, 182 insertions(+), 52 deletions(-) diff --git a/x/observer/keeper/ballot.go b/x/observer/keeper/ballot.go index 4c8487d2f1..d35d9c337a 100644 --- a/x/observer/keeper/ballot.go +++ b/x/observer/keeper/ballot.go @@ -44,7 +44,10 @@ func (k Keeper) GetBallotList(ctx sdk.Context, height int64) (val types.BallotLi store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.BallotListKey)) b := store.Get(types.BallotListKeyPrefix(height)) if b == nil { - return val, false + return types.BallotListForHeight{ + Height: height, + BallotsIndexList: nil, + }, false } k.cdc.MustUnmarshal(b, &val) return val, true diff --git a/x/observer/keeper/ballot_test.go b/x/observer/keeper/ballot_test.go index a5d2d0eafe..65d69821b6 100644 --- a/x/observer/keeper/ballot_test.go +++ b/x/observer/keeper/ballot_test.go @@ -5,6 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" + "github.com/zeta-chain/node/x/observer/keeper" keepertest "github.com/zeta-chain/node/testutil/keeper" "github.com/zeta-chain/node/testutil/sample" @@ -54,25 +55,49 @@ func TestKeeper_GetBallot(t *testing.T) { } func TestKeeper_GetBallotList(t *testing.T) { - k, ctx, _, _ := keepertest.ObserverKeeper(t) - identifier := sample.ZetaIndex(t) - b := &types.Ballot{ - Index: "", - BallotIdentifier: identifier, - VoterList: nil, - ObservationType: 0, - BallotThreshold: sdk.ZeroDec(), - BallotStatus: 0, - BallotCreationHeight: 1, - } - _, found := k.GetBallotList(ctx, 1) - require.False(t, found) + t.Run("get existing ballot list", func(t *testing.T) { + k, ctx, _, _ := keepertest.ObserverKeeper(t) + identifier := sample.ZetaIndex(t) + b := &types.Ballot{ + Index: "", + BallotIdentifier: identifier, + VoterList: nil, + ObservationType: 0, + BallotThreshold: sdk.ZeroDec(), + BallotStatus: 0, + BallotCreationHeight: 1, + } + _, found := k.GetBallotList(ctx, 1) + require.False(t, found) + + k.AddBallotToList(ctx, *b) + list, found := k.GetBallotList(ctx, 1) + require.True(t, found) + require.Equal(t, 1, len(list.BallotsIndexList)) + require.Equal(t, identifier, list.BallotsIndexList[0]) + }) + + t.Run("get non-existing ballot list", func(t *testing.T) { + k, ctx, _, _ := keepertest.ObserverKeeper(t) + identifier := sample.ZetaIndex(t) + b := &types.Ballot{ + Index: "", + BallotIdentifier: identifier, + VoterList: nil, + ObservationType: 0, + BallotThreshold: sdk.ZeroDec(), + BallotStatus: 0, + BallotCreationHeight: 1, + } + _, found := k.GetBallotList(ctx, 1) + require.False(t, found) + + k.AddBallotToList(ctx, *b) + list, found := k.GetBallotList(ctx, -10) + require.False(t, found) + require.Nil(t, list.BallotsIndexList) + }) - k.AddBallotToList(ctx, *b) - list, found := k.GetBallotList(ctx, 1) - require.True(t, found) - require.Equal(t, 1, len(list.BallotsIndexList)) - require.Equal(t, identifier, list.BallotsIndexList[0]) } func TestKeeper_GetMaturedBallots(t *testing.T) { @@ -308,3 +333,44 @@ func TestKeeper_ClearMaturedBallots(t *testing.T) { require.Equal(t, numberOfBallots, eventCount) }) } + +func TestGetMaturedBallotHeight(t *testing.T) { + tt := []struct { + name string + currentHeight int64 + maturityBlocks int64 + expectedHeight int64 + }{ + { + name: "maturity blocks is 0", + currentHeight: 10, + maturityBlocks: 0, + expectedHeight: 10, + }, + { + name: "maturity blocks is same as current height", + currentHeight: 10, + maturityBlocks: 10, + expectedHeight: 0, + }, + { + name: "maturity blocks is less than current height", + currentHeight: 10, + maturityBlocks: 5, + expectedHeight: 5, + }, + { + name: "maturity blocks is greater than current height", + currentHeight: 5, + maturityBlocks: 10, + expectedHeight: -5, + }, + } + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + _, ctx, _, _ := keepertest.ObserverKeeper(t) + ctx = ctx.WithBlockHeight(tc.currentHeight) + require.Equal(t, tc.expectedHeight, keeper.GetMaturedBallotHeight(ctx, tc.maturityBlocks)) + }) + } +} diff --git a/x/observer/keeper/events.go b/x/observer/keeper/events.go index 090b4ed41a..e8831a0fb9 100644 --- a/x/observer/keeper/events.go +++ b/x/observer/keeper/events.go @@ -1,6 +1,7 @@ package keeper import ( + "fmt" "strconv" types2 "github.com/coinbase/rosetta-sdk-go/types" @@ -22,11 +23,17 @@ func EmitEventBallotCreated(ctx sdk.Context, ballot types.Ballot, observationHas } func EmitEventBallotDeleted(ctx sdk.Context, ballot types.Ballot) { - err := ctx.EventManager().EmitTypedEvent(&types.EventBallotDeleted{ + var voterList []types.VoterList + voterList, err := ballot.GenerateVoterList() + if err != nil { + ctx.Logger(). + Error(fmt.Sprintf("failed to generate voter list for ballot %s", ballot.BallotIdentifier), err.Error()) + } + err = ctx.EventManager().EmitTypedEvent(&types.EventBallotDeleted{ MsgTypeUrl: "zetachain.zetacore.observer.internal.BallotDeleted", BallotIdentifier: ballot.BallotIdentifier, BallotType: ballot.ObservationType.String(), - Voters: ballot.GenerateVoterList(), + Voters: voterList, }) if err != nil { ctx.Logger().Error("failed to emit EventBallotDeleted : %s", err.Error()) diff --git a/x/observer/keeper/events_test.go b/x/observer/keeper/events_test.go index 2fcda72609..f0657664d3 100644 --- a/x/observer/keeper/events_test.go +++ b/x/observer/keeper/events_test.go @@ -2,8 +2,10 @@ package keeper_test import ( "fmt" + "strings" "testing" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" keepertest "github.com/zeta-chain/node/testutil/keeper" "github.com/zeta-chain/node/testutil/sample" @@ -18,13 +20,15 @@ func TestEmitEventBallotDeleted(t *testing.T) { ballotType types.ObservationType voters []string voteType []types.VoteType + expectErr bool }{ { - name: "successfull votes only", + name: "successful votes only", ballotIdentifier: sample.ZetaIndex(t), ballotType: types.ObservationType_InboundTx, voters: []string{"voter1", "voter2"}, voteType: []types.VoteType{types.VoteType_SuccessObservation, types.VoteType_SuccessObservation}, + expectErr: false, }, { @@ -33,6 +37,16 @@ func TestEmitEventBallotDeleted(t *testing.T) { ballotType: types.ObservationType_InboundTx, voters: []string{"voter1", "voter2"}, voteType: []types.VoteType{types.VoteType_FailureObservation, types.VoteType_FailureObservation}, + expectErr: false, + }, + + { + name: "invalid voter list", + ballotIdentifier: sample.ZetaIndex(t), + ballotType: types.ObservationType_InboundTx, + voters: []string{"voter1", "voter2"}, + voteType: []types.VoteType{types.VoteType_FailureObservation}, + expectErr: true, }, } for _, tc := range tt { @@ -45,32 +59,40 @@ func TestEmitEventBallotDeleted(t *testing.T) { Votes: tc.voteType, } keeper.EmitEventBallotDeleted(ctx, ballot) - for _, event := range ctx.EventManager().Events() { - for _, attr := range event.Attributes { - if attr.Key == "ballot_identifier" { - require.Equal(t, tc.ballotIdentifier, RemoveQuotes(attr.Value)) - } - if attr.Key == "ballot_type" { - require.Equal(t, tc.ballotType.String(), RemoveQuotes(attr.Value)) - } - if attr.Key == "voters" { - expectedString := "" - for _, voter := range ballot.GenerateVoterList() { - st := fmt.Sprintf( - "{\"voter_address\":\"%s\",\"vote_type\":\"%s\"}", - voter.VoterAddress, - voter.VoteType, - ) - expectedString += st - expectedString += "," - } - expectedString = expectedString[:len(expectedString)-1] - require.Equal(t, expectedString, RemoveQuotes(attr.Value)) + checkEventAttributes(t, ctx, ballot, tc.expectErr) + }) + } +} + +func checkEventAttributes(t *testing.T, ctx sdk.Context, ballot types.Ballot, expectErr bool) { + for _, event := range ctx.EventManager().Events() { + for _, attr := range event.Attributes { + if attr.Key == "ballot_identifier" { + require.Equal(t, ballot.BallotIdentifier, RemoveQuotes(attr.Value)) + } + if attr.Key == "ballot_type" { + require.Equal(t, ballot.ObservationType.String(), RemoveQuotes(attr.Value)) + } + if attr.Key == "voters" { + expectedString := "" + list, err := ballot.GenerateVoterList() + if !expectErr { + require.NoError(t, err) + var voterStrings []string + for _, voter := range list { + voterStrings = append(voterStrings, fmt.Sprintf( + "{\"voter_address\":\"%s\",\"vote_type\":\"%s\"}", + voter.VoterAddress, + voter.VoteType, + )) } + expectedString = strings.Join(voterStrings, ",") + } else { + require.ErrorIs(t, err, types.ErrInvalidVoterList) } + require.Equal(t, expectedString, RemoveQuotes(attr.Value)) } - - }) + } } } diff --git a/x/observer/keeper/grpc_query_ballot.go b/x/observer/keeper/grpc_query_ballot.go index 85d76cdc21..a36c37d136 100644 --- a/x/observer/keeper/grpc_query_ballot.go +++ b/x/observer/keeper/grpc_query_ballot.go @@ -40,10 +40,14 @@ func (k Keeper) BallotByIdentifier( if !found { return nil, status.Error(codes.NotFound, "not found ballot") } + voterList, err := ballot.GenerateVoterList() + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } return &types.QueryBallotByIdentifierResponse{ BallotIdentifier: ballot.BallotIdentifier, - Voters: ballot.GenerateVoterList(), + Voters: voterList, ObservationType: ballot.ObservationType, BallotStatus: ballot.BallotStatus, }, nil diff --git a/x/observer/types/ballot.go b/x/observer/types/ballot.go index 967a5d5749..06501ebd9b 100644 --- a/x/observer/types/ballot.go +++ b/x/observer/types/ballot.go @@ -116,15 +116,21 @@ func (m Ballot) BuildRewardsDistribution(rewardsMap map[string]int64) int64 { return totalRewardUnits } -func (m Ballot) GenerateVoterList() []VoterList { +// GenerateVoterList generates a list of voters from the `VoterList` and `Votes` fields +// This is used for queries and events and not persisted to the store +func (m Ballot) GenerateVoterList() ([]VoterList, error) { + if len(m.VoterList) != len(m.Votes) { + return nil, ErrInvalidVoterList + } + votersList := make([]VoterList, len(m.VoterList)) - for i, voterAddress := range m.VoterList { + for i := range m.VoterList { voter := VoterList{ - VoterAddress: voterAddress, - VoteType: m.Votes[m.GetVoterIndex(voterAddress)], + VoterAddress: m.VoterList[i], + VoteType: m.Votes[i], } votersList[i] = voter } - return votersList + return votersList, nil } diff --git a/x/observer/types/ballot_test.go b/x/observer/types/ballot_test.go index 5cba1713ab..7127074605 100644 --- a/x/observer/types/ballot_test.go +++ b/x/observer/types/ballot_test.go @@ -485,6 +485,7 @@ func TestBallot_GenerateVoterList(t *testing.T) { voters []string votes []VoteType expectedVoterList []VoterList + err require.ErrorAssertionFunc }{ { name: "Success observation", @@ -513,6 +514,7 @@ func TestBallot_GenerateVoterList(t *testing.T) { VoteType: VoteType_SuccessObservation, }, }, + err: require.NoError, }, { @@ -542,6 +544,7 @@ func TestBallot_GenerateVoterList(t *testing.T) { VoteType: VoteType_FailureObservation, }, }, + err: require.NoError, }, { @@ -571,6 +574,22 @@ func TestBallot_GenerateVoterList(t *testing.T) { VoteType: VoteType_SuccessObservation, }, }, + err: require.NoError, + }, + + { + name: "voterList and votes length mismatch", + voters: []string{"Observer1", "Observer2", "Observer3", "Observer4"}, + votes: []VoteType{ + VoteType_FailureObservation, + VoteType_FailureObservation, + VoteType_SuccessObservation, + }, + expectedVoterList: nil, + err: func(t require.TestingT, err error, i ...interface{}) { + require.Error(t, err) + require.Equal(t, err, ErrInvalidVoterList) + }, }, } for _, test := range tt { @@ -579,7 +598,8 @@ func TestBallot_GenerateVoterList(t *testing.T) { VoterList: test.voters, Votes: test.votes, } - voterList := ballot.GenerateVoterList() + voterList, err := ballot.GenerateVoterList() + test.err(t, err) require.Equal(t, test.expectedVoterList, voterList) }) } diff --git a/x/observer/types/errors.go b/x/observer/types/errors.go index 218521f242..0cd82caf15 100644 --- a/x/observer/types/errors.go +++ b/x/observer/types/errors.go @@ -52,4 +52,6 @@ var ( ErrDuplicateObserver = errorsmod.Register(ModuleName, 1135, "observer already exists") ErrObserverNotFound = errorsmod.Register(ModuleName, 1136, "observer not found") ErrInvalidObserverAddress = errorsmod.Register(ModuleName, 1137, "invalid observer address") + + ErrInvalidVoterList = errorsmod.Register(ModuleName, 1138, "invalid voter list for ballot") ) From afaa312cdc815babff7ec59bc90cca36b45f0d0d Mon Sep 17 00:00:00 2001 From: Tanmay Date: Mon, 16 Sep 2024 21:29:48 +0530 Subject: [PATCH 05/16] refactor names for ballot list functions --- x/emissions/abci_test.go | 4 ++-- x/observer/keeper/ballot.go | 10 +++++----- x/observer/keeper/ballot_test.go | 32 ++++++++++++++++---------------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/x/emissions/abci_test.go b/x/emissions/abci_test.go index 95bd9b45ac..a99a40ce79 100644 --- a/x/emissions/abci_test.go +++ b/x/emissions/abci_test.go @@ -252,7 +252,7 @@ func TestBeginBlocker(t *testing.T) { require.True(t, blockRewards.TruncateInt().GT(distributedRewards)) require.Len(t, zk.ObserverKeeper.GetAllBallots(ctx), len(ballotList)) - _, found = zk.ObserverKeeper.GetBallotList(ctx, 0) + _, found = zk.ObserverKeeper.GetBallotListForHeight(ctx, 0) require.True(t, found) // Act @@ -299,7 +299,7 @@ func TestBeginBlocker(t *testing.T) { // 2 . Assert ballots and ballot list are deleted on maturity require.Len(t, zk.ObserverKeeper.GetAllBallots(ctx), 0) - _, found = zk.ObserverKeeper.GetBallotList(ctx, 0) + _, found = zk.ObserverKeeper.GetBallotListForHeight(ctx, 0) require.False(t, found) //3. Assert amounts in undistributed pools diff --git a/x/observer/keeper/ballot.go b/x/observer/keeper/ballot.go index d35d9c337a..f46262e783 100644 --- a/x/observer/keeper/ballot.go +++ b/x/observer/keeper/ballot.go @@ -25,7 +25,7 @@ func (k Keeper) DeleteBallot(ctx sdk.Context, index string) { store.Delete([]byte(index)) } -func (k Keeper) DeleteBallotList(ctx sdk.Context, height int64) { +func (k Keeper) DeleteBallotListForHeight(ctx sdk.Context, height int64) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.BallotListKey)) store.Delete(types.BallotListKeyPrefix(height)) } @@ -40,7 +40,7 @@ func (k Keeper) GetBallot(ctx sdk.Context, index string) (val types.Ballot, foun return val, true } -func (k Keeper) GetBallotList(ctx sdk.Context, height int64) (val types.BallotListForHeight, found bool) { +func (k Keeper) GetBallotListForHeight(ctx sdk.Context, height int64) (val types.BallotListForHeight, found bool) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.BallotListKey)) b := store.Get(types.BallotListKeyPrefix(height)) if b == nil { @@ -54,7 +54,7 @@ func (k Keeper) GetBallotList(ctx sdk.Context, height int64) (val types.BallotLi } func (k Keeper) GetMaturedBallots(ctx sdk.Context, maturityBlocks int64) (val types.BallotListForHeight, found bool) { - return k.GetBallotList(ctx, GetMaturedBallotHeight(ctx, maturityBlocks)) + return k.GetBallotListForHeight(ctx, GetMaturedBallotHeight(ctx, maturityBlocks)) } func (k Keeper) GetAllBallots(ctx sdk.Context) (voters []*types.Ballot) { @@ -71,7 +71,7 @@ func (k Keeper) GetAllBallots(ctx sdk.Context) (voters []*types.Ballot) { // AddBallotToList adds a ballot to the list of ballots for a given height. func (k Keeper) AddBallotToList(ctx sdk.Context, ballot types.Ballot) { - list, found := k.GetBallotList(ctx, ballot.BallotCreationHeight) + list, found := k.GetBallotListForHeight(ctx, ballot.BallotCreationHeight) if !found { list = types.BallotListForHeight{Height: ballot.BallotCreationHeight, BallotsIndexList: []string{}} } @@ -86,7 +86,7 @@ func (k Keeper) ClearMaturedBallots(ctx sdk.Context, ballots []types.Ballot, mat k.DeleteBallot(ctx, ballot.BallotIdentifier) EmitEventBallotDeleted(ctx, ballot) } - k.DeleteBallotList(ctx, GetMaturedBallotHeight(ctx, maturityBlocks)) + k.DeleteBallotListForHeight(ctx, GetMaturedBallotHeight(ctx, maturityBlocks)) return } diff --git a/x/observer/keeper/ballot_test.go b/x/observer/keeper/ballot_test.go index 65d69821b6..34a09f22ef 100644 --- a/x/observer/keeper/ballot_test.go +++ b/x/observer/keeper/ballot_test.go @@ -67,11 +67,11 @@ func TestKeeper_GetBallotList(t *testing.T) { BallotStatus: 0, BallotCreationHeight: 1, } - _, found := k.GetBallotList(ctx, 1) + _, found := k.GetBallotListForHeight(ctx, 1) require.False(t, found) k.AddBallotToList(ctx, *b) - list, found := k.GetBallotList(ctx, 1) + list, found := k.GetBallotListForHeight(ctx, 1) require.True(t, found) require.Equal(t, 1, len(list.BallotsIndexList)) require.Equal(t, identifier, list.BallotsIndexList[0]) @@ -89,11 +89,11 @@ func TestKeeper_GetBallotList(t *testing.T) { BallotStatus: 0, BallotCreationHeight: 1, } - _, found := k.GetBallotList(ctx, 1) + _, found := k.GetBallotListForHeight(ctx, 1) require.False(t, found) k.AddBallotToList(ctx, *b) - list, found := k.GetBallotList(ctx, -10) + list, found := k.GetBallotListForHeight(ctx, -10) require.False(t, found) require.Nil(t, list.BallotsIndexList) }) @@ -199,14 +199,14 @@ func TestKeeper_DeleteBallotList(t *testing.T) { }) } - _, found := k.GetBallotList(ctx, 1) + _, found := k.GetBallotListForHeight(ctx, 1) require.True(t, found) //Act - k.DeleteBallotList(ctx, 1) + k.DeleteBallotListForHeight(ctx, 1) //Assert - _, found = k.GetBallotList(ctx, 1) + _, found = k.GetBallotListForHeight(ctx, 1) require.False(t, found) }) @@ -221,14 +221,14 @@ func TestKeeper_DeleteBallotList(t *testing.T) { }) } - _, found := k.GetBallotList(ctx, 1) + _, found := k.GetBallotListForHeight(ctx, 1) require.True(t, found) //Act - k.DeleteBallotList(ctx, 2) + k.DeleteBallotListForHeight(ctx, 2) //Assert - _, found = k.GetBallotList(ctx, 1) + _, found = k.GetBallotListForHeight(ctx, 1) require.True(t, found) }) } @@ -248,7 +248,7 @@ func TestKeeper_ClearMaturedBallots(t *testing.T) { k.SetBallot(ctx, &b) ballots[i] = b } - _, found := k.GetBallotList(ctx, 1) + _, found := k.GetBallotListForHeight(ctx, 1) require.True(t, found) require.Equal(t, numberOfBallots, len(k.GetAllBallots(ctx))) @@ -260,7 +260,7 @@ func TestKeeper_ClearMaturedBallots(t *testing.T) { _, found = k.GetBallot(ctx, b.BallotIdentifier) require.False(t, found) } - _, found = k.GetBallotList(ctx, 0) + _, found = k.GetBallotListForHeight(ctx, 0) require.False(t, found) eventCount := 0 for _, event := range ctx.EventManager().Events() { @@ -284,7 +284,7 @@ func TestKeeper_ClearMaturedBallots(t *testing.T) { k.AddBallotToList(ctx, b) ballots[i] = b } - _, found := k.GetBallotList(ctx, 1) + _, found := k.GetBallotListForHeight(ctx, 1) require.True(t, found) require.Equal(t, 0, len(k.GetAllBallots(ctx))) @@ -292,7 +292,7 @@ func TestKeeper_ClearMaturedBallots(t *testing.T) { k.ClearMaturedBallots(ctx, []types.Ballot{}, 0) //Assert - _, found = k.GetBallotList(ctx, 1) + _, found = k.GetBallotListForHeight(ctx, 1) require.False(t, found) require.Equal(t, 0, len(k.GetAllBallots(ctx))) }) @@ -311,7 +311,7 @@ func TestKeeper_ClearMaturedBallots(t *testing.T) { ballots[i] = b } require.Equal(t, numberOfBallots, len(k.GetAllBallots(ctx))) - _, found := k.GetBallotList(ctx, 1) + _, found := k.GetBallotListForHeight(ctx, 1) require.False(t, found) //Act @@ -322,7 +322,7 @@ func TestKeeper_ClearMaturedBallots(t *testing.T) { _, found := k.GetBallot(ctx, b.BallotIdentifier) require.False(t, found) } - _, found = k.GetBallotList(ctx, 1) + _, found = k.GetBallotListForHeight(ctx, 1) require.False(t, found) eventCount := 0 for _, event := range ctx.EventManager().Events() { From bf3c438ef9670acec9bafc312da221efdb8e6776 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Mon, 23 Sep 2024 09:52:03 +0530 Subject: [PATCH 06/16] refactor ClearMaturedBallots to ClearMaturedBallotsAndBallotList --- testutil/keeper/mocks/emissions/observer.go | 4 ++-- x/emissions/abci.go | 2 +- x/emissions/types/expected_keepers.go | 2 +- x/observer/keeper/ballot.go | 4 ++-- x/observer/keeper/ballot_test.go | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/testutil/keeper/mocks/emissions/observer.go b/testutil/keeper/mocks/emissions/observer.go index fd50cf5fbe..dfd6012751 100644 --- a/testutil/keeper/mocks/emissions/observer.go +++ b/testutil/keeper/mocks/emissions/observer.go @@ -15,8 +15,8 @@ type EmissionObserverKeeper struct { mock.Mock } -// ClearMaturedBallots provides a mock function with given fields: ctx, ballots, maturityBlocks -func (_m *EmissionObserverKeeper) ClearMaturedBallots(ctx types.Context, ballots []observertypes.Ballot, maturityBlocks int64) { +// ClearMaturedBallotsAndBallotList provides a mock function with given fields: ctx, ballots, maturityBlocks +func (_m *EmissionObserverKeeper) ClearMaturedBallotsAndBallotList(ctx types.Context, ballots []observertypes.Ballot, maturityBlocks int64) { _m.Called(ctx, ballots, maturityBlocks) } diff --git a/x/emissions/abci.go b/x/emissions/abci.go index 4ab0e4da24..b4ddf672ed 100644 --- a/x/emissions/abci.go +++ b/x/emissions/abci.go @@ -166,7 +166,7 @@ func DistributeObserverRewards( types.EmitObserverEmissions(ctx, finalDistributionList) // Clear the matured ballots - keeper.GetObserverKeeper().ClearMaturedBallots(ctx, ballots, params.BallotMaturityBlocks) + keeper.GetObserverKeeper().ClearMaturedBallotsAndBallotList(ctx, ballots, params.BallotMaturityBlocks) return nil } diff --git a/x/emissions/types/expected_keepers.go b/x/emissions/types/expected_keepers.go index d834dc0f1a..df7b404cf0 100644 --- a/x/emissions/types/expected_keepers.go +++ b/x/emissions/types/expected_keepers.go @@ -16,7 +16,7 @@ type AccountKeeper interface { type ObserverKeeper interface { GetBallot(ctx sdk.Context, index string) (val observertypes.Ballot, found bool) GetMaturedBallots(ctx sdk.Context, maturityBlocks int64) (val observertypes.BallotListForHeight, found bool) - ClearMaturedBallots(ctx sdk.Context, ballots []observertypes.Ballot, maturityBlocks int64) + ClearMaturedBallotsAndBallotList(ctx sdk.Context, ballots []observertypes.Ballot, maturityBlocks int64) } // BankKeeper defines the expected interface needed to retrieve account balances. diff --git a/x/observer/keeper/ballot.go b/x/observer/keeper/ballot.go index f46262e783..d756003644 100644 --- a/x/observer/keeper/ballot.go +++ b/x/observer/keeper/ballot.go @@ -79,9 +79,9 @@ func (k Keeper) AddBallotToList(ctx sdk.Context, ballot types.Ballot) { k.SetBallotList(ctx, &list) } -// ClearMaturedBallots deletes all matured ballots and the list of ballots for a given height. +// ClearMaturedBallotsAndBallotList deletes all matured ballots and the list of ballots for a given height. // It also emits an event for each ballot deleted. -func (k Keeper) ClearMaturedBallots(ctx sdk.Context, ballots []types.Ballot, maturityBlocks int64) { +func (k Keeper) ClearMaturedBallotsAndBallotList(ctx sdk.Context, ballots []types.Ballot, maturityBlocks int64) { for _, ballot := range ballots { k.DeleteBallot(ctx, ballot.BallotIdentifier) EmitEventBallotDeleted(ctx, ballot) diff --git a/x/observer/keeper/ballot_test.go b/x/observer/keeper/ballot_test.go index 34a09f22ef..6de6b402f8 100644 --- a/x/observer/keeper/ballot_test.go +++ b/x/observer/keeper/ballot_test.go @@ -253,7 +253,7 @@ func TestKeeper_ClearMaturedBallots(t *testing.T) { require.Equal(t, numberOfBallots, len(k.GetAllBallots(ctx))) //Act - k.ClearMaturedBallots(ctx, ballots, 0) + k.ClearMaturedBallotsAndBallotList(ctx, ballots, 0) //Assert for _, b := range ballots { @@ -289,7 +289,7 @@ func TestKeeper_ClearMaturedBallots(t *testing.T) { require.Equal(t, 0, len(k.GetAllBallots(ctx))) //Act - k.ClearMaturedBallots(ctx, []types.Ballot{}, 0) + k.ClearMaturedBallotsAndBallotList(ctx, []types.Ballot{}, 0) //Assert _, found = k.GetBallotListForHeight(ctx, 1) @@ -315,7 +315,7 @@ func TestKeeper_ClearMaturedBallots(t *testing.T) { require.False(t, found) //Act - k.ClearMaturedBallots(ctx, ballots, 0) + k.ClearMaturedBallotsAndBallotList(ctx, ballots, 0) //Assert for _, b := range ballots { From fbf277bed10f088e0a035ea5d899148baf790184 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Thu, 26 Sep 2024 23:57:21 +0530 Subject: [PATCH 07/16] make getMaturedBallotHeight private --- x/observer/keeper/ballot.go | 8 +++++--- x/observer/keeper/ballot_test.go | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/x/observer/keeper/ballot.go b/x/observer/keeper/ballot.go index d756003644..ef37a96b70 100644 --- a/x/observer/keeper/ballot.go +++ b/x/observer/keeper/ballot.go @@ -7,6 +7,8 @@ import ( "github.com/zeta-chain/node/x/observer/types" ) +var GetMaturedBallotHeightFunc = getMaturedBallotHeight + func (k Keeper) SetBallot(ctx sdk.Context, ballot *types.Ballot) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.VoterKey)) ballot.Index = ballot.BallotIdentifier @@ -54,7 +56,7 @@ func (k Keeper) GetBallotListForHeight(ctx sdk.Context, height int64) (val types } func (k Keeper) GetMaturedBallots(ctx sdk.Context, maturityBlocks int64) (val types.BallotListForHeight, found bool) { - return k.GetBallotListForHeight(ctx, GetMaturedBallotHeight(ctx, maturityBlocks)) + return k.GetBallotListForHeight(ctx, getMaturedBallotHeight(ctx, maturityBlocks)) } func (k Keeper) GetAllBallots(ctx sdk.Context) (voters []*types.Ballot) { @@ -86,10 +88,10 @@ func (k Keeper) ClearMaturedBallotsAndBallotList(ctx sdk.Context, ballots []type k.DeleteBallot(ctx, ballot.BallotIdentifier) EmitEventBallotDeleted(ctx, ballot) } - k.DeleteBallotListForHeight(ctx, GetMaturedBallotHeight(ctx, maturityBlocks)) + k.DeleteBallotListForHeight(ctx, getMaturedBallotHeight(ctx, maturityBlocks)) return } -func GetMaturedBallotHeight(ctx sdk.Context, maturityBlocks int64) int64 { +func getMaturedBallotHeight(ctx sdk.Context, maturityBlocks int64) int64 { return ctx.BlockHeight() - maturityBlocks } diff --git a/x/observer/keeper/ballot_test.go b/x/observer/keeper/ballot_test.go index 6de6b402f8..ad39fd5eb7 100644 --- a/x/observer/keeper/ballot_test.go +++ b/x/observer/keeper/ballot_test.go @@ -370,7 +370,7 @@ func TestGetMaturedBallotHeight(t *testing.T) { t.Run(tc.name, func(t *testing.T) { _, ctx, _, _ := keepertest.ObserverKeeper(t) ctx = ctx.WithBlockHeight(tc.currentHeight) - require.Equal(t, tc.expectedHeight, keeper.GetMaturedBallotHeight(ctx, tc.maturityBlocks)) + require.Equal(t, tc.expectedHeight, keeper.GetMaturedBallotHeightFunc(ctx, tc.maturityBlocks)) }) } } From 8be7f3f5ec19b2a0918911c569a12c49884e0fde Mon Sep 17 00:00:00 2001 From: Tanmay Date: Thu, 26 Sep 2024 23:58:53 +0530 Subject: [PATCH 08/16] make getMaturedBallotHeight private --- x/observer/keeper/ballot.go | 1 + 1 file changed, 1 insertion(+) diff --git a/x/observer/keeper/ballot.go b/x/observer/keeper/ballot.go index ef37a96b70..de9ea8d549 100644 --- a/x/observer/keeper/ballot.go +++ b/x/observer/keeper/ballot.go @@ -92,6 +92,7 @@ func (k Keeper) ClearMaturedBallotsAndBallotList(ctx sdk.Context, ballots []type return } +// getMaturedBallotHeight returns the height at which a ballot is considered matured. func getMaturedBallotHeight(ctx sdk.Context, maturityBlocks int64) int64 { return ctx.BlockHeight() - maturityBlocks } From 12f9baa1b9643f196dccd094a814b5973311a696 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Tue, 1 Oct 2024 11:55:47 +0530 Subject: [PATCH 09/16] add migration script to delete ballots and tests with mainnet data --- testutil/testdata/testdata.go | 23 ++++++++++++ x/observer/migrations/v9/migrate.go | 37 +++++++++++++++++++ x/observer/migrations/v9/migrate_test.go | 47 ++++++++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 x/observer/migrations/v9/migrate.go create mode 100644 x/observer/migrations/v9/migrate_test.go diff --git a/testutil/testdata/testdata.go b/testutil/testdata/testdata.go index 50f08b1451..cfc9c85ebb 100644 --- a/testutil/testdata/testdata.go +++ b/testutil/testdata/testdata.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/require" + observertypes "github.com/zeta-chain/node/x/observer/types" ) const ( @@ -28,6 +29,28 @@ var ethFiles embed.FS //go:embed * var testDataFiles embed.FS +//go:embed * observer/* +var ObserverFiles embed.FS + +type Ballots struct { + Ballots []*observertypes.Ballot `json:"Ballots"` +} + +// ReadMainnetBallots reads the mainnet ballots from a file. This was last updated on 09-30-2024. +func ReadMainnetBallots(t *testing.T) []*observertypes.Ballot { + + file, err := ObserverFiles.Open("observer/ballots.json") + require.NoError(t, err) + defer file.Close() + + // Decode the JSON into the data struct + var b Ballots + err = json.NewDecoder(file).Decode(&b) + require.NoError(t, err) + + return b.Ballots +} + // ReadEthHeader reads a header from a file. // TODO: centralize test data // https://github.com/zeta-chain/node/issues/1874 diff --git a/x/observer/migrations/v9/migrate.go b/x/observer/migrations/v9/migrate.go new file mode 100644 index 0000000000..736bbd99ff --- /dev/null +++ b/x/observer/migrations/v9/migrate.go @@ -0,0 +1,37 @@ +package v9 + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/zeta-chain/node/x/observer/types" +) + +type observerKeeper interface { + GetBallotListForHeight(ctx sdk.Context, height int64) (val types.BallotListForHeight, found bool) + DeleteBallot(ctx sdk.Context, index string) + DeleteBallotListForHeight(ctx sdk.Context, height int64) +} + +// MigrateStore migrates the x/observer module state from the consensus version 7 to 8 +// It updates the indexing for chain nonces object to use chain ID instead of chain name +func MigrateStore(ctx sdk.Context, observerKeeper observerKeeper) error { + currentHeight := ctx.BlockHeight() + // Maturity blocks is a parameter in the emissions module + maturityBlocks := int64(100) + if currentHeight < maturityBlocks { + return nil + } + maturedHeight := currentHeight - maturityBlocks + + for i := maturedHeight; i > 0; i-- { + ballotList, found := observerKeeper.GetBallotListForHeight(ctx, i) + if !found { + continue + } + for _, ballotIndex := range ballotList.BallotsIndexList { + observerKeeper.DeleteBallot(ctx, ballotIndex) + } + observerKeeper.DeleteBallotListForHeight(ctx, i) + } + return nil +} diff --git a/x/observer/migrations/v9/migrate_test.go b/x/observer/migrations/v9/migrate_test.go new file mode 100644 index 0000000000..f179237952 --- /dev/null +++ b/x/observer/migrations/v9/migrate_test.go @@ -0,0 +1,47 @@ +package v9_test + +import ( + "testing" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + keepertest "github.com/zeta-chain/node/testutil/keeper" + "github.com/zeta-chain/node/testutil/testdata" + observerkeeper "github.com/zeta-chain/node/x/observer/keeper" + v9 "github.com/zeta-chain/node/x/observer/migrations/v9" + "github.com/zeta-chain/node/x/observer/types" +) + +func TestMigrateStore(t *testing.T) { + k, ctx, _, _ := keepertest.ObserverKeeper(t) + SetupMainnetData(t, k, ctx) + ctx = ctx.WithBlockHeight(5073825) + err := v9.MigrateStore(ctx, k) + require.NoError(t, err) + + start := time.Now() + ballots := k.GetAllBallots(ctx) + elapsed := time.Since(start) + + // Elapsed should be less than 1 second + require.Less(t, elapsed.Seconds(), 1) + require.Len(t, ballots, 0) +} + +func SetupMainnetData(t *testing.T, k *observerkeeper.Keeper, ctx sdk.Context) { + b := testdata.ReadMainnetBallots(t) + ballotsList := map[int64][]string{} + + for _, ballot := range b { + k.SetBallot(ctx, ballot) + ballotsList[ballot.BallotCreationHeight] = append(ballotsList[ballot.BallotCreationHeight], ballot.BallotIdentifier) + } + + for height, ballotList := range ballotsList { + k.SetBallotList(ctx, &types.BallotListForHeight{ + Height: height, + BallotsIndexList: ballotList, + }) + } +} From 68bd73ad9685f1eae0ff4dd926102df0d1f2edb4 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Thu, 19 Dec 2024 17:01:30 -0500 Subject: [PATCH 10/16] add test for migration --- testutil/keeper/mocks/emissions/observer.go | 6 +- testutil/testdata/testdata.go | 23 --- x/emissions/abci.go | 82 ++++++---- x/emissions/types/expected_keepers.go | 2 +- x/observer/keeper/ballot.go | 23 ++- x/observer/keeper/ballot_test.go | 25 ++- x/observer/keeper/migrator.go | 6 + x/observer/migrations/v9/migrate.go | 12 +- x/observer/migrations/v9/migrate_test.go | 169 +++++++++++++++----- 9 files changed, 232 insertions(+), 116 deletions(-) diff --git a/testutil/keeper/mocks/emissions/observer.go b/testutil/keeper/mocks/emissions/observer.go index dfd6012751..18c95ae92c 100644 --- a/testutil/keeper/mocks/emissions/observer.go +++ b/testutil/keeper/mocks/emissions/observer.go @@ -15,9 +15,9 @@ type EmissionObserverKeeper struct { mock.Mock } -// ClearMaturedBallotsAndBallotList provides a mock function with given fields: ctx, ballots, maturityBlocks -func (_m *EmissionObserverKeeper) ClearMaturedBallotsAndBallotList(ctx types.Context, ballots []observertypes.Ballot, maturityBlocks int64) { - _m.Called(ctx, ballots, maturityBlocks) +// ClearMaturedBallotsAndBallotList provides a mock function with given fields: ctx, maturityBlocks +func (_m *EmissionObserverKeeper) ClearMaturedBallotsAndBallotList(ctx types.Context, maturityBlocks int64) { + _m.Called(ctx, maturityBlocks) } // GetBallot provides a mock function with given fields: ctx, index diff --git a/testutil/testdata/testdata.go b/testutil/testdata/testdata.go index cfc9c85ebb..50f08b1451 100644 --- a/testutil/testdata/testdata.go +++ b/testutil/testdata/testdata.go @@ -8,7 +8,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/require" - observertypes "github.com/zeta-chain/node/x/observer/types" ) const ( @@ -29,28 +28,6 @@ var ethFiles embed.FS //go:embed * var testDataFiles embed.FS -//go:embed * observer/* -var ObserverFiles embed.FS - -type Ballots struct { - Ballots []*observertypes.Ballot `json:"Ballots"` -} - -// ReadMainnetBallots reads the mainnet ballots from a file. This was last updated on 09-30-2024. -func ReadMainnetBallots(t *testing.T) []*observertypes.Ballot { - - file, err := ObserverFiles.Open("observer/ballots.json") - require.NoError(t, err) - defer file.Close() - - // Decode the JSON into the data struct - var b Ballots - err = json.NewDecoder(file).Decode(&b) - require.NoError(t, err) - - return b.Ballots -} - // ReadEthHeader reads a header from a file. // TODO: centralize test data // https://github.com/zeta-chain/node/issues/1874 diff --git a/x/emissions/abci.go b/x/emissions/abci.go index ddc3d8e923..6ae996b4f4 100644 --- a/x/emissions/abci.go +++ b/x/emissions/abci.go @@ -4,6 +4,7 @@ import ( "fmt" "sort" + sdkerrors "cosmossdk.io/errors" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" @@ -101,44 +102,80 @@ func DistributeObserverRewards( keeper keeper.Keeper, params types.Params, ) error { - slashAmount := params.ObserverSlashAmount - rewardsDistributer := map[string]int64{} - totalRewardsUnits := int64(0) + var ( + slashAmount = params.ObserverSlashAmount + maturityBlocks = params.BallotMaturityBlocks + + maturedBallots []string + ) + err := keeper.GetBankKeeper(). SendCoinsFromModuleToModule(ctx, types.ModuleName, types.UndistributedObserverRewardsPool, sdk.NewCoins(sdk.NewCoin(config.BaseDenom, amount))) if err != nil { - return err + return sdkerrors.Wrap(err, "Error while transferring funds to the undistributed pool") } - list, found := keeper.GetObserverKeeper().GetMaturedBallots(ctx, params.BallotMaturityBlocks) - ballotIdentifiers := []string{} + // Fetch the matured ballots for this block + list, found := keeper.GetObserverKeeper().GetMaturedBallots(ctx, maturityBlocks) if found { - ballotIdentifiers = list.BallotsIndexList + maturedBallots = list.BallotsIndexList } - // do not distribute rewards if no ballots are matured, the rewards can accumulate in the undistributed pool - if len(ballotIdentifiers) == 0 { + if len(maturedBallots) == 0 { return nil } - ballots := make([]observertypes.Ballot, 0, len(ballotIdentifiers)) - for _, ballotIdentifier := range ballotIdentifiers { + + // We have some matured ballots, we now need to process them + // Processing Step 1: Distribute the rewards + // Final distribution list is the list of ObserverEmissions, which will be emitted as events + finalDistributionList := distributeRewardsForMaturedBallots(ctx, keeper, maturedBallots, amount, slashAmount) + + // Processing Step 2: Emit the observer emissions + types.EmitObserverEmissions(ctx, finalDistributionList) + + // Processing Step 3: Delete all matured ballots and the ballot list + keeper.GetObserverKeeper().ClearMaturedBallotsAndBallotList(ctx, params.BallotMaturityBlocks) + return nil +} + +// DistributeTSSRewards trasferes the allocated rewards to the Undistributed Tss Rewards Pool. +// This is done so that the reserves factor is properly calculated in the next block +func DistributeTSSRewards(ctx sdk.Context, amount sdk.Int, bankKeeper types.BankKeeper) error { + coin := sdk.NewCoins(sdk.NewCoin(config.BaseDenom, amount)) + return bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, types.UndistributedTSSRewardsPool, coin) +} + +func distributeRewardsForMaturedBallots( + ctx sdk.Context, + keeper keeper.Keeper, + maturedBallots []string, + amount sdkmath.Int, + slashAmount sdkmath.Int, +) []*types.ObserverEmission { + var ( + rewardsDistributeMap = map[string]int64{} + totalRewardsUnits = int64(0) + ) + ballots := make([]observertypes.Ballot, 0, len(maturedBallots)) + for _, ballotIdentifier := range maturedBallots { ballot, found := keeper.GetObserverKeeper().GetBallot(ctx, ballotIdentifier) if !found { continue } ballots = append(ballots, ballot) - totalRewardsUnits += ballot.BuildRewardsDistribution(rewardsDistributer) + totalRewardsUnits += ballot.BuildRewardsDistribution(rewardsDistributeMap) } rewardPerUnit := sdkmath.ZeroInt() if totalRewardsUnits > 0 && amount.IsPositive() { rewardPerUnit = amount.Quo(sdk.NewInt(totalRewardsUnits)) } ctx.Logger(). - Debug(fmt.Sprintf("Total Rewards Units : %d , rewards per Unit %s ,number of ballots :%d", totalRewardsUnits, rewardPerUnit.String(), len(ballotIdentifiers))) - sortedKeys := make([]string, 0, len(rewardsDistributer)) - for k := range rewardsDistributer { + Debug(fmt.Sprintf("Total Rewards Units : %d , rewards per Unit %s ,number of ballots :%d", totalRewardsUnits, rewardPerUnit.String(), len(maturedBallots))) + sortedKeys := make([]string, 0, len(rewardsDistributeMap)) + for k := range rewardsDistributeMap { sortedKeys = append(sortedKeys, k) } + sort.Strings(sortedKeys) var finalDistributionList []*types.ObserverEmission for _, key := range sortedKeys { @@ -149,7 +186,7 @@ func DistributeObserverRewards( } // observerRewardUnits can be negative if the observer has been slashed // an observers earn 1 unit for a correct vote, and -1 unit for an incorrect vote - observerRewardUnits := rewardsDistributer[key] + observerRewardUnits := rewardsDistributeMap[key] if observerRewardUnits == 0 { finalDistributionList = append(finalDistributionList, &types.ObserverEmission{ @@ -180,16 +217,5 @@ func DistributeObserverRewards( }) } } - types.EmitObserverEmissions(ctx, finalDistributionList) - - // Clear the matured ballots - keeper.GetObserverKeeper().ClearMaturedBallotsAndBallotList(ctx, ballots, params.BallotMaturityBlocks) - return nil -} - -// DistributeTSSRewards trasferes the allocated rewards to the Undistributed Tss Rewards Pool. -// This is done so that the reserves factor is properly calculated in the next block -func DistributeTSSRewards(ctx sdk.Context, amount sdk.Int, bankKeeper types.BankKeeper) error { - coin := sdk.NewCoins(sdk.NewCoin(config.BaseDenom, amount)) - return bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, types.UndistributedTSSRewardsPool, coin) + return finalDistributionList } diff --git a/x/emissions/types/expected_keepers.go b/x/emissions/types/expected_keepers.go index df7b404cf0..a0754a8870 100644 --- a/x/emissions/types/expected_keepers.go +++ b/x/emissions/types/expected_keepers.go @@ -16,7 +16,7 @@ type AccountKeeper interface { type ObserverKeeper interface { GetBallot(ctx sdk.Context, index string) (val observertypes.Ballot, found bool) GetMaturedBallots(ctx sdk.Context, maturityBlocks int64) (val observertypes.BallotListForHeight, found bool) - ClearMaturedBallotsAndBallotList(ctx sdk.Context, ballots []observertypes.Ballot, maturityBlocks int64) + ClearMaturedBallotsAndBallotList(ctx sdk.Context, maturityBlocks int64) } // BankKeeper defines the expected interface needed to retrieve account balances. diff --git a/x/observer/keeper/ballot.go b/x/observer/keeper/ballot.go index de9ea8d549..13a78a3f81 100644 --- a/x/observer/keeper/ballot.go +++ b/x/observer/keeper/ballot.go @@ -83,12 +83,27 @@ func (k Keeper) AddBallotToList(ctx sdk.Context, ballot types.Ballot) { // ClearMaturedBallotsAndBallotList deletes all matured ballots and the list of ballots for a given height. // It also emits an event for each ballot deleted. -func (k Keeper) ClearMaturedBallotsAndBallotList(ctx sdk.Context, ballots []types.Ballot, maturityBlocks int64) { - for _, ballot := range ballots { - k.DeleteBallot(ctx, ballot.BallotIdentifier) +func (k Keeper) ClearMaturedBallotsAndBallotList(ctx sdk.Context, maturityBlocks int64) { + maturedBallotsHeight := getMaturedBallotHeight(ctx, maturityBlocks) + + // Fetch all the matured ballots, return if no matured ballots are found + // For the current implementation, this should never happen as ClearMaturedBallotsAndBallotList is only called after the Distribution of the rewards, + // which means that there are matured ballots to be deleted + maturedBallots, found := k.GetBallotListForHeight(ctx, maturedBallotsHeight) + if !found { + return + } + // Delete all the matured ballots and emit an event for each ballot deleted + for _, ballotIndex := range maturedBallots.BallotsIndexList { + ballot, found := k.GetBallot(ctx, ballotIndex) + if !found { + continue + } + k.DeleteBallot(ctx, ballotIndex) EmitEventBallotDeleted(ctx, ballot) } - k.DeleteBallotListForHeight(ctx, getMaturedBallotHeight(ctx, maturityBlocks)) + // Delete the list of matured ballots + k.DeleteBallotListForHeight(ctx, maturedBallotsHeight) return } diff --git a/x/observer/keeper/ballot_test.go b/x/observer/keeper/ballot_test.go index ad39fd5eb7..6f8fa0ef0a 100644 --- a/x/observer/keeper/ballot_test.go +++ b/x/observer/keeper/ballot_test.go @@ -253,7 +253,7 @@ func TestKeeper_ClearMaturedBallots(t *testing.T) { require.Equal(t, numberOfBallots, len(k.GetAllBallots(ctx))) //Act - k.ClearMaturedBallotsAndBallotList(ctx, ballots, 0) + k.ClearMaturedBallotsAndBallotList(ctx, 0) //Assert for _, b := range ballots { @@ -289,7 +289,7 @@ func TestKeeper_ClearMaturedBallots(t *testing.T) { require.Equal(t, 0, len(k.GetAllBallots(ctx))) //Act - k.ClearMaturedBallotsAndBallotList(ctx, []types.Ballot{}, 0) + k.ClearMaturedBallotsAndBallotList(ctx, 0) //Assert _, found = k.GetBallotListForHeight(ctx, 1) @@ -297,7 +297,8 @@ func TestKeeper_ClearMaturedBallots(t *testing.T) { require.Equal(t, 0, len(k.GetAllBallots(ctx))) }) - t.Run("clear only ballots successfully if ballotList is not found", func(t *testing.T) { + t.Run("do nothing if ballot list for height is not found", func(t *testing.T) { + // Note this condition should never happen in production as the ballot list for height should always be set when saving a ballot to state //Arrange k, ctx, _, _ := keepertest.ObserverKeeper(t) numberOfBallots := 10 @@ -310,28 +311,20 @@ func TestKeeper_ClearMaturedBallots(t *testing.T) { k.SetBallot(ctx, &b) ballots[i] = b } - require.Equal(t, numberOfBallots, len(k.GetAllBallots(ctx))) _, found := k.GetBallotListForHeight(ctx, 1) require.False(t, found) + require.Equal(t, numberOfBallots, len(k.GetAllBallots(ctx))) //Act - k.ClearMaturedBallotsAndBallotList(ctx, ballots, 0) + k.ClearMaturedBallotsAndBallotList(ctx, 0) //Assert for _, b := range ballots { - _, found := k.GetBallot(ctx, b.BallotIdentifier) - require.False(t, found) - } - _, found = k.GetBallotListForHeight(ctx, 1) - require.False(t, found) - eventCount := 0 - for _, event := range ctx.EventManager().Events() { - if event.Type == "zetachain.zetacore.observer.EventBallotDeleted" { - eventCount++ - } + _, found = k.GetBallot(ctx, b.BallotIdentifier) + require.True(t, found) } - require.Equal(t, numberOfBallots, eventCount) }) + } func TestGetMaturedBallotHeight(t *testing.T) { diff --git a/x/observer/keeper/migrator.go b/x/observer/keeper/migrator.go index f6ee68c594..c98ccd9e0c 100644 --- a/x/observer/keeper/migrator.go +++ b/x/observer/keeper/migrator.go @@ -4,6 +4,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" v8 "github.com/zeta-chain/node/x/observer/migrations/v8" + v9 "github.com/zeta-chain/node/x/observer/migrations/v9" ) // Migrator is a struct for handling in-place store migrations. @@ -49,3 +50,8 @@ func (m Migrator) Migrate6to7(_ sdk.Context) error { func (m Migrator) Migrate7to8(ctx sdk.Context) error { return v8.MigrateStore(ctx, m.observerKeeper) } + +// Migrate8to9 migrates the store from consensus version 8 to 9 +func (m Migrator) Migrate8to9(ctx sdk.Context) error { + return v9.MigrateStore(ctx, m.observerKeeper) +} diff --git a/x/observer/migrations/v9/migrate.go b/x/observer/migrations/v9/migrate.go index 736bbd99ff..14c6dc7af6 100644 --- a/x/observer/migrations/v9/migrate.go +++ b/x/observer/migrations/v9/migrate.go @@ -12,17 +12,18 @@ type observerKeeper interface { DeleteBallotListForHeight(ctx sdk.Context, height int64) } -// MigrateStore migrates the x/observer module state from the consensus version 7 to 8 +const MaturityBlocks = int64(100) + +// MigrateStore migrates the x/observer module state from the consensus version 8 to version 9. // It updates the indexing for chain nonces object to use chain ID instead of chain name func MigrateStore(ctx sdk.Context, observerKeeper observerKeeper) error { currentHeight := ctx.BlockHeight() // Maturity blocks is a parameter in the emissions module - maturityBlocks := int64(100) - if currentHeight < maturityBlocks { + + if currentHeight < MaturityBlocks { return nil } - maturedHeight := currentHeight - maturityBlocks - + maturedHeight := currentHeight - MaturityBlocks for i := maturedHeight; i > 0; i-- { ballotList, found := observerKeeper.GetBallotListForHeight(ctx, i) if !found { @@ -33,5 +34,6 @@ func MigrateStore(ctx sdk.Context, observerKeeper observerKeeper) error { } observerKeeper.DeleteBallotListForHeight(ctx, i) } + return nil } diff --git a/x/observer/migrations/v9/migrate_test.go b/x/observer/migrations/v9/migrate_test.go index 3572ffb96e..b13012613f 100644 --- a/x/observer/migrations/v9/migrate_test.go +++ b/x/observer/migrations/v9/migrate_test.go @@ -2,49 +2,146 @@ package v9_test import ( "testing" - "time" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" keepertest "github.com/zeta-chain/node/testutil/keeper" - "github.com/zeta-chain/node/testutil/testdata" - observerkeeper "github.com/zeta-chain/node/x/observer/keeper" + "github.com/zeta-chain/node/testutil/sample" v9 "github.com/zeta-chain/node/x/observer/migrations/v9" "github.com/zeta-chain/node/x/observer/types" ) func TestMigrateStore(t *testing.T) { - k, ctx, _, _ := keepertest.ObserverKeeper(t) - SetupMainnetData(t, k, ctx) - ctx = ctx.WithBlockHeight(5073825) - err := v9.MigrateStore(ctx, k) - require.NoError(t, err) - - start := time.Now() - ballots := k.GetAllBallots(ctx) - elapsed := time.Since(start) - - // Elapsed should be less than 1 second - require.Less(t, elapsed.Seconds(), 1) - require.Len(t, ballots, 0) -} + t.Run("delete all matured ballots", func(t *testing.T) { + //Arrange + k, ctx, _, _ := keepertest.ObserverKeeper(t) + // Set current height to 1000 + currentHeight := int64(1000) + // 100 is the maturity blocks parameter defined in emissions module and used by the migrator script + lastMaturedHeight := currentHeight - v9.MaturityBlocks + // The first block height is 1 for zeta chain + firstBlockHeight := int64(1) + // Account for the first block height to be 1 + numberOfActualBlocks := currentHeight - firstBlockHeight + blocksWithUnMaturedBallots := numberOfActualBlocks - lastMaturedHeight + // Use this constant to add ballot to each block + numberOfBallotsPerBlock := int64(10) + + ctx = ctx.WithBlockHeight(currentHeight) + + for i := firstBlockHeight; i < currentHeight; i++ { + for j := int64(0); j < numberOfBallotsPerBlock; j++ { + b := types.Ballot{ + BallotIdentifier: sample.ZetaIndex(t), + BallotCreationHeight: i, + } + k.AddBallotToList(ctx, b) + k.SetBallot(ctx, &b) + } + } + + allBallots := k.GetAllBallots(ctx) + require.Equal(t, numberOfActualBlocks*numberOfBallotsPerBlock, int64(len(allBallots))) + + //Act + err := v9.MigrateStore(ctx, k) + require.NoError(t, err) + + //Assert + // We have 10 ballots per block for the last 999 blocks. + // However, since the maturity blocks are 100, the last 99 blocks will have unmatured ballots. + // 99*10 = 990 + remainingBallotsAfterMigration := k.GetAllBallots(ctx) + require.Equal(t, blocksWithUnMaturedBallots*numberOfBallotsPerBlock, int64(len(remainingBallotsAfterMigration))) + require.Equal(t, int64(990), int64(len(remainingBallotsAfterMigration))) + + // remaining ballots should have creation height greater than last matured height + for _, b := range remainingBallotsAfterMigration { + require.Greater(t, b.BallotCreationHeight, lastMaturedHeight) + } + + // all ballots lists before last matured height should be deleted + for i := firstBlockHeight; i < lastMaturedHeight; i++ { + _, found := k.GetBallotListForHeight(ctx, i) + require.False(t, found) + } + + // all ballots lists after last matured height should be present + for i := lastMaturedHeight + 1; i < currentHeight; i++ { + _, found := k.GetBallotListForHeight(ctx, i) + require.True(t, found) + } + }) + + t.Run("do not thing if ballot list for height is not found", func(t *testing.T) { + //Arrange + k, ctx, _, _ := keepertest.ObserverKeeper(t) + // Set current height to 1000 + currentHeight := int64(1000) + // The first block height is 1 for zeta chain + firstBlockHeight := int64(1) + // Account for the first block height to be 1 + numberOfActualBlocks := currentHeight - firstBlockHeight + // Use this constant to add ballot to each block + numberOfBallotsPerBlock := int64(10) + + ctx = ctx.WithBlockHeight(currentHeight) + + for i := firstBlockHeight; i < currentHeight; i++ { + for j := int64(0); j < numberOfBallotsPerBlock; j++ { + b := types.Ballot{ + BallotIdentifier: sample.ZetaIndex(t), + BallotCreationHeight: i, + } + k.SetBallot(ctx, &b) + } + } + + allBallots := k.GetAllBallots(ctx) + require.Equal(t, numberOfActualBlocks*numberOfBallotsPerBlock, int64(len(allBallots))) + + //Act + err := v9.MigrateStore(ctx, k) + require.NoError(t, err) + + //Assert + allBallotsAfterMigration := k.GetAllBallots(ctx) + require.Equal(t, numberOfActualBlocks*numberOfBallotsPerBlock, int64(len(allBallotsAfterMigration))) + }) + + t.Run("do not thing if current height is less than maturity blocks", func(t *testing.T) { + //Arrange + k, ctx, _, _ := keepertest.ObserverKeeper(t) + // Set current height to 100 + currentHeight := int64(10) + // The first block height is 1 for zeta chain + firstBlockHeight := int64(1) + // Account for the first block height to be 1 + numberOfActualBlocks := currentHeight - firstBlockHeight + // Use this constant to add ballot to each block + numberOfBallotsPerBlock := int64(10) + + ctx = ctx.WithBlockHeight(currentHeight) + + for i := firstBlockHeight; i < currentHeight; i++ { + for j := int64(0); j < numberOfBallotsPerBlock; j++ { + b := types.Ballot{ + BallotIdentifier: sample.ZetaIndex(t), + BallotCreationHeight: i, + } + k.AddBallotToList(ctx, b) + k.SetBallot(ctx, &b) + } + } + + allBallots := k.GetAllBallots(ctx) + require.Equal(t, numberOfActualBlocks*numberOfBallotsPerBlock, int64(len(allBallots))) + + //Act + err := v9.MigrateStore(ctx, k) + require.NoError(t, err) -func SetupMainnetData(t *testing.T, k *observerkeeper.Keeper, ctx sdk.Context) { - b := testdata.ReadMainnetBallots(t) - ballotsList := map[int64][]string{} - - for _, ballot := range b { - k.SetBallot(ctx, ballot) - ballotsList[ballot.BallotCreationHeight] = append( - ballotsList[ballot.BallotCreationHeight], - ballot.BallotIdentifier, - ) - } - - for height, ballotList := range ballotsList { - k.SetBallotList(ctx, &types.BallotListForHeight{ - Height: height, - BallotsIndexList: ballotList, - }) - } + //Assert + allBallotsAfterMigration := k.GetAllBallots(ctx) + require.Equal(t, numberOfActualBlocks*numberOfBallotsPerBlock, int64(len(allBallotsAfterMigration))) + }) } From b074ddaafde127d518980a5c55116152c0e0bd16 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Thu, 19 Dec 2024 17:41:12 -0500 Subject: [PATCH 11/16] add a query for all ballots --- proto/zetachain/zetacore/observer/query.proto | 14 + x/emissions/abci.go | 1 - x/observer/client/cli/query.go | 1 + x/observer/client/cli/query_ballot.go | 25 + x/observer/keeper/ballot.go | 4 +- x/observer/keeper/grpc_query_ballot.go | 13 + x/observer/keeper/grpc_query_ballot_test.go | 47 + x/observer/types/query.pb.go | 856 ++++++++++++++---- x/observer/types/query.pb.gw.go | 83 ++ 9 files changed, 844 insertions(+), 200 deletions(-) diff --git a/proto/zetachain/zetacore/observer/query.proto b/proto/zetachain/zetacore/observer/query.proto index f69a6dcce2..eca364631b 100644 --- a/proto/zetachain/zetacore/observer/query.proto +++ b/proto/zetachain/zetacore/observer/query.proto @@ -171,6 +171,20 @@ service Query { returns (QueryOperationalFlagsResponse) { option (google.api.http).get = "/zeta-chain/observer/operationalFlags"; } + + // Query all ballots + rpc Ballots(QueryBallotsRequest) returns (QueryBallotsResponse) { + option (google.api.http).get = "/zeta-chain/observer/ballots"; + } +} + +message QueryBallotsRequest { + cosmos.base.query.v1beta1.PageRequest pagination = 1; +} + +message QueryBallotsResponse { + repeated Ballot ballots = 1 [ (gogoproto.nullable) = false ]; + cosmos.base.query.v1beta1.PageResponse pagination = 2; } message QueryOperationalFlagsRequest {} diff --git a/x/emissions/abci.go b/x/emissions/abci.go index 6ae996b4f4..b5399cf9f3 100644 --- a/x/emissions/abci.go +++ b/x/emissions/abci.go @@ -105,7 +105,6 @@ func DistributeObserverRewards( var ( slashAmount = params.ObserverSlashAmount maturityBlocks = params.BallotMaturityBlocks - maturedBallots []string ) diff --git a/x/observer/client/cli/query.go b/x/observer/client/cli/query.go index 04c773063b..5276430453 100644 --- a/x/observer/client/cli/query.go +++ b/x/observer/client/cli/query.go @@ -44,6 +44,7 @@ func GetQueryCmd(_ string) *cobra.Command { CmdGetAllTssFundsMigrator(), CmdGetTssFundsMigrator(), CmdShowOperationalFlags(), + CmdAllBallots(), ) return cmd diff --git a/x/observer/client/cli/query_ballot.go b/x/observer/client/cli/query_ballot.go index 6d724a3571..60b39e2afc 100644 --- a/x/observer/client/cli/query_ballot.go +++ b/x/observer/client/cli/query_ballot.go @@ -37,6 +37,31 @@ func CmdBallotByIdentifier() *cobra.Command { } flags.AddQueryFlagsToCmd(cmd) + return cmd +} + +func CmdAllBallots() *cobra.Command { + cmd := &cobra.Command{ + Use: "list-ballots", + Short: "Query all ballots", + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + params := &types.QueryBallotsRequest{} + + res, err := queryClient.Ballots(cmd.Context(), params) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + flags.AddQueryFlagsToCmd(cmd) return cmd } diff --git a/x/observer/keeper/ballot.go b/x/observer/keeper/ballot.go index 13a78a3f81..645873a271 100644 --- a/x/observer/keeper/ballot.go +++ b/x/observer/keeper/ballot.go @@ -83,8 +83,8 @@ func (k Keeper) AddBallotToList(ctx sdk.Context, ballot types.Ballot) { // ClearMaturedBallotsAndBallotList deletes all matured ballots and the list of ballots for a given height. // It also emits an event for each ballot deleted. -func (k Keeper) ClearMaturedBallotsAndBallotList(ctx sdk.Context, maturityBlocks int64) { - maturedBallotsHeight := getMaturedBallotHeight(ctx, maturityBlocks) +func (k Keeper) ClearMaturedBallotsAndBallotList(ctx sdk.Context, maturityBlocksParam int64) { + maturedBallotsHeight := getMaturedBallotHeight(ctx, maturityBlocksParam) // Fetch all the matured ballots, return if no matured ballots are found // For the current implementation, this should never happen as ClearMaturedBallotsAndBallotList is only called after the Distribution of the rewards, diff --git a/x/observer/keeper/grpc_query_ballot.go b/x/observer/keeper/grpc_query_ballot.go index a36c37d136..20eed7acda 100644 --- a/x/observer/keeper/grpc_query_ballot.go +++ b/x/observer/keeper/grpc_query_ballot.go @@ -52,3 +52,16 @@ func (k Keeper) BallotByIdentifier( BallotStatus: ballot.BallotStatus, }, nil } + +func (k Keeper) Ballots(goCtx context.Context, req *types.QueryBallotsRequest) (*types.QueryBallotsResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + ctx := sdk.UnwrapSDKContext(goCtx) + ballotList := k.GetAllBallots(ctx) + ballots := make([]types.Ballot, len(ballotList)) + for i, ballot := range ballotList { + ballots[i] = *ballot + } + return &types.QueryBallotsResponse{Ballots: ballots}, nil +} diff --git a/x/observer/keeper/grpc_query_ballot_test.go b/x/observer/keeper/grpc_query_ballot_test.go index 48b76b40e7..d00956f741 100644 --- a/x/observer/keeper/grpc_query_ballot_test.go +++ b/x/observer/keeper/grpc_query_ballot_test.go @@ -1,6 +1,7 @@ package keeper_test import ( + "fmt" "testing" sdk "github.com/cosmos/cosmos-sdk/types" @@ -135,3 +136,49 @@ func TestKeeper_BallotByIdentifier(t *testing.T) { }, res) }) } + +func TestKeeper_Ballots(t *testing.T) { + t.Run("should error if req is nil", func(t *testing.T) { + k, ctx, _, _ := keepertest.ObserverKeeper(t) + wctx := sdk.WrapSDKContext(ctx) + + res, err := k.Ballots(wctx, nil) + require.Nil(t, res) + require.Error(t, err) + }) + + t.Run("should return empty list if no ballots", func(t *testing.T) { + k, ctx, _, _ := keepertest.ObserverKeeper(t) + wctx := sdk.WrapSDKContext(ctx) + + res, err := k.Ballots(wctx, &types.QueryBallotsRequest{}) + require.NoError(t, err) + require.Equal(t, &types.QueryBallotsResponse{ + Ballots: []types.Ballot{}, + }, res) + }) + + t.Run("should return all ballots", func(t *testing.T) { + k, ctx, _, _ := keepertest.ObserverKeeper(t) + wctx := sdk.WrapSDKContext(ctx) + + ballots := make([]types.Ballot, 10) + for i := 0; i < 10; i++ { + ballot := types.Ballot{ + Index: "", + BallotIdentifier: fmt.Sprintf("index-%d", i), + VoterList: []string{sample.AccAddress()}, + Votes: []types.VoteType{types.VoteType_SuccessObservation}, + BallotStatus: types.BallotStatus_BallotInProgress, + BallotCreationHeight: 1, + BallotThreshold: sdk.MustNewDecFromStr("0.5"), + } + k.SetBallot(ctx, &ballot) + ballots[i] = ballot + } + + res, err := k.Ballots(wctx, &types.QueryBallotsRequest{}) + require.NoError(t, err) + require.ElementsMatch(t, ballots, res.Ballots) + }) +} diff --git a/x/observer/types/query.pb.go b/x/observer/types/query.pb.go index 3a7baaeba2..04c5d99321 100644 --- a/x/observer/types/query.pb.go +++ b/x/observer/types/query.pb.go @@ -32,6 +32,102 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +type QueryBallotsRequest struct { + Pagination *query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryBallotsRequest) Reset() { *m = QueryBallotsRequest{} } +func (m *QueryBallotsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryBallotsRequest) ProtoMessage() {} +func (*QueryBallotsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_25b2aa420449a0c0, []int{0} +} +func (m *QueryBallotsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryBallotsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryBallotsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryBallotsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryBallotsRequest.Merge(m, src) +} +func (m *QueryBallotsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryBallotsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryBallotsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryBallotsRequest proto.InternalMessageInfo + +func (m *QueryBallotsRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +type QueryBallotsResponse struct { + Ballots []Ballot `protobuf:"bytes,1,rep,name=ballots,proto3" json:"ballots"` + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryBallotsResponse) Reset() { *m = QueryBallotsResponse{} } +func (m *QueryBallotsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryBallotsResponse) ProtoMessage() {} +func (*QueryBallotsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_25b2aa420449a0c0, []int{1} +} +func (m *QueryBallotsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryBallotsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryBallotsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryBallotsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryBallotsResponse.Merge(m, src) +} +func (m *QueryBallotsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryBallotsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryBallotsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryBallotsResponse proto.InternalMessageInfo + +func (m *QueryBallotsResponse) GetBallots() []Ballot { + if m != nil { + return m.Ballots + } + return nil +} + +func (m *QueryBallotsResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + type QueryOperationalFlagsRequest struct { } @@ -39,7 +135,7 @@ func (m *QueryOperationalFlagsRequest) Reset() { *m = QueryOperationalFl func (m *QueryOperationalFlagsRequest) String() string { return proto.CompactTextString(m) } func (*QueryOperationalFlagsRequest) ProtoMessage() {} func (*QueryOperationalFlagsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{0} + return fileDescriptor_25b2aa420449a0c0, []int{2} } func (m *QueryOperationalFlagsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -76,7 +172,7 @@ func (m *QueryOperationalFlagsResponse) Reset() { *m = QueryOperationalF func (m *QueryOperationalFlagsResponse) String() string { return proto.CompactTextString(m) } func (*QueryOperationalFlagsResponse) ProtoMessage() {} func (*QueryOperationalFlagsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{1} + return fileDescriptor_25b2aa420449a0c0, []int{3} } func (m *QueryOperationalFlagsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -119,7 +215,7 @@ func (m *QueryTssFundsMigratorInfoAllRequest) Reset() { *m = QueryTssFun func (m *QueryTssFundsMigratorInfoAllRequest) String() string { return proto.CompactTextString(m) } func (*QueryTssFundsMigratorInfoAllRequest) ProtoMessage() {} func (*QueryTssFundsMigratorInfoAllRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{2} + return fileDescriptor_25b2aa420449a0c0, []int{4} } func (m *QueryTssFundsMigratorInfoAllRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -156,7 +252,7 @@ func (m *QueryTssFundsMigratorInfoAllResponse) Reset() { *m = QueryTssFu func (m *QueryTssFundsMigratorInfoAllResponse) String() string { return proto.CompactTextString(m) } func (*QueryTssFundsMigratorInfoAllResponse) ProtoMessage() {} func (*QueryTssFundsMigratorInfoAllResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{3} + return fileDescriptor_25b2aa420449a0c0, []int{5} } func (m *QueryTssFundsMigratorInfoAllResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -200,7 +296,7 @@ func (m *QueryTssFundsMigratorInfoRequest) Reset() { *m = QueryTssFundsM func (m *QueryTssFundsMigratorInfoRequest) String() string { return proto.CompactTextString(m) } func (*QueryTssFundsMigratorInfoRequest) ProtoMessage() {} func (*QueryTssFundsMigratorInfoRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{4} + return fileDescriptor_25b2aa420449a0c0, []int{6} } func (m *QueryTssFundsMigratorInfoRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -244,7 +340,7 @@ func (m *QueryTssFundsMigratorInfoResponse) Reset() { *m = QueryTssFunds func (m *QueryTssFundsMigratorInfoResponse) String() string { return proto.CompactTextString(m) } func (*QueryTssFundsMigratorInfoResponse) ProtoMessage() {} func (*QueryTssFundsMigratorInfoResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{5} + return fileDescriptor_25b2aa420449a0c0, []int{7} } func (m *QueryTssFundsMigratorInfoResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -288,7 +384,7 @@ func (m *QueryGetChainNoncesRequest) Reset() { *m = QueryGetChainNoncesR func (m *QueryGetChainNoncesRequest) String() string { return proto.CompactTextString(m) } func (*QueryGetChainNoncesRequest) ProtoMessage() {} func (*QueryGetChainNoncesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{6} + return fileDescriptor_25b2aa420449a0c0, []int{8} } func (m *QueryGetChainNoncesRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -332,7 +428,7 @@ func (m *QueryGetChainNoncesResponse) Reset() { *m = QueryGetChainNonces func (m *QueryGetChainNoncesResponse) String() string { return proto.CompactTextString(m) } func (*QueryGetChainNoncesResponse) ProtoMessage() {} func (*QueryGetChainNoncesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{7} + return fileDescriptor_25b2aa420449a0c0, []int{9} } func (m *QueryGetChainNoncesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -376,7 +472,7 @@ func (m *QueryAllChainNoncesRequest) Reset() { *m = QueryAllChainNoncesR func (m *QueryAllChainNoncesRequest) String() string { return proto.CompactTextString(m) } func (*QueryAllChainNoncesRequest) ProtoMessage() {} func (*QueryAllChainNoncesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{8} + return fileDescriptor_25b2aa420449a0c0, []int{10} } func (m *QueryAllChainNoncesRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -421,7 +517,7 @@ func (m *QueryAllChainNoncesResponse) Reset() { *m = QueryAllChainNonces func (m *QueryAllChainNoncesResponse) String() string { return proto.CompactTextString(m) } func (*QueryAllChainNoncesResponse) ProtoMessage() {} func (*QueryAllChainNoncesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{9} + return fileDescriptor_25b2aa420449a0c0, []int{11} } func (m *QueryAllChainNoncesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -472,7 +568,7 @@ func (m *QueryAllPendingNoncesRequest) Reset() { *m = QueryAllPendingNon func (m *QueryAllPendingNoncesRequest) String() string { return proto.CompactTextString(m) } func (*QueryAllPendingNoncesRequest) ProtoMessage() {} func (*QueryAllPendingNoncesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{10} + return fileDescriptor_25b2aa420449a0c0, []int{12} } func (m *QueryAllPendingNoncesRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -517,7 +613,7 @@ func (m *QueryAllPendingNoncesResponse) Reset() { *m = QueryAllPendingNo func (m *QueryAllPendingNoncesResponse) String() string { return proto.CompactTextString(m) } func (*QueryAllPendingNoncesResponse) ProtoMessage() {} func (*QueryAllPendingNoncesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{11} + return fileDescriptor_25b2aa420449a0c0, []int{13} } func (m *QueryAllPendingNoncesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -568,7 +664,7 @@ func (m *QueryPendingNoncesByChainRequest) Reset() { *m = QueryPendingNo func (m *QueryPendingNoncesByChainRequest) String() string { return proto.CompactTextString(m) } func (*QueryPendingNoncesByChainRequest) ProtoMessage() {} func (*QueryPendingNoncesByChainRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{12} + return fileDescriptor_25b2aa420449a0c0, []int{14} } func (m *QueryPendingNoncesByChainRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -612,7 +708,7 @@ func (m *QueryPendingNoncesByChainResponse) Reset() { *m = QueryPendingN func (m *QueryPendingNoncesByChainResponse) String() string { return proto.CompactTextString(m) } func (*QueryPendingNoncesByChainResponse) ProtoMessage() {} func (*QueryPendingNoncesByChainResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{13} + return fileDescriptor_25b2aa420449a0c0, []int{15} } func (m *QueryPendingNoncesByChainResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -655,7 +751,7 @@ func (m *QueryGetTSSRequest) Reset() { *m = QueryGetTSSRequest{} } func (m *QueryGetTSSRequest) String() string { return proto.CompactTextString(m) } func (*QueryGetTSSRequest) ProtoMessage() {} func (*QueryGetTSSRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{14} + return fileDescriptor_25b2aa420449a0c0, []int{16} } func (m *QueryGetTSSRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -692,7 +788,7 @@ func (m *QueryGetTSSResponse) Reset() { *m = QueryGetTSSResponse{} } func (m *QueryGetTSSResponse) String() string { return proto.CompactTextString(m) } func (*QueryGetTSSResponse) ProtoMessage() {} func (*QueryGetTSSResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{15} + return fileDescriptor_25b2aa420449a0c0, []int{17} } func (m *QueryGetTSSResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -736,7 +832,7 @@ func (m *QueryGetTssAddressRequest) Reset() { *m = QueryGetTssAddressReq func (m *QueryGetTssAddressRequest) String() string { return proto.CompactTextString(m) } func (*QueryGetTssAddressRequest) ProtoMessage() {} func (*QueryGetTssAddressRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{16} + return fileDescriptor_25b2aa420449a0c0, []int{18} } func (m *QueryGetTssAddressRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -781,7 +877,7 @@ func (m *QueryGetTssAddressResponse) Reset() { *m = QueryGetTssAddressRe func (m *QueryGetTssAddressResponse) String() string { return proto.CompactTextString(m) } func (*QueryGetTssAddressResponse) ProtoMessage() {} func (*QueryGetTssAddressResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{17} + return fileDescriptor_25b2aa420449a0c0, []int{19} } func (m *QueryGetTssAddressResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -837,7 +933,7 @@ func (m *QueryGetTssAddressByFinalizedHeightRequest) String() string { } func (*QueryGetTssAddressByFinalizedHeightRequest) ProtoMessage() {} func (*QueryGetTssAddressByFinalizedHeightRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{18} + return fileDescriptor_25b2aa420449a0c0, []int{20} } func (m *QueryGetTssAddressByFinalizedHeightRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -893,7 +989,7 @@ func (m *QueryGetTssAddressByFinalizedHeightResponse) String() string { } func (*QueryGetTssAddressByFinalizedHeightResponse) ProtoMessage() {} func (*QueryGetTssAddressByFinalizedHeightResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{19} + return fileDescriptor_25b2aa420449a0c0, []int{21} } func (m *QueryGetTssAddressByFinalizedHeightResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -944,7 +1040,7 @@ func (m *QueryTssHistoryRequest) Reset() { *m = QueryTssHistoryRequest{} func (m *QueryTssHistoryRequest) String() string { return proto.CompactTextString(m) } func (*QueryTssHistoryRequest) ProtoMessage() {} func (*QueryTssHistoryRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{20} + return fileDescriptor_25b2aa420449a0c0, []int{22} } func (m *QueryTssHistoryRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -989,7 +1085,7 @@ func (m *QueryTssHistoryResponse) Reset() { *m = QueryTssHistoryResponse func (m *QueryTssHistoryResponse) String() string { return proto.CompactTextString(m) } func (*QueryTssHistoryResponse) ProtoMessage() {} func (*QueryTssHistoryResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{21} + return fileDescriptor_25b2aa420449a0c0, []int{23} } func (m *QueryTssHistoryResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1041,7 +1137,7 @@ func (m *QueryHasVotedRequest) Reset() { *m = QueryHasVotedRequest{} } func (m *QueryHasVotedRequest) String() string { return proto.CompactTextString(m) } func (*QueryHasVotedRequest) ProtoMessage() {} func (*QueryHasVotedRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{22} + return fileDescriptor_25b2aa420449a0c0, []int{24} } func (m *QueryHasVotedRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1092,7 +1188,7 @@ func (m *QueryHasVotedResponse) Reset() { *m = QueryHasVotedResponse{} } func (m *QueryHasVotedResponse) String() string { return proto.CompactTextString(m) } func (*QueryHasVotedResponse) ProtoMessage() {} func (*QueryHasVotedResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{23} + return fileDescriptor_25b2aa420449a0c0, []int{25} } func (m *QueryHasVotedResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1136,7 +1232,7 @@ func (m *QueryBallotByIdentifierRequest) Reset() { *m = QueryBallotByIde func (m *QueryBallotByIdentifierRequest) String() string { return proto.CompactTextString(m) } func (*QueryBallotByIdentifierRequest) ProtoMessage() {} func (*QueryBallotByIdentifierRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{24} + return fileDescriptor_25b2aa420449a0c0, []int{26} } func (m *QueryBallotByIdentifierRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1183,7 +1279,7 @@ func (m *QueryBallotByIdentifierResponse) Reset() { *m = QueryBallotById func (m *QueryBallotByIdentifierResponse) String() string { return proto.CompactTextString(m) } func (*QueryBallotByIdentifierResponse) ProtoMessage() {} func (*QueryBallotByIdentifierResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{25} + return fileDescriptor_25b2aa420449a0c0, []int{27} } func (m *QueryBallotByIdentifierResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1247,7 +1343,7 @@ func (m *QueryObserverSet) Reset() { *m = QueryObserverSet{} } func (m *QueryObserverSet) String() string { return proto.CompactTextString(m) } func (*QueryObserverSet) ProtoMessage() {} func (*QueryObserverSet) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{26} + return fileDescriptor_25b2aa420449a0c0, []int{28} } func (m *QueryObserverSet) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1284,7 +1380,7 @@ func (m *QueryObserverSetResponse) Reset() { *m = QueryObserverSetRespon func (m *QueryObserverSetResponse) String() string { return proto.CompactTextString(m) } func (*QueryObserverSetResponse) ProtoMessage() {} func (*QueryObserverSetResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{27} + return fileDescriptor_25b2aa420449a0c0, []int{29} } func (m *QueryObserverSetResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1327,7 +1423,7 @@ func (m *QuerySupportedChains) Reset() { *m = QuerySupportedChains{} } func (m *QuerySupportedChains) String() string { return proto.CompactTextString(m) } func (*QuerySupportedChains) ProtoMessage() {} func (*QuerySupportedChains) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{28} + return fileDescriptor_25b2aa420449a0c0, []int{30} } func (m *QuerySupportedChains) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1364,7 +1460,7 @@ func (m *QuerySupportedChainsResponse) Reset() { *m = QuerySupportedChai func (m *QuerySupportedChainsResponse) String() string { return proto.CompactTextString(m) } func (*QuerySupportedChainsResponse) ProtoMessage() {} func (*QuerySupportedChainsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{29} + return fileDescriptor_25b2aa420449a0c0, []int{31} } func (m *QuerySupportedChainsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1408,7 +1504,7 @@ func (m *QueryGetChainParamsForChainRequest) Reset() { *m = QueryGetChai func (m *QueryGetChainParamsForChainRequest) String() string { return proto.CompactTextString(m) } func (*QueryGetChainParamsForChainRequest) ProtoMessage() {} func (*QueryGetChainParamsForChainRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{30} + return fileDescriptor_25b2aa420449a0c0, []int{32} } func (m *QueryGetChainParamsForChainRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1452,7 +1548,7 @@ func (m *QueryGetChainParamsForChainResponse) Reset() { *m = QueryGetCha func (m *QueryGetChainParamsForChainResponse) String() string { return proto.CompactTextString(m) } func (*QueryGetChainParamsForChainResponse) ProtoMessage() {} func (*QueryGetChainParamsForChainResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{31} + return fileDescriptor_25b2aa420449a0c0, []int{33} } func (m *QueryGetChainParamsForChainResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1495,7 +1591,7 @@ func (m *QueryGetChainParamsRequest) Reset() { *m = QueryGetChainParamsR func (m *QueryGetChainParamsRequest) String() string { return proto.CompactTextString(m) } func (*QueryGetChainParamsRequest) ProtoMessage() {} func (*QueryGetChainParamsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{32} + return fileDescriptor_25b2aa420449a0c0, []int{34} } func (m *QueryGetChainParamsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1532,7 +1628,7 @@ func (m *QueryGetChainParamsResponse) Reset() { *m = QueryGetChainParams func (m *QueryGetChainParamsResponse) String() string { return proto.CompactTextString(m) } func (*QueryGetChainParamsResponse) ProtoMessage() {} func (*QueryGetChainParamsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{33} + return fileDescriptor_25b2aa420449a0c0, []int{35} } func (m *QueryGetChainParamsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1576,7 +1672,7 @@ func (m *QueryGetNodeAccountRequest) Reset() { *m = QueryGetNodeAccountR func (m *QueryGetNodeAccountRequest) String() string { return proto.CompactTextString(m) } func (*QueryGetNodeAccountRequest) ProtoMessage() {} func (*QueryGetNodeAccountRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{34} + return fileDescriptor_25b2aa420449a0c0, []int{36} } func (m *QueryGetNodeAccountRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1620,7 +1716,7 @@ func (m *QueryGetNodeAccountResponse) Reset() { *m = QueryGetNodeAccount func (m *QueryGetNodeAccountResponse) String() string { return proto.CompactTextString(m) } func (*QueryGetNodeAccountResponse) ProtoMessage() {} func (*QueryGetNodeAccountResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{35} + return fileDescriptor_25b2aa420449a0c0, []int{37} } func (m *QueryGetNodeAccountResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1664,7 +1760,7 @@ func (m *QueryAllNodeAccountRequest) Reset() { *m = QueryAllNodeAccountR func (m *QueryAllNodeAccountRequest) String() string { return proto.CompactTextString(m) } func (*QueryAllNodeAccountRequest) ProtoMessage() {} func (*QueryAllNodeAccountRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{36} + return fileDescriptor_25b2aa420449a0c0, []int{38} } func (m *QueryAllNodeAccountRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1709,7 +1805,7 @@ func (m *QueryAllNodeAccountResponse) Reset() { *m = QueryAllNodeAccount func (m *QueryAllNodeAccountResponse) String() string { return proto.CompactTextString(m) } func (*QueryAllNodeAccountResponse) ProtoMessage() {} func (*QueryAllNodeAccountResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{37} + return fileDescriptor_25b2aa420449a0c0, []int{39} } func (m *QueryAllNodeAccountResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1759,7 +1855,7 @@ func (m *QueryGetCrosschainFlagsRequest) Reset() { *m = QueryGetCrosscha func (m *QueryGetCrosschainFlagsRequest) String() string { return proto.CompactTextString(m) } func (*QueryGetCrosschainFlagsRequest) ProtoMessage() {} func (*QueryGetCrosschainFlagsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{38} + return fileDescriptor_25b2aa420449a0c0, []int{40} } func (m *QueryGetCrosschainFlagsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1796,7 +1892,7 @@ func (m *QueryGetCrosschainFlagsResponse) Reset() { *m = QueryGetCrossch func (m *QueryGetCrosschainFlagsResponse) String() string { return proto.CompactTextString(m) } func (*QueryGetCrosschainFlagsResponse) ProtoMessage() {} func (*QueryGetCrosschainFlagsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{39} + return fileDescriptor_25b2aa420449a0c0, []int{41} } func (m *QueryGetCrosschainFlagsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1839,7 +1935,7 @@ func (m *QueryGetKeygenRequest) Reset() { *m = QueryGetKeygenRequest{} } func (m *QueryGetKeygenRequest) String() string { return proto.CompactTextString(m) } func (*QueryGetKeygenRequest) ProtoMessage() {} func (*QueryGetKeygenRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{40} + return fileDescriptor_25b2aa420449a0c0, []int{42} } func (m *QueryGetKeygenRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1876,7 +1972,7 @@ func (m *QueryGetKeygenResponse) Reset() { *m = QueryGetKeygenResponse{} func (m *QueryGetKeygenResponse) String() string { return proto.CompactTextString(m) } func (*QueryGetKeygenResponse) ProtoMessage() {} func (*QueryGetKeygenResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{41} + return fileDescriptor_25b2aa420449a0c0, []int{43} } func (m *QueryGetKeygenResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1919,7 +2015,7 @@ func (m *QueryShowObserverCountRequest) Reset() { *m = QueryShowObserver func (m *QueryShowObserverCountRequest) String() string { return proto.CompactTextString(m) } func (*QueryShowObserverCountRequest) ProtoMessage() {} func (*QueryShowObserverCountRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{42} + return fileDescriptor_25b2aa420449a0c0, []int{44} } func (m *QueryShowObserverCountRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1956,7 +2052,7 @@ func (m *QueryShowObserverCountResponse) Reset() { *m = QueryShowObserve func (m *QueryShowObserverCountResponse) String() string { return proto.CompactTextString(m) } func (*QueryShowObserverCountResponse) ProtoMessage() {} func (*QueryShowObserverCountResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{43} + return fileDescriptor_25b2aa420449a0c0, []int{45} } func (m *QueryShowObserverCountResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2000,7 +2096,7 @@ func (m *QueryBlameByIdentifierRequest) Reset() { *m = QueryBlameByIdent func (m *QueryBlameByIdentifierRequest) String() string { return proto.CompactTextString(m) } func (*QueryBlameByIdentifierRequest) ProtoMessage() {} func (*QueryBlameByIdentifierRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{44} + return fileDescriptor_25b2aa420449a0c0, []int{46} } func (m *QueryBlameByIdentifierRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2044,7 +2140,7 @@ func (m *QueryBlameByIdentifierResponse) Reset() { *m = QueryBlameByIden func (m *QueryBlameByIdentifierResponse) String() string { return proto.CompactTextString(m) } func (*QueryBlameByIdentifierResponse) ProtoMessage() {} func (*QueryBlameByIdentifierResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{45} + return fileDescriptor_25b2aa420449a0c0, []int{47} } func (m *QueryBlameByIdentifierResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2088,7 +2184,7 @@ func (m *QueryAllBlameRecordsRequest) Reset() { *m = QueryAllBlameRecord func (m *QueryAllBlameRecordsRequest) String() string { return proto.CompactTextString(m) } func (*QueryAllBlameRecordsRequest) ProtoMessage() {} func (*QueryAllBlameRecordsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{46} + return fileDescriptor_25b2aa420449a0c0, []int{48} } func (m *QueryAllBlameRecordsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2133,7 +2229,7 @@ func (m *QueryAllBlameRecordsResponse) Reset() { *m = QueryAllBlameRecor func (m *QueryAllBlameRecordsResponse) String() string { return proto.CompactTextString(m) } func (*QueryAllBlameRecordsResponse) ProtoMessage() {} func (*QueryAllBlameRecordsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{47} + return fileDescriptor_25b2aa420449a0c0, []int{49} } func (m *QueryAllBlameRecordsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2185,7 +2281,7 @@ func (m *QueryBlameByChainAndNonceRequest) Reset() { *m = QueryBlameByCh func (m *QueryBlameByChainAndNonceRequest) String() string { return proto.CompactTextString(m) } func (*QueryBlameByChainAndNonceRequest) ProtoMessage() {} func (*QueryBlameByChainAndNonceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{48} + return fileDescriptor_25b2aa420449a0c0, []int{50} } func (m *QueryBlameByChainAndNonceRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2236,7 +2332,7 @@ func (m *QueryBlameByChainAndNonceResponse) Reset() { *m = QueryBlameByC func (m *QueryBlameByChainAndNonceResponse) String() string { return proto.CompactTextString(m) } func (*QueryBlameByChainAndNonceResponse) ProtoMessage() {} func (*QueryBlameByChainAndNonceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_25b2aa420449a0c0, []int{49} + return fileDescriptor_25b2aa420449a0c0, []int{51} } func (m *QueryBlameByChainAndNonceResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2273,6 +2369,8 @@ func (m *QueryBlameByChainAndNonceResponse) GetBlameInfo() []*Blame { } func init() { + proto.RegisterType((*QueryBallotsRequest)(nil), "zetachain.zetacore.observer.QueryBallotsRequest") + proto.RegisterType((*QueryBallotsResponse)(nil), "zetachain.zetacore.observer.QueryBallotsResponse") proto.RegisterType((*QueryOperationalFlagsRequest)(nil), "zetachain.zetacore.observer.QueryOperationalFlagsRequest") proto.RegisterType((*QueryOperationalFlagsResponse)(nil), "zetachain.zetacore.observer.QueryOperationalFlagsResponse") proto.RegisterType((*QueryTssFundsMigratorInfoAllRequest)(nil), "zetachain.zetacore.observer.QueryTssFundsMigratorInfoAllRequest") @@ -2330,154 +2428,158 @@ func init() { } var fileDescriptor_25b2aa420449a0c0 = []byte{ - // 2347 bytes of a gzipped FileDescriptorProto + // 2415 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x5a, 0xcf, 0x6f, 0x1b, 0xc7, - 0xf5, 0xf7, 0x5a, 0x89, 0x22, 0x8d, 0x6c, 0x89, 0x1a, 0xcb, 0xb6, 0x42, 0x3b, 0xb4, 0xbc, 0xb2, - 0x63, 0x59, 0x96, 0xb8, 0x36, 0xed, 0x7c, 0xfd, 0x2b, 0xfe, 0xda, 0xa4, 0x63, 0x49, 0x76, 0x12, - 0xdb, 0x21, 0xdd, 0x06, 0x30, 0xda, 0x32, 0x4b, 0x72, 0x48, 0x6e, 0xbd, 0xda, 0x61, 0x76, 0x46, - 0x4e, 0x18, 0x55, 0x40, 0xdb, 0x5b, 0x73, 0x28, 0x0a, 0x14, 0x68, 0x6f, 0x45, 0x2f, 0x3d, 0x16, - 0x28, 0x02, 0x04, 0x08, 0x50, 0xe4, 0x90, 0x53, 0x73, 0xe8, 0x21, 0x45, 0x8b, 0xa2, 0xa7, 0x34, - 0xb0, 0xfb, 0x87, 0x14, 0x3b, 0xf3, 0x96, 0xdc, 0x5d, 0xee, 0x2e, 0x87, 0xb2, 0x7a, 0x22, 0x77, - 0x76, 0xde, 0x9b, 0xcf, 0xe7, 0xcd, 0xcc, 0x9b, 0xcf, 0xcc, 0x2c, 0x3a, 0xf3, 0x09, 0xe1, 0x66, - 0xbd, 0x6d, 0x5a, 0x8e, 0x21, 0xfe, 0x51, 0x97, 0x18, 0xb4, 0xc6, 0x88, 0xfb, 0x94, 0xb8, 0xc6, - 0x87, 0x5b, 0xc4, 0xed, 0xe6, 0x3b, 0x2e, 0xe5, 0x14, 0x1f, 0xeb, 0x55, 0xcc, 0xfb, 0x15, 0xf3, - 0x7e, 0xc5, 0xec, 0x72, 0x9d, 0xb2, 0x4d, 0xca, 0x8c, 0x9a, 0xc9, 0x88, 0xb4, 0x32, 0x9e, 0x5e, - 0xa8, 0x11, 0x6e, 0x5e, 0x30, 0x3a, 0x66, 0xcb, 0x72, 0x4c, 0x6e, 0x51, 0x47, 0x3a, 0xca, 0xce, - 0xb5, 0x68, 0x8b, 0x8a, 0xbf, 0x86, 0xf7, 0x0f, 0x4a, 0x8f, 0xb7, 0x28, 0x6d, 0xd9, 0xc4, 0x30, - 0x3b, 0x96, 0x61, 0x3a, 0x0e, 0xe5, 0xc2, 0x84, 0xc1, 0xdb, 0xa5, 0x34, 0x94, 0x35, 0xd3, 0xb6, - 0x29, 0x87, 0x9a, 0xa9, 0x7c, 0x6a, 0xb6, 0xb9, 0x49, 0xa0, 0x62, 0x3e, 0xad, 0xa2, 0x28, 0xaf, - 0x3a, 0xd4, 0xa9, 0x13, 0x1f, 0x42, 0x21, 0xb5, 0xbe, 0x4b, 0x19, 0x93, 0x46, 0x4d, 0xdb, 0x6c, - 0x29, 0xc1, 0x7e, 0x42, 0xba, 0x2d, 0xe2, 0xa8, 0xa0, 0x71, 0x68, 0x83, 0x54, 0xcd, 0x7a, 0x9d, - 0x6e, 0x39, 0x3e, 0xcd, 0xe5, 0xb4, 0xfa, 0xfe, 0x1f, 0x15, 0x14, 0x1d, 0xd3, 0x35, 0x37, 0x7d, - 0xbc, 0xe7, 0x53, 0x6b, 0x12, 0xa7, 0x61, 0x39, 0xad, 0x70, 0x54, 0x4e, 0xa7, 0x59, 0x70, 0xe6, - 0x57, 0x5b, 0x4d, 0x85, 0xdb, 0x21, 0xae, 0xe8, 0x6d, 0xd3, 0x4e, 0x61, 0xd7, 0x79, 0xd2, 0x92, - 0xdd, 0xc2, 0xe0, 0x67, 0x48, 0xdd, 0x8e, 0x4b, 0x69, 0x93, 0xc1, 0x0f, 0xd4, 0xbd, 0x34, 0x04, - 0x6d, 0xb5, 0xb9, 0xe5, 0x34, 0x58, 0x75, 0xd3, 0x6a, 0xb9, 0x26, 0xa7, 0x10, 0x3f, 0x3d, 0x87, - 0x8e, 0xbf, 0xe7, 0x0d, 0xe9, 0x07, 0x7d, 0x9c, 0x6b, 0x5e, 0x27, 0x97, 0xc9, 0x87, 0x5b, 0x84, - 0x71, 0xfd, 0x67, 0x1a, 0x7a, 0x2d, 0xa1, 0x02, 0xeb, 0x50, 0x87, 0x11, 0xfc, 0x01, 0x9a, 0x0d, - 0x90, 0x94, 0x43, 0x64, 0x5e, 0x5b, 0xd0, 0x96, 0xa6, 0x0a, 0xab, 0xf9, 0x94, 0x79, 0x95, 0x8f, - 0x7a, 0x2c, 0xbd, 0xf4, 0xf5, 0xb7, 0x27, 0xf6, 0x95, 0x33, 0x34, 0x52, 0xae, 0x9f, 0x46, 0x8b, - 0x02, 0xc2, 0x23, 0xc6, 0xd6, 0x3c, 0x0e, 0xef, 0x02, 0x85, 0xbb, 0x4e, 0x93, 0x16, 0x6d, 0xdb, - 0x87, 0xfa, 0x4b, 0x0d, 0x9d, 0x4a, 0xaf, 0x07, 0x88, 0x9b, 0xe8, 0xd0, 0x60, 0x3c, 0x3c, 0xcc, - 0x63, 0x4b, 0x53, 0x85, 0xf3, 0xa9, 0x98, 0xc1, 0x75, 0xd0, 0x33, 0xc0, 0x9e, 0xe5, 0x91, 0x56, - 0x99, 0x7e, 0x03, 0x2d, 0x24, 0xe2, 0x01, 0xd0, 0xf8, 0x55, 0x34, 0x21, 0xa7, 0x96, 0xd5, 0x10, - 0x41, 0x1b, 0x2b, 0xbf, 0x22, 0x9e, 0xef, 0x36, 0xf4, 0x5f, 0x68, 0xe8, 0x64, 0x8a, 0x3d, 0x90, - 0x69, 0x20, 0x3c, 0x48, 0x06, 0xe2, 0xbf, 0x5b, 0x2e, 0x99, 0x28, 0x17, 0xfd, 0x32, 0xca, 0x0a, - 0x28, 0xeb, 0x84, 0xdf, 0xf6, 0xdc, 0xdd, 0x17, 0xf3, 0x44, 0x81, 0x04, 0x45, 0xc7, 0x62, 0x0d, - 0x01, 0xfd, 0x43, 0x34, 0x15, 0x28, 0x06, 0xd8, 0x4b, 0xa9, 0xb0, 0x03, 0xf5, 0x01, 0x6e, 0xd0, - 0x85, 0xde, 0x00, 0xa4, 0x45, 0xdb, 0x8e, 0x41, 0xba, 0x86, 0x50, 0x3f, 0x67, 0x43, 0x73, 0xaf, - 0xe7, 0x65, 0x82, 0xcf, 0x7b, 0x09, 0x3e, 0x2f, 0x97, 0x05, 0x48, 0xf0, 0xf9, 0x87, 0x66, 0x8b, - 0x80, 0x6d, 0x39, 0x60, 0xa9, 0x7f, 0xa1, 0x01, 0xaf, 0x68, 0x33, 0x49, 0xbc, 0xc6, 0x5e, 0x90, - 0x17, 0x5e, 0x0f, 0x21, 0xdf, 0x2f, 0x90, 0x9f, 0x19, 0x8a, 0x5c, 0xc2, 0x09, 0x41, 0x6f, 0xc2, - 0x8c, 0x2f, 0xda, 0xf6, 0x43, 0x99, 0xf5, 0xfe, 0x37, 0x21, 0xfa, 0xca, 0xcf, 0x1c, 0x83, 0x0d, - 0x41, 0x90, 0xde, 0x47, 0xd3, 0xe1, 0xbc, 0x0b, 0x71, 0x5a, 0x4e, 0x8d, 0x53, 0xc8, 0x17, 0x44, - 0xea, 0x60, 0x27, 0x58, 0xb8, 0x77, 0xb1, 0xf2, 0x67, 0x70, 0xb8, 0xcd, 0xae, 0xe8, 0x17, 0x85, - 0xc1, 0xff, 0x13, 0x98, 0xc0, 0xf1, 0xe6, 0x29, 0x51, 0xd0, 0xf6, 0x20, 0x0a, 0xfa, 0x1c, 0xc2, - 0xfe, 0xd4, 0x7b, 0x54, 0xa9, 0xf8, 0x59, 0xf2, 0x01, 0x3a, 0x14, 0x2a, 0x05, 0x14, 0x57, 0xd0, - 0xd8, 0xa3, 0x4a, 0x05, 0x9a, 0x5e, 0x48, 0xcf, 0x1b, 0x95, 0x0a, 0x34, 0xe8, 0x99, 0xe8, 0x77, - 0xd0, 0xab, 0x3d, 0x87, 0x8c, 0x15, 0x1b, 0x0d, 0x97, 0xb0, 0xde, 0x60, 0x5a, 0x42, 0x99, 0x9a, - 0xc5, 0xeb, 0xd4, 0x72, 0xaa, 0xbd, 0x20, 0xed, 0x17, 0x41, 0x9a, 0x86, 0xf2, 0xdb, 0x10, 0xab, - 0x5b, 0xfd, 0x0c, 0x13, 0x74, 0x03, 0xf0, 0x32, 0x68, 0x8c, 0xf0, 0xb6, 0x80, 0x37, 0x59, 0xf6, - 0xfe, 0x7a, 0x25, 0x35, 0x5e, 0x17, 0xce, 0x26, 0xcb, 0xde, 0x5f, 0xfd, 0x53, 0x0d, 0x2d, 0x0f, - 0xba, 0x28, 0x75, 0xd7, 0x2c, 0xc7, 0xb4, 0xad, 0x4f, 0x48, 0x63, 0x83, 0x58, 0xad, 0x36, 0xf7, - 0xa1, 0x15, 0xd0, 0xe1, 0xa6, 0xff, 0xa6, 0xea, 0xb1, 0xac, 0xb6, 0xc5, 0x7b, 0xe8, 0xc4, 0x43, - 0xbd, 0x97, 0x8f, 0x09, 0x37, 0xa5, 0xe9, 0x08, 0x74, 0xde, 0x43, 0xe7, 0x94, 0xb0, 0x8c, 0xc0, - 0xef, 0x03, 0x74, 0xc4, 0x5f, 0x0e, 0x36, 0x2c, 0xc6, 0xa9, 0xdb, 0xdd, 0xeb, 0x29, 0xfb, 0x07, - 0x0d, 0x1d, 0x1d, 0x68, 0x02, 0x10, 0x16, 0xd1, 0x84, 0xb7, 0xce, 0xd8, 0x16, 0xe3, 0x30, 0x4d, - 0x55, 0x47, 0xc9, 0x2b, 0x9c, 0xb1, 0x77, 0x2c, 0xc6, 0xf7, 0x6e, 0x5a, 0xb6, 0xd1, 0x9c, 0x80, - 0xb9, 0x61, 0xb2, 0xef, 0x53, 0x4e, 0x1a, 0x7e, 0x1c, 0xce, 0xa1, 0x59, 0xa9, 0x97, 0xab, 0x56, - 0x83, 0x38, 0xdc, 0x6a, 0x5a, 0xc4, 0x85, 0x98, 0x66, 0xe4, 0x8b, 0xbb, 0xbd, 0x72, 0xbc, 0x88, - 0x0e, 0x3e, 0xa5, 0x9c, 0xb8, 0x55, 0x53, 0x76, 0x0e, 0x84, 0xfa, 0x80, 0x28, 0x84, 0x0e, 0xd3, - 0x2f, 0xa1, 0xc3, 0x91, 0x96, 0x20, 0x1c, 0xc7, 0xd0, 0x64, 0xdb, 0x64, 0x55, 0xaf, 0xb2, 0x9c, - 0xf6, 0x13, 0xe5, 0x89, 0x36, 0x54, 0xd2, 0xdf, 0x45, 0x39, 0x61, 0x55, 0x12, 0x6d, 0x96, 0xba, - 0xfd, 0x56, 0x77, 0x83, 0x54, 0xff, 0x72, 0x3f, 0x3a, 0x91, 0xe8, 0x0f, 0xf0, 0x8c, 0x44, 0xfd, - 0x2d, 0x34, 0x2e, 0x58, 0x7a, 0x9c, 0xc7, 0xc4, 0x58, 0x49, 0xeb, 0x49, 0x8f, 0x93, 0xeb, 0x75, - 0x20, 0xf4, 0x27, 0xd8, 0xe2, 0xf7, 0x51, 0x46, 0xd6, 0x11, 0x9d, 0x52, 0xe5, 0xdd, 0x0e, 0x99, - 0x1f, 0x5b, 0xd0, 0x96, 0xa6, 0x0b, 0x2b, 0xe9, 0xba, 0xaf, 0x6f, 0xf4, 0xa8, 0xdb, 0x21, 0xe5, - 0x19, 0x1a, 0x2e, 0xc0, 0xf7, 0xd1, 0x41, 0xe0, 0xc2, 0xb8, 0xc9, 0xb7, 0xd8, 0xfc, 0x4b, 0xc2, - 0xeb, 0xd9, 0x54, 0xaf, 0x32, 0x36, 0x15, 0x61, 0x50, 0x3e, 0x50, 0x0b, 0x3c, 0xe9, 0x18, 0x65, - 0xa4, 0x84, 0x85, 0xba, 0x15, 0xc2, 0xf5, 0x2b, 0x68, 0x3e, 0x5a, 0xd6, 0x8b, 0xe5, 0x71, 0x34, - 0xe9, 0xbb, 0x95, 0x4b, 0xd2, 0x64, 0xb9, 0x5f, 0xa0, 0x1f, 0x81, 0xc1, 0x57, 0xd9, 0xea, 0x74, - 0xa8, 0xcb, 0x49, 0x43, 0x4c, 0x79, 0xa6, 0xd7, 0x60, 0x5d, 0x8d, 0x94, 0xf7, 0xbc, 0x96, 0xd0, - 0xb8, 0xd4, 0xf6, 0x30, 0x7d, 0x4e, 0xc5, 0xd1, 0xe9, 0x3c, 0x69, 0xe5, 0x61, 0x07, 0x20, 0xcc, - 0xfd, 0x90, 0xcb, 0x32, 0xfd, 0x26, 0xd2, 0x43, 0x6a, 0xea, 0xa1, 0xd8, 0xe0, 0xac, 0x51, 0x57, - 0x75, 0x45, 0x72, 0x41, 0x4a, 0x27, 0x39, 0x00, 0xac, 0x6f, 0xa3, 0x03, 0xd2, 0x83, 0xdc, 0x41, - 0xa9, 0xeb, 0x32, 0xe9, 0xaf, 0x3c, 0x55, 0xef, 0x3f, 0xe8, 0xc7, 0x23, 0xda, 0x11, 0xea, 0xc0, - 0x7a, 0xe4, 0x44, 0x04, 0xa2, 0xff, 0x16, 0x90, 0x3c, 0x88, 0x45, 0xb2, 0xa2, 0x8a, 0xc4, 0x1b, - 0xb6, 0x61, 0x34, 0x85, 0x3e, 0x9a, 0xfb, 0xb4, 0x41, 0x8a, 0x72, 0xe7, 0xe9, 0x87, 0x6e, 0x0e, - 0xbd, 0x6c, 0x39, 0x0d, 0xf2, 0x31, 0x4c, 0x1d, 0xf9, 0xa0, 0xff, 0xb8, 0x8f, 0x31, 0x64, 0xd3, - 0x8f, 0x56, 0x70, 0x17, 0xab, 0x14, 0xad, 0xa0, 0x9f, 0x29, 0xa7, 0xff, 0x10, 0xd4, 0xaf, 0x31, - 0xf8, 0xf6, 0x2a, 0xd3, 0x7f, 0x16, 0xd0, 0xaf, 0x71, 0x94, 0xee, 0xa1, 0xa9, 0x40, 0xb1, 0x92, - 0x7e, 0x0d, 0x31, 0x0a, 0x3c, 0xec, 0x5d, 0xda, 0x5f, 0x80, 0xb4, 0xea, 0x0d, 0x95, 0xde, 0x99, - 0x44, 0x68, 0xb7, 0xfa, 0x53, 0x0d, 0x32, 0x65, 0x5c, 0x15, 0xa0, 0xf6, 0x43, 0x94, 0x89, 0x9e, - 0x68, 0xa8, 0x8d, 0xaa, 0xb0, 0x3f, 0x98, 0x99, 0x33, 0xf5, 0x70, 0xb1, 0x7e, 0x14, 0x56, 0x8c, - 0x75, 0xc2, 0xdf, 0x16, 0x87, 0x20, 0x3e, 0xb6, 0xef, 0xc1, 0xf2, 0x1d, 0x78, 0x01, 0x88, 0xae, - 0xa3, 0x71, 0x79, 0x5e, 0x02, 0x38, 0x16, 0x53, 0x71, 0x80, 0x31, 0x98, 0xe8, 0x27, 0x40, 0x65, - 0x57, 0xda, 0xf4, 0x23, 0x3f, 0x99, 0xdd, 0x0e, 0x0c, 0x19, 0x2f, 0x26, 0xb9, 0xa4, 0x1a, 0x00, - 0xe0, 0x47, 0xe8, 0x90, 0x6d, 0x32, 0x5e, 0xf5, 0xdb, 0xa8, 0x06, 0xc7, 0x71, 0x3e, 0x15, 0xcd, - 0x3b, 0x26, 0xe3, 0x61, 0xa7, 0xb3, 0x76, 0xb4, 0x48, 0xbf, 0x07, 0x18, 0x4b, 0xb6, 0xb9, 0x49, - 0xe2, 0x96, 0xc3, 0xb3, 0x28, 0x23, 0x8e, 0xaf, 0x06, 0x17, 0xaf, 0x19, 0x51, 0x1e, 0x58, 0x0c, - 0xeb, 0xfe, 0xda, 0x3a, 0xe8, 0xab, 0xa7, 0x54, 0x10, 0x38, 0x73, 0x9a, 0x14, 0x48, 0xe8, 0xe9, - 0x6b, 0x87, 0x57, 0xbd, 0x3c, 0x29, 0x9b, 0x72, 0x9a, 0x54, 0x27, 0xfd, 0xd9, 0x21, 0xdf, 0x91, - 0x3a, 0x75, 0x1b, 0x7b, 0xbe, 0x45, 0xfa, 0x93, 0xd6, 0xdf, 0x8b, 0x85, 0xdb, 0x01, 0x2a, 0xeb, - 0x11, 0x2a, 0x63, 0x6a, 0x54, 0x60, 0x6c, 0xf6, 0x09, 0xed, 0xdd, 0x1c, 0xac, 0xc0, 0x8e, 0x08, - 0xc2, 0x2f, 0x52, 0x6d, 0xd1, 0x69, 0x88, 0x2d, 0xc7, 0xf0, 0xf5, 0xc7, 0xcb, 0xaf, 0x62, 0x93, - 0x03, 0xaa, 0x59, 0x3e, 0xe8, 0x4d, 0xd8, 0x27, 0xc5, 0x3b, 0x4d, 0xe8, 0xd6, 0xb1, 0x91, 0xbb, - 0xb5, 0xf0, 0xed, 0x69, 0xf4, 0xb2, 0x68, 0x08, 0x7f, 0xa9, 0xa1, 0x09, 0x5f, 0xd3, 0xe1, 0x0b, - 0xa9, 0x5e, 0xe2, 0x94, 0x66, 0xb6, 0x30, 0x8a, 0x89, 0x24, 0xa0, 0xdf, 0xfb, 0xf9, 0xdf, 0xff, - 0xf3, 0xeb, 0xfd, 0x6f, 0xe1, 0x92, 0x38, 0x9f, 0x5b, 0x95, 0x47, 0x75, 0xbd, 0x13, 0xba, 0x9e, - 0x9a, 0x34, 0xb6, 0x07, 0x84, 0xdc, 0x8e, 0xb1, 0x1d, 0x92, 0xaa, 0x3b, 0xf8, 0x9f, 0x1a, 0xc2, - 0x83, 0x6a, 0x10, 0x5f, 0x1f, 0x0e, 0x2b, 0x51, 0x93, 0x66, 0xdf, 0xdc, 0x9d, 0x31, 0xb0, 0xbb, - 0x23, 0xd8, 0xdd, 0xc4, 0x37, 0x62, 0xd9, 0x01, 0xa5, 0x5a, 0x37, 0xc0, 0x2a, 0x8e, 0x28, 0xfe, - 0x9d, 0x86, 0xa6, 0x02, 0x9a, 0x0c, 0xaf, 0x0e, 0x07, 0x15, 0xa8, 0x9e, 0x7d, 0x63, 0xa4, 0xea, - 0x3d, 0xf0, 0x67, 0x05, 0xf8, 0x45, 0x7c, 0x32, 0x16, 0x7c, 0x2f, 0x2d, 0x32, 0xc2, 0xf1, 0x1f, - 0x35, 0x34, 0x13, 0x91, 0x78, 0x2a, 0x03, 0x28, 0x62, 0x92, 0xbd, 0x3a, 0xb2, 0x49, 0x0f, 0xec, - 0x8a, 0x00, 0xfb, 0x3a, 0x3e, 0x15, 0x0b, 0x96, 0x45, 0xb0, 0xfd, 0x5b, 0x43, 0x47, 0xe2, 0xd5, - 0x1e, 0xbe, 0x39, 0x1c, 0x43, 0xaa, 0xd0, 0xcc, 0xde, 0xda, 0xbd, 0x03, 0xe0, 0x52, 0x12, 0x5c, - 0xde, 0xc4, 0xd7, 0x62, 0xb9, 0xb4, 0x08, 0xaf, 0x06, 0xd5, 0x5f, 0xb5, 0x49, 0x5d, 0x59, 0x60, - 0x6c, 0xfb, 0x19, 0x66, 0x07, 0x7f, 0xa6, 0xa1, 0xe9, 0x70, 0x33, 0xf8, 0xf2, 0xa8, 0xc0, 0x7c, - 0x46, 0x57, 0x46, 0x37, 0x04, 0x26, 0xab, 0x82, 0xc9, 0x19, 0x7c, 0x5a, 0x89, 0x89, 0x07, 0x3a, - 0x24, 0x92, 0xd4, 0x10, 0x0f, 0x2a, 0x42, 0x45, 0xc4, 0x31, 0x1a, 0x4f, 0x3f, 0x2f, 0x10, 0x2f, - 0xe3, 0xa5, 0x58, 0xc4, 0x01, 0x4d, 0x6a, 0x6c, 0x0b, 0x19, 0xbc, 0xe3, 0x8d, 0xfd, 0xe9, 0x80, - 0xa7, 0xa2, 0x6d, 0xab, 0xe0, 0x8e, 0x55, 0xb2, 0x2a, 0xb8, 0xe3, 0xb5, 0xa9, 0xbe, 0x24, 0x70, - 0xeb, 0x78, 0x61, 0x18, 0x6e, 0xfc, 0x67, 0x0d, 0xcd, 0x44, 0x64, 0x9b, 0x4a, 0x8a, 0x4c, 0xd4, - 0x97, 0x2a, 0x29, 0x32, 0x59, 0x79, 0x0e, 0x19, 0x22, 0x51, 0x51, 0x8a, 0x7f, 0xa3, 0xa1, 0x71, - 0x29, 0xf6, 0x70, 0x41, 0xa9, 0xdd, 0x90, 0xde, 0xcc, 0x5e, 0x1c, 0xc9, 0x06, 0x20, 0x2e, 0x0a, - 0x88, 0xaf, 0xe1, 0x63, 0xb1, 0x10, 0xa5, 0xe4, 0xc4, 0x7f, 0xd1, 0xd0, 0xec, 0x80, 0x98, 0xc4, - 0xd7, 0x14, 0x32, 0x5a, 0x82, 0x46, 0xcd, 0x5e, 0xdf, 0x95, 0x2d, 0x60, 0xbe, 0x2a, 0x30, 0x5f, - 0xc4, 0x17, 0x82, 0x98, 0x07, 0xaf, 0xc0, 0x58, 0x9b, 0x7e, 0x14, 0x51, 0xb8, 0xf8, 0x6f, 0x1a, - 0x9a, 0x1d, 0x10, 0x92, 0x2a, 0x4c, 0x92, 0x94, 0xac, 0x0a, 0x93, 0x44, 0xe5, 0xaa, 0xdf, 0x16, - 0x4c, 0x6e, 0xe0, 0xeb, 0xf1, 0x6b, 0xa8, 0x50, 0x3f, 0xd1, 0x25, 0x34, 0x22, 0x9b, 0x77, 0x3c, - 0x69, 0x83, 0xd7, 0x09, 0x8f, 0x48, 0x4a, 0xac, 0x36, 0xdf, 0x62, 0xd4, 0xae, 0xca, 0x52, 0x95, - 0xa0, 0x5f, 0xf5, 0x82, 0x20, 0xb4, 0x82, 0x97, 0x13, 0x93, 0xa2, 0x69, 0xdb, 0x55, 0xc9, 0xc1, - 0x05, 0xa0, 0xdf, 0x69, 0xe8, 0xb0, 0x70, 0xc6, 0x22, 0x4a, 0x10, 0xdf, 0x50, 0x8e, 0x6d, 0x9c, - 0x2c, 0xcd, 0xfe, 0xff, 0x6e, 0xcd, 0x81, 0xcc, 0x86, 0x20, 0x53, 0xc2, 0xb7, 0xd2, 0x7b, 0x47, - 0x4e, 0x61, 0xd3, 0x69, 0xc8, 0xe3, 0xfc, 0xc0, 0x4a, 0x65, 0x6c, 0x8b, 0x92, 0x1d, 0xfc, 0x95, - 0x86, 0x0e, 0x86, 0x0e, 0x86, 0xf1, 0xff, 0x29, 0x4d, 0xd6, 0x81, 0xf3, 0xf5, 0xec, 0xe5, 0x91, - 0xed, 0x80, 0xcc, 0x4d, 0x41, 0xe6, 0x2a, 0xbe, 0x9c, 0xd8, 0x33, 0x9c, 0x31, 0x5f, 0x6f, 0x1a, - 0xdb, 0xd1, 0x53, 0xef, 0x1d, 0xfc, 0xdb, 0xfd, 0x28, 0x97, 0x7e, 0xb8, 0x8d, 0xd7, 0x47, 0x04, - 0x97, 0x74, 0x54, 0x9f, 0xdd, 0x78, 0x71, 0x47, 0x40, 0xbb, 0x26, 0x68, 0xff, 0x00, 0x3f, 0x56, - 0xa1, 0x5d, 0x6d, 0x8b, 0x33, 0x70, 0xab, 0x6e, 0xda, 0xc6, 0x76, 0xec, 0x5d, 0xc1, 0x4e, 0x5c, - 0x64, 0x3e, 0xd5, 0xc4, 0x5d, 0x0a, 0x36, 0xd4, 0x50, 0xf7, 0xae, 0x66, 0xb2, 0xe7, 0xd5, 0x0d, - 0x80, 0xce, 0x82, 0xa0, 0x93, 0xc5, 0xf3, 0xb1, 0x74, 0x3c, 0x10, 0xbf, 0xd7, 0x10, 0xea, 0x9f, - 0xe6, 0x63, 0x85, 0x45, 0x61, 0xe0, 0x7a, 0x21, 0x7b, 0x69, 0x34, 0x23, 0xc0, 0x76, 0x46, 0x60, - 0x3b, 0x89, 0x4f, 0xc4, 0x62, 0xe3, 0x7d, 0x4c, 0x9f, 0x6b, 0x28, 0x13, 0xba, 0xce, 0xf2, 0x74, - 0x85, 0x5a, 0xd2, 0x89, 0xbb, 0xc0, 0xcc, 0x5e, 0xdb, 0x8d, 0x29, 0x80, 0x5e, 0x16, 0xa0, 0x4f, - 0x61, 0x3d, 0x16, 0x74, 0xf8, 0x96, 0xf1, 0xaf, 0x1a, 0x9a, 0x8b, 0xbb, 0xd9, 0x53, 0xc9, 0x53, - 0x29, 0x17, 0x8a, 0x2a, 0x79, 0x2a, 0xed, 0x42, 0x51, 0x7f, 0x43, 0x70, 0x30, 0xf0, 0xea, 0x70, - 0x0e, 0x41, 0x19, 0xfd, 0xb9, 0x16, 0xba, 0xb3, 0x1e, 0x45, 0x43, 0x87, 0xe3, 0x7f, 0x65, 0x74, - 0x43, 0x40, 0x7e, 0x51, 0x20, 0x5f, 0xc5, 0xe7, 0xe2, 0x05, 0x52, 0xdf, 0x22, 0x88, 0xdb, 0x13, - 0xa5, 0x01, 0x67, 0xea, 0xa2, 0x74, 0x77, 0xd0, 0xe3, 0x2f, 0xfc, 0x87, 0x88, 0xd2, 0x00, 0x74, - 0x4f, 0x3d, 0xcd, 0xc5, 0x7d, 0xd1, 0xa1, 0x32, 0x6c, 0x52, 0xbe, 0x24, 0x51, 0x19, 0x36, 0x69, - 0x1f, 0x92, 0x0c, 0xd9, 0x0e, 0xb4, 0x44, 0x7e, 0x0d, 0x59, 0xe3, 0x7f, 0x68, 0xe8, 0x68, 0xc2, - 0xb7, 0x36, 0xf8, 0xd6, 0xee, 0xd0, 0xf4, 0x3f, 0xe7, 0xc9, 0x16, 0x5f, 0xc0, 0x03, 0x50, 0xba, - 0x24, 0x28, 0xe5, 0xf1, 0x4a, 0x12, 0xa5, 0xa2, 0x6d, 0x47, 0x7d, 0x30, 0xfc, 0x85, 0x86, 0x32, - 0xd1, 0x6f, 0x93, 0x54, 0xf2, 0x51, 0xc2, 0x27, 0x54, 0x2a, 0xf9, 0x28, 0xe9, 0xe3, 0xaa, 0x21, - 0x5b, 0x86, 0xe8, 0x97, 0x52, 0xa5, 0x3b, 0x5f, 0x3f, 0xcb, 0x69, 0xdf, 0x3c, 0xcb, 0x69, 0xdf, - 0x3d, 0xcb, 0x69, 0xbf, 0x7a, 0x9e, 0xdb, 0xf7, 0xcd, 0xf3, 0xdc, 0xbe, 0x7f, 0x3d, 0xcf, 0xed, - 0x7b, 0x7c, 0xae, 0x65, 0xf1, 0xf6, 0x56, 0x2d, 0x5f, 0xa7, 0x9b, 0x41, 0x57, 0xde, 0x6e, 0xc9, - 0xf8, 0x38, 0x90, 0x96, 0xbb, 0x1d, 0xc2, 0x6a, 0xe3, 0xe2, 0xdb, 0xb0, 0x8b, 0xff, 0x0d, 0x00, - 0x00, 0xff, 0xff, 0x5b, 0xa6, 0xcd, 0x80, 0x40, 0x29, 0x00, 0x00, + 0x15, 0xf6, 0x5a, 0x89, 0x2d, 0x8d, 0x6c, 0x89, 0x1a, 0xcb, 0xb6, 0x42, 0x2b, 0xb4, 0xbc, 0x92, + 0x6d, 0x59, 0x96, 0xb8, 0x12, 0xed, 0xd4, 0xbf, 0xe2, 0xda, 0xa4, 0x62, 0x49, 0x76, 0x12, 0xdb, + 0x21, 0xdd, 0x06, 0x30, 0x9a, 0x32, 0x4b, 0x72, 0x48, 0x6e, 0xbd, 0xda, 0x61, 0x76, 0x56, 0x4e, + 0x18, 0x55, 0x40, 0xdb, 0x5b, 0x73, 0x28, 0x0a, 0xb4, 0x68, 0x6f, 0x45, 0x0f, 0xed, 0xb1, 0x40, + 0x11, 0x20, 0x40, 0x80, 0x22, 0x87, 0x9c, 0x9a, 0x43, 0x0f, 0x29, 0x5a, 0x14, 0x3d, 0xb5, 0x81, + 0xdd, 0x7f, 0xa1, 0xf7, 0x62, 0x67, 0xde, 0x92, 0xbb, 0xcb, 0xdd, 0xe5, 0x50, 0x66, 0x4f, 0xe4, + 0xce, 0xce, 0x7b, 0xf3, 0x7d, 0x6f, 0x66, 0xde, 0x7c, 0x33, 0xb3, 0xe8, 0xfc, 0xc7, 0xc4, 0xd1, + 0xab, 0x4d, 0xdd, 0xb0, 0x34, 0xfe, 0x8f, 0xda, 0x44, 0xa3, 0x15, 0x46, 0xec, 0xa7, 0xc4, 0xd6, + 0x3e, 0xd8, 0x21, 0x76, 0x3b, 0xdb, 0xb2, 0xa9, 0x43, 0xf1, 0xa9, 0x4e, 0xc5, 0xac, 0x57, 0x31, + 0xeb, 0x55, 0x4c, 0x2f, 0x55, 0x29, 0xdb, 0xa6, 0x4c, 0xab, 0xe8, 0x8c, 0x08, 0x2b, 0xed, 0xe9, + 0x5a, 0x85, 0x38, 0xfa, 0x9a, 0xd6, 0xd2, 0x1b, 0x86, 0xa5, 0x3b, 0x06, 0xb5, 0x84, 0xa3, 0xf4, + 0x74, 0x83, 0x36, 0x28, 0xff, 0xab, 0xb9, 0xff, 0xa0, 0x74, 0xb6, 0x41, 0x69, 0xc3, 0x24, 0x9a, + 0xde, 0x32, 0x34, 0xdd, 0xb2, 0xa8, 0xc3, 0x4d, 0x18, 0xbc, 0x5d, 0x4c, 0x42, 0x59, 0xd1, 0x4d, + 0x93, 0x3a, 0x50, 0x33, 0x91, 0x4f, 0xc5, 0xd4, 0xb7, 0x09, 0x54, 0xcc, 0x26, 0x55, 0xe4, 0xe5, + 0x65, 0x8b, 0x5a, 0x55, 0xe2, 0x41, 0xc8, 0x25, 0xd6, 0xb7, 0x29, 0x63, 0xc2, 0xa8, 0x6e, 0xea, + 0x0d, 0x29, 0xd8, 0x4f, 0x48, 0xbb, 0x41, 0x2c, 0x19, 0x34, 0x16, 0xad, 0x91, 0xb2, 0x5e, 0xad, + 0xd2, 0x1d, 0xcb, 0xa3, 0xb9, 0x94, 0x54, 0xdf, 0xfb, 0x23, 0x83, 0xa2, 0xa5, 0xdb, 0xfa, 0xb6, + 0x87, 0x77, 0x35, 0xb1, 0x26, 0xb1, 0x6a, 0x86, 0xd5, 0x08, 0x46, 0xe5, 0x6c, 0x92, 0x85, 0xc3, + 0xbc, 0x6a, 0x2b, 0x89, 0x70, 0x5b, 0xc4, 0xe6, 0xbd, 0xad, 0x9b, 0x09, 0xec, 0x5a, 0x4f, 0x1a, + 0xa2, 0x5b, 0x18, 0xfc, 0xf4, 0xa9, 0xdb, 0xb2, 0x29, 0xad, 0x33, 0xf8, 0x81, 0xba, 0x97, 0xfb, + 0xa0, 0x2d, 0xd7, 0x77, 0xac, 0x1a, 0x2b, 0x6f, 0x1b, 0x0d, 0x5b, 0x77, 0x28, 0xc4, 0x4f, 0x7d, + 0x0f, 0x1d, 0x7b, 0xc7, 0x1d, 0xd2, 0x05, 0x3e, 0xce, 0x58, 0x91, 0x7c, 0xb0, 0x43, 0x98, 0x83, + 0x37, 0x10, 0xea, 0x8e, 0xed, 0x19, 0x65, 0x4e, 0x59, 0x1c, 0xcf, 0x9d, 0xcb, 0x8a, 0x89, 0x90, + 0x75, 0x27, 0x42, 0x56, 0x4c, 0x1f, 0x98, 0x08, 0xd9, 0x87, 0x7a, 0x83, 0x80, 0x6d, 0xd1, 0x67, + 0xa9, 0xfe, 0x4e, 0x41, 0xd3, 0x41, 0xff, 0xac, 0x45, 0x2d, 0x46, 0xf0, 0x3a, 0x3a, 0x2c, 0x86, + 0x36, 0x9b, 0x51, 0xe6, 0x46, 0x16, 0xc7, 0x73, 0xf3, 0xd9, 0x84, 0x39, 0x98, 0x15, 0xe6, 0x85, + 0x97, 0xbe, 0xfa, 0xd7, 0xe9, 0x03, 0x45, 0xcf, 0x12, 0x6f, 0x06, 0x50, 0x1e, 0xe4, 0x28, 0xcf, + 0xf7, 0x45, 0x29, 0x10, 0x04, 0x60, 0x66, 0xd0, 0x2c, 0x47, 0xf9, 0xa0, 0xdb, 0x5b, 0x1b, 0xee, + 0x50, 0x07, 0x4a, 0xea, 0x8f, 0x15, 0xf4, 0x6a, 0x4c, 0x05, 0xe0, 0xf3, 0x3e, 0x9a, 0xf2, 0x75, + 0xb5, 0x98, 0x28, 0x10, 0xb7, 0x95, 0x44, 0x66, 0x61, 0x8f, 0xc0, 0x31, 0x45, 0x43, 0xe5, 0xea, + 0x59, 0x34, 0xcf, 0x21, 0x3c, 0x62, 0x6c, 0xc3, 0xed, 0xc9, 0xb7, 0xa1, 0x23, 0xef, 0x5a, 0x75, + 0x9a, 0x37, 0x4d, 0x0f, 0xea, 0xcf, 0x14, 0xb4, 0x90, 0x5c, 0x0f, 0x10, 0xd7, 0xd1, 0xb1, 0xde, + 0x51, 0xe1, 0xf5, 0xc6, 0x6a, 0x22, 0x66, 0x70, 0xed, 0xf7, 0x0c, 0xb0, 0xa7, 0x9c, 0x50, 0xab, + 0x4c, 0xbd, 0x89, 0xe6, 0x62, 0xf1, 0x78, 0xc3, 0xed, 0x15, 0x34, 0x2a, 0x12, 0x8c, 0x51, 0xe3, + 0x41, 0x1b, 0x29, 0x1e, 0xe6, 0xcf, 0x77, 0x6b, 0xea, 0x4f, 0x15, 0x74, 0x26, 0xc1, 0x1e, 0xc8, + 0xd4, 0x10, 0xee, 0x25, 0x03, 0xf1, 0xdf, 0x2f, 0x97, 0x54, 0x98, 0x8b, 0x7a, 0x05, 0xa5, 0x39, + 0x94, 0x4d, 0xe2, 0xac, 0xbb, 0xee, 0xee, 0xf3, 0x6c, 0x21, 0x41, 0x82, 0xa2, 0x53, 0x91, 0x86, + 0x80, 0xfe, 0x21, 0x1a, 0xf7, 0x15, 0x03, 0xec, 0xc5, 0x44, 0xd8, 0xbe, 0xfa, 0x00, 0xd7, 0xef, + 0x42, 0xad, 0x01, 0xd2, 0xbc, 0x69, 0x46, 0x20, 0x1d, 0xd6, 0xec, 0xfe, 0x5c, 0x01, 0x5e, 0xe1, + 0x66, 0xe2, 0x78, 0x8d, 0xbc, 0x20, 0xaf, 0xe1, 0xcd, 0xf8, 0x3a, 0xcc, 0xf8, 0xbc, 0x69, 0x3e, + 0x14, 0xb9, 0xff, 0xff, 0x13, 0xa2, 0x2f, 0xbd, 0xcc, 0xd1, 0xdb, 0x10, 0x04, 0xe9, 0x5d, 0x34, + 0x11, 0x5c, 0x7d, 0x20, 0x4e, 0x4b, 0x89, 0x71, 0x0a, 0xf8, 0x82, 0x48, 0x1d, 0x6d, 0xf9, 0x0b, + 0x87, 0x17, 0x2b, 0x6f, 0x06, 0x07, 0xdb, 0x6c, 0xf3, 0x7e, 0x91, 0x18, 0xfc, 0x3f, 0x84, 0x09, + 0x1c, 0x6d, 0x9e, 0x10, 0x05, 0x65, 0x08, 0x51, 0x50, 0xa7, 0x11, 0xf6, 0xa6, 0xde, 0xa3, 0x52, + 0xc9, 0xcb, 0x92, 0x0f, 0x60, 0xd9, 0xf3, 0x4a, 0x01, 0xc5, 0x55, 0x34, 0xf2, 0xa8, 0x54, 0x82, + 0xa6, 0xe7, 0x92, 0xf3, 0x46, 0xa9, 0x04, 0x0d, 0xba, 0x26, 0xea, 0x1d, 0xf4, 0x4a, 0xc7, 0x21, + 0x63, 0xf9, 0x5a, 0xcd, 0x26, 0xac, 0x33, 0x98, 0x16, 0x51, 0xaa, 0x62, 0x38, 0x55, 0x6a, 0x58, + 0xe5, 0x4e, 0x90, 0x0e, 0xf2, 0x20, 0x4d, 0x40, 0xf9, 0x3a, 0xc4, 0xea, 0x76, 0x37, 0xc3, 0xf8, + 0xdd, 0x00, 0xbc, 0x14, 0x1a, 0x21, 0x4e, 0x93, 0xc3, 0x1b, 0x2b, 0xba, 0x7f, 0xdd, 0x92, 0x8a, + 0x53, 0xe5, 0xce, 0xc6, 0x8a, 0xee, 0x5f, 0xf5, 0x13, 0x05, 0x2d, 0xf5, 0xba, 0x28, 0xb4, 0x37, + 0x0c, 0x4b, 0x37, 0x8d, 0x8f, 0x49, 0x6d, 0x8b, 0x18, 0x8d, 0xa6, 0xe3, 0x41, 0xcb, 0xa1, 0xe3, + 0x75, 0xef, 0x4d, 0xd9, 0x65, 0x59, 0x6e, 0xf2, 0xf7, 0xd0, 0x89, 0xc7, 0x3a, 0x2f, 0x1f, 0x13, + 0x47, 0x17, 0xa6, 0x03, 0xd0, 0x79, 0x07, 0x5d, 0x94, 0xc2, 0x32, 0x00, 0xbf, 0xf7, 0xd1, 0x09, + 0x6f, 0x39, 0xd8, 0x32, 0x98, 0x43, 0xed, 0xf6, 0xb0, 0xa7, 0xec, 0xef, 0x15, 0x74, 0xb2, 0xa7, + 0x09, 0x40, 0x98, 0x47, 0xa3, 0xee, 0x3a, 0x63, 0x1a, 0xcc, 0x81, 0x69, 0x2a, 0x3b, 0x4a, 0x0e, + 0x3b, 0x8c, 0xbd, 0x65, 0x30, 0x67, 0x78, 0xd3, 0xb2, 0x09, 0xd2, 0x6a, 0x4b, 0x67, 0xdf, 0xa5, + 0x0e, 0xa9, 0x79, 0x71, 0xb8, 0x88, 0xa6, 0x84, 0x40, 0x2a, 0x1b, 0x35, 0x62, 0x39, 0x46, 0xdd, + 0x20, 0x36, 0xc4, 0x34, 0x25, 0x5e, 0xdc, 0xed, 0x94, 0xe3, 0x79, 0x74, 0xf4, 0x29, 0x75, 0x88, + 0x5d, 0xd6, 0x45, 0xe7, 0x40, 0xa8, 0x8f, 0xf0, 0x42, 0xe8, 0x30, 0xf5, 0x32, 0x3a, 0x1e, 0x6a, + 0x09, 0xc2, 0x71, 0x0a, 0x8d, 0x35, 0x75, 0x56, 0x76, 0x2b, 0x8b, 0x69, 0x3f, 0x5a, 0x1c, 0x6d, + 0x42, 0x25, 0xf5, 0x6d, 0x94, 0xf1, 0x49, 0xbf, 0x42, 0xbb, 0xdb, 0xea, 0x7e, 0x90, 0xaa, 0x5f, + 0x1c, 0x44, 0xa7, 0x63, 0xfd, 0x01, 0x9e, 0x81, 0xa8, 0xbf, 0x81, 0x0e, 0x71, 0x96, 0x2e, 0xe7, + 0x11, 0x3e, 0x56, 0x92, 0x7a, 0xd2, 0xe5, 0x64, 0xbb, 0x1d, 0x08, 0xfd, 0x09, 0xb6, 0xf8, 0x5d, + 0x94, 0x12, 0x75, 0x78, 0xa7, 0x94, 0x9d, 0x76, 0x8b, 0xcc, 0x8c, 0xcc, 0x29, 0x8b, 0x13, 0xb9, + 0xe5, 0x64, 0xdd, 0xd7, 0x35, 0x7a, 0xd4, 0x6e, 0x91, 0xe2, 0x24, 0x0d, 0x16, 0xe0, 0xfb, 0xe8, + 0x28, 0x70, 0x61, 0x8e, 0xee, 0xec, 0xb0, 0x99, 0x97, 0xb8, 0xd7, 0x0b, 0x12, 0x3a, 0xb9, 0xc4, + 0x0d, 0x8a, 0x47, 0x2a, 0xbe, 0x27, 0x15, 0xa3, 0x94, 0x90, 0xb0, 0x50, 0xb7, 0x44, 0x1c, 0xf5, + 0x2a, 0x9a, 0x09, 0x97, 0x75, 0x62, 0x39, 0x8b, 0xc6, 0x3c, 0xb7, 0x62, 0x49, 0x1a, 0x2b, 0x76, + 0x0b, 0xd4, 0x13, 0x30, 0xf8, 0x4a, 0x3b, 0xad, 0x16, 0xb5, 0x1d, 0x52, 0xe3, 0x53, 0x9e, 0xa9, + 0x15, 0x58, 0x57, 0x43, 0xe5, 0x1d, 0xaf, 0x05, 0x74, 0x48, 0xec, 0x70, 0x60, 0xfa, 0x2c, 0x44, + 0xd1, 0x69, 0x3d, 0x69, 0x64, 0x61, 0x1f, 0xc4, 0xcd, 0xbd, 0x90, 0x8b, 0x32, 0xf5, 0x16, 0x52, + 0x03, 0x6a, 0xea, 0x21, 0xdf, 0xe6, 0x6d, 0x50, 0x5b, 0x76, 0x45, 0xb2, 0x41, 0x4a, 0xc7, 0x39, + 0x00, 0xac, 0x6f, 0xa2, 0x23, 0xc2, 0x83, 0xd8, 0x47, 0xca, 0xeb, 0x32, 0xe1, 0xaf, 0x38, 0x5e, + 0xed, 0x3e, 0xa8, 0xb3, 0x21, 0xed, 0x08, 0x75, 0x60, 0x3d, 0xb2, 0x42, 0x02, 0xd1, 0x7b, 0x0b, + 0x48, 0x1e, 0x44, 0x22, 0x59, 0x96, 0x45, 0xe2, 0x0e, 0xdb, 0x20, 0x9a, 0x5c, 0x17, 0xcd, 0x7d, + 0x5a, 0x23, 0x79, 0xb1, 0xff, 0xf6, 0x42, 0x37, 0x8d, 0x5e, 0x36, 0xac, 0x1a, 0xf9, 0x08, 0xa6, + 0x8e, 0x78, 0x50, 0x7f, 0xd0, 0xc5, 0x18, 0xb0, 0xe9, 0x46, 0xcb, 0xbf, 0x97, 0x97, 0x8a, 0x96, + 0xdf, 0xcf, 0xb8, 0xd5, 0x7d, 0xf0, 0xeb, 0xd7, 0x08, 0x7c, 0xc3, 0xca, 0xf4, 0x9f, 0xfa, 0xf4, + 0x6b, 0x14, 0xa5, 0x7b, 0x68, 0xdc, 0x57, 0x2c, 0xa5, 0x5f, 0x03, 0x8c, 0x7c, 0x0f, 0xc3, 0x4b, + 0xfb, 0x73, 0x90, 0x56, 0xdd, 0xa1, 0xd2, 0x39, 0x99, 0x09, 0xec, 0x56, 0x7f, 0xa4, 0x40, 0xa6, + 0x8c, 0xaa, 0x02, 0xd4, 0xde, 0x43, 0xa9, 0xf0, 0xb9, 0x8e, 0xdc, 0xa8, 0x0a, 0xfa, 0x83, 0x99, + 0x39, 0x59, 0x0d, 0x16, 0xab, 0x27, 0x61, 0xc5, 0xd8, 0x24, 0xce, 0x9b, 0xfc, 0x28, 0xc8, 0xc3, + 0xf6, 0x1d, 0x58, 0xbe, 0x7d, 0x2f, 0x00, 0xd1, 0x0d, 0x74, 0x48, 0x9c, 0x1a, 0x01, 0x8e, 0xe4, + 0x03, 0x01, 0x30, 0x06, 0x13, 0xf5, 0x34, 0xa8, 0xec, 0x52, 0x93, 0x7e, 0xe8, 0x25, 0xb3, 0x75, + 0xdf, 0x90, 0x71, 0x63, 0x92, 0x89, 0xab, 0x01, 0x00, 0xbe, 0x8f, 0x8e, 0x99, 0x3a, 0x73, 0xca, + 0x5e, 0x1b, 0x65, 0xff, 0x38, 0xce, 0x26, 0xa2, 0x79, 0x4b, 0x67, 0x4e, 0xd0, 0xe9, 0x94, 0x19, + 0x2e, 0x52, 0xef, 0x01, 0xc6, 0x82, 0xa9, 0x6f, 0x93, 0xa8, 0xe5, 0xf0, 0x02, 0x4a, 0xf1, 0x43, + 0xbc, 0xde, 0xc5, 0x6b, 0x92, 0x97, 0xfb, 0x16, 0xc3, 0xaa, 0xb7, 0xb6, 0xf6, 0xfa, 0xea, 0x28, + 0x15, 0x04, 0xce, 0xac, 0x3a, 0x05, 0x12, 0x6a, 0xf2, 0xda, 0xe1, 0x56, 0x2f, 0x8e, 0x89, 0xa6, + 0xac, 0x3a, 0x55, 0x49, 0x77, 0x76, 0x88, 0x77, 0xa4, 0x4a, 0xed, 0xda, 0xd0, 0xb7, 0x48, 0x7f, + 0x54, 0xba, 0x7b, 0xb1, 0x60, 0x3b, 0x40, 0x65, 0x33, 0x44, 0x65, 0x44, 0x8e, 0x0a, 0x8c, 0xcd, + 0x2e, 0xa1, 0xe1, 0xcd, 0xc1, 0x12, 0xec, 0x88, 0x20, 0xfc, 0x3c, 0xd5, 0xe6, 0xad, 0x1a, 0xdf, + 0x72, 0xf4, 0x5f, 0x7f, 0xdc, 0xfc, 0xca, 0x37, 0x39, 0xa0, 0x9a, 0xc5, 0x83, 0x5a, 0x87, 0x7d, + 0x52, 0xb4, 0xd3, 0x98, 0x6e, 0x1d, 0x19, 0xb8, 0x5b, 0x73, 0xff, 0x3d, 0x87, 0x5e, 0xe6, 0x0d, + 0xe1, 0x2f, 0x14, 0x34, 0xea, 0x69, 0x3a, 0xbc, 0x96, 0xe8, 0x25, 0x4a, 0x69, 0xa6, 0x73, 0x83, + 0x98, 0x08, 0x02, 0xea, 0xbd, 0x9f, 0xfc, 0xed, 0x3f, 0xbf, 0x38, 0xf8, 0x06, 0x2e, 0xf0, 0x53, + 0xca, 0x15, 0x71, 0x60, 0xd9, 0x39, 0xa7, 0xec, 0xa8, 0x49, 0x6d, 0xb7, 0x47, 0xc8, 0xed, 0x69, + 0xbb, 0x01, 0xa9, 0xba, 0x87, 0xff, 0xa1, 0x20, 0xdc, 0xab, 0x06, 0xf1, 0x8d, 0xfe, 0xb0, 0x62, + 0x35, 0x69, 0xfa, 0xf5, 0xfd, 0x19, 0x03, 0xbb, 0x3b, 0x9c, 0xdd, 0x2d, 0x7c, 0x33, 0x92, 0x1d, + 0x50, 0xaa, 0xb4, 0x7d, 0xac, 0xa2, 0x88, 0xe2, 0xdf, 0x28, 0x68, 0xdc, 0xa7, 0xc9, 0xf0, 0x4a, + 0x7f, 0x50, 0xbe, 0xea, 0xe9, 0xd7, 0x06, 0xaa, 0xde, 0x01, 0x7f, 0x81, 0x83, 0x9f, 0xc7, 0x67, + 0x22, 0xc1, 0x77, 0xd2, 0x22, 0x23, 0x0e, 0xfe, 0x83, 0x82, 0x26, 0x43, 0x12, 0x4f, 0x66, 0x00, + 0x85, 0x4c, 0xd2, 0xd7, 0x06, 0x36, 0xe9, 0x80, 0x5d, 0xe6, 0x60, 0xcf, 0xe1, 0x85, 0x48, 0xb0, + 0x2c, 0x84, 0xed, 0xdf, 0x0a, 0x3a, 0x11, 0xad, 0xf6, 0xf0, 0xad, 0xfe, 0x18, 0x12, 0x85, 0x66, + 0xfa, 0xf6, 0xfe, 0x1d, 0x00, 0x97, 0x02, 0xe7, 0xf2, 0x3a, 0xbe, 0x1e, 0xc9, 0xa5, 0x41, 0x9c, + 0xb2, 0x5f, 0xfd, 0x95, 0xeb, 0xd4, 0x16, 0x05, 0xda, 0xae, 0x97, 0x61, 0xf6, 0xf0, 0xa7, 0x0a, + 0x9a, 0x08, 0x36, 0x83, 0xaf, 0x0c, 0x0a, 0xcc, 0x63, 0x74, 0x75, 0x70, 0x43, 0x60, 0xb2, 0xc2, + 0x99, 0x9c, 0xc7, 0x67, 0xa5, 0x98, 0xb8, 0xa0, 0x03, 0x22, 0x49, 0x0e, 0x71, 0xaf, 0x22, 0x94, + 0x44, 0x1c, 0xa1, 0xf1, 0xd4, 0x55, 0x8e, 0x78, 0x09, 0x2f, 0x46, 0x22, 0xf6, 0x69, 0x52, 0x6d, + 0x97, 0xcb, 0xe0, 0x3d, 0x77, 0xec, 0x4f, 0xf8, 0x3c, 0xe5, 0x4d, 0x53, 0x06, 0x77, 0xa4, 0x92, + 0x95, 0xc1, 0x1d, 0xad, 0x4d, 0xd5, 0x45, 0x8e, 0x5b, 0xc5, 0x73, 0xfd, 0x70, 0xe3, 0x3f, 0x29, + 0x68, 0x32, 0x24, 0xdb, 0x64, 0x52, 0x64, 0xac, 0xbe, 0x94, 0x49, 0x91, 0xf1, 0xca, 0xb3, 0xcf, + 0x10, 0x09, 0x8b, 0x52, 0xfc, 0x2b, 0x05, 0x1d, 0x12, 0x62, 0x0f, 0xe7, 0xa4, 0xda, 0x0d, 0xe8, + 0xcd, 0xf4, 0xa5, 0x81, 0x6c, 0x00, 0xe2, 0x3c, 0x87, 0xf8, 0x2a, 0x3e, 0x15, 0x09, 0x51, 0x48, + 0x4e, 0xfc, 0x67, 0x05, 0x4d, 0xf5, 0x88, 0x49, 0x7c, 0x5d, 0x22, 0xa3, 0xc5, 0x68, 0xd4, 0xf4, + 0x8d, 0x7d, 0xd9, 0x02, 0xe6, 0x6b, 0x1c, 0xf3, 0x25, 0xbc, 0xe6, 0xc7, 0xdc, 0x7b, 0x11, 0xc8, + 0x9a, 0xf4, 0xc3, 0x90, 0xc2, 0xc5, 0x7f, 0x55, 0xd0, 0x54, 0x8f, 0x90, 0x94, 0x61, 0x12, 0xa7, + 0x64, 0x65, 0x98, 0xc4, 0x2a, 0x57, 0x75, 0x9d, 0x33, 0xb9, 0x89, 0x6f, 0x44, 0xaf, 0xa1, 0x5c, + 0xfd, 0x84, 0x97, 0xd0, 0x90, 0x6c, 0xde, 0x73, 0xa5, 0x0d, 0xde, 0x24, 0x4e, 0x48, 0x52, 0x62, + 0xb9, 0xf9, 0x16, 0xa1, 0x76, 0x65, 0x96, 0xaa, 0x18, 0xfd, 0xaa, 0xe6, 0x38, 0xa1, 0x65, 0xbc, + 0x14, 0x9b, 0x14, 0x75, 0xd3, 0x2c, 0x0b, 0x0e, 0x36, 0x00, 0xfd, 0x46, 0x41, 0xc7, 0xb9, 0x33, + 0x16, 0x52, 0x82, 0xf8, 0xa6, 0x74, 0x6c, 0xa3, 0x64, 0x69, 0xfa, 0xdb, 0xfb, 0x35, 0x07, 0x32, + 0x5b, 0x9c, 0x4c, 0x01, 0xdf, 0x4e, 0xee, 0x1d, 0x31, 0x85, 0x75, 0xab, 0x26, 0x8e, 0xf3, 0x7d, + 0x2b, 0x95, 0xb6, 0xcb, 0x4b, 0xf6, 0xf0, 0x97, 0x0a, 0x3a, 0x1a, 0x38, 0x18, 0xc6, 0xdf, 0x92, + 0x9a, 0xac, 0x3d, 0xe7, 0xeb, 0xe9, 0x2b, 0x03, 0xdb, 0x01, 0x99, 0x5b, 0x9c, 0xcc, 0x35, 0x7c, + 0x25, 0xb6, 0x67, 0x1c, 0xc6, 0x3c, 0xbd, 0xa9, 0xed, 0x86, 0x4f, 0xbd, 0xf7, 0xf0, 0xaf, 0x0f, + 0xa2, 0x4c, 0xf2, 0xe1, 0x36, 0xde, 0x1c, 0x10, 0x5c, 0xdc, 0x51, 0x7d, 0x7a, 0xeb, 0xc5, 0x1d, + 0x01, 0xed, 0x0a, 0xa7, 0xfd, 0x3d, 0xfc, 0x58, 0x86, 0x76, 0xb9, 0xc9, 0xcf, 0xc0, 0x8d, 0xaa, + 0x6e, 0x6a, 0xbb, 0x91, 0x77, 0x05, 0x7b, 0x51, 0x91, 0xf9, 0x44, 0xe1, 0x77, 0x29, 0x58, 0x93, + 0x43, 0xdd, 0xb9, 0x9a, 0x49, 0xaf, 0xca, 0x1b, 0x00, 0x9d, 0x39, 0x4e, 0x27, 0x8d, 0x67, 0x22, + 0xe9, 0xb8, 0x20, 0x7e, 0xab, 0x20, 0xd4, 0x3d, 0xcd, 0xc7, 0x12, 0x8b, 0x42, 0xcf, 0xf5, 0x42, + 0xfa, 0xf2, 0x60, 0x46, 0x80, 0xed, 0x3c, 0xc7, 0x76, 0x06, 0x9f, 0x8e, 0xc4, 0xe6, 0x74, 0x31, + 0x7d, 0xa6, 0xa0, 0x54, 0xe0, 0x3a, 0xcb, 0xd5, 0x15, 0x72, 0x49, 0x27, 0xea, 0x02, 0x33, 0x7d, + 0x7d, 0x3f, 0xa6, 0x00, 0x7a, 0x89, 0x83, 0x5e, 0xc0, 0x6a, 0x24, 0xe8, 0xe0, 0x2d, 0xe3, 0x5f, + 0x14, 0x34, 0x1d, 0x75, 0xb3, 0x27, 0x93, 0xa7, 0x12, 0x2e, 0x14, 0x65, 0xf2, 0x54, 0xd2, 0x85, + 0xa2, 0xfa, 0x1a, 0xe7, 0xa0, 0xe1, 0x95, 0xfe, 0x1c, 0xfc, 0x32, 0xfa, 0x33, 0x25, 0x70, 0x67, + 0x3d, 0x88, 0x86, 0x0e, 0xc6, 0xff, 0xea, 0xe0, 0x86, 0x80, 0xfc, 0x12, 0x47, 0xbe, 0x82, 0x2f, + 0x46, 0x0b, 0xa4, 0xae, 0x85, 0x1f, 0xb7, 0x2b, 0x4a, 0x7d, 0xce, 0xe4, 0x45, 0xe9, 0xfe, 0xa0, + 0x47, 0x5f, 0xf8, 0xf7, 0x11, 0xa5, 0x3e, 0xe8, 0xae, 0x7a, 0x9a, 0x8e, 0xfa, 0xa2, 0x43, 0x66, + 0xd8, 0x24, 0x7c, 0x49, 0x22, 0x33, 0x6c, 0x92, 0x3e, 0x24, 0xe9, 0xb3, 0x1d, 0x68, 0xf0, 0xfc, + 0x1a, 0xb0, 0xc6, 0x7f, 0x57, 0xd0, 0xc9, 0x98, 0x6f, 0x6d, 0xf0, 0xed, 0xfd, 0xa1, 0xe9, 0x7e, + 0xce, 0x93, 0xce, 0xbf, 0x80, 0x07, 0xa0, 0x74, 0x99, 0x53, 0xca, 0xe2, 0xe5, 0x38, 0x4a, 0x79, + 0xd3, 0x0c, 0xfb, 0x60, 0xf8, 0x73, 0x05, 0xa5, 0xc2, 0xdf, 0x26, 0xc9, 0xe4, 0xa3, 0x98, 0x4f, + 0xa8, 0x64, 0xf2, 0x51, 0xdc, 0xc7, 0x55, 0x7d, 0xb6, 0x0c, 0xe1, 0x2f, 0xa5, 0xf0, 0x2f, 0x15, + 0x74, 0x18, 0xbe, 0x37, 0xc3, 0xab, 0xb2, 0xc7, 0x39, 0x1d, 0xa0, 0x6b, 0x03, 0x58, 0x00, 0xbe, + 0x05, 0x8e, 0x2f, 0x83, 0x67, 0x13, 0x4e, 0x7d, 0x58, 0xe1, 0xce, 0x57, 0xcf, 0x32, 0xca, 0xd7, + 0xcf, 0x32, 0xca, 0x37, 0xcf, 0x32, 0xca, 0xcf, 0x9f, 0x67, 0x0e, 0x7c, 0xfd, 0x3c, 0x73, 0xe0, + 0x9f, 0xcf, 0x33, 0x07, 0x1e, 0x5f, 0x6c, 0x18, 0x4e, 0x73, 0xa7, 0x92, 0xad, 0xd2, 0x6d, 0xbf, + 0x07, 0x77, 0x13, 0xa7, 0x7d, 0xe4, 0x5b, 0x2d, 0xda, 0x2d, 0xc2, 0x2a, 0x87, 0xf8, 0x87, 0x7b, + 0x97, 0xfe, 0x17, 0x00, 0x00, 0xff, 0xff, 0x46, 0x09, 0xce, 0x82, 0xdd, 0x2a, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -2536,6 +2638,8 @@ type QueryClient interface { TssFundsMigratorInfoAll(ctx context.Context, in *QueryTssFundsMigratorInfoAllRequest, opts ...grpc.CallOption) (*QueryTssFundsMigratorInfoAllResponse, error) // Queries operational flags OperationalFlags(ctx context.Context, in *QueryOperationalFlagsRequest, opts ...grpc.CallOption) (*QueryOperationalFlagsResponse, error) + // Query all ballots + Ballots(ctx context.Context, in *QueryBallotsRequest, opts ...grpc.CallOption) (*QueryBallotsResponse, error) } type queryClient struct { @@ -2771,6 +2875,15 @@ func (c *queryClient) OperationalFlags(ctx context.Context, in *QueryOperational return out, nil } +func (c *queryClient) Ballots(ctx context.Context, in *QueryBallotsRequest, opts ...grpc.CallOption) (*QueryBallotsResponse, error) { + out := new(QueryBallotsResponse) + err := c.cc.Invoke(ctx, "/zetachain.zetacore.observer.Query/Ballots", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { // Query if a voter has voted for a ballot @@ -2817,6 +2930,8 @@ type QueryServer interface { TssFundsMigratorInfoAll(context.Context, *QueryTssFundsMigratorInfoAllRequest) (*QueryTssFundsMigratorInfoAllResponse, error) // Queries operational flags OperationalFlags(context.Context, *QueryOperationalFlagsRequest) (*QueryOperationalFlagsResponse, error) + // Query all ballots + Ballots(context.Context, *QueryBallotsRequest) (*QueryBallotsResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -2898,6 +3013,9 @@ func (*UnimplementedQueryServer) TssFundsMigratorInfoAll(ctx context.Context, re func (*UnimplementedQueryServer) OperationalFlags(ctx context.Context, req *QueryOperationalFlagsRequest) (*QueryOperationalFlagsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method OperationalFlags not implemented") } +func (*UnimplementedQueryServer) Ballots(ctx context.Context, req *QueryBallotsRequest) (*QueryBallotsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Ballots not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -3353,6 +3471,24 @@ func _Query_OperationalFlags_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } +func _Query_Ballots_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryBallotsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Ballots(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/zetachain.zetacore.observer.Query/Ballots", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Ballots(ctx, req.(*QueryBallotsRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "zetachain.zetacore.observer.Query", HandlerType: (*QueryServer)(nil), @@ -3457,11 +3593,99 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "OperationalFlags", Handler: _Query_OperationalFlags_Handler, }, + { + MethodName: "Ballots", + Handler: _Query_Ballots_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "zetachain/zetacore/observer/query.proto", } +func (m *QueryBallotsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryBallotsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryBallotsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryBallotsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryBallotsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryBallotsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Ballots) > 0 { + for iNdEx := len(m.Ballots) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Ballots[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func (m *QueryOperationalFlagsRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -5145,6 +5369,38 @@ func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return base } +func (m *QueryBallotsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryBallotsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Ballots) > 0 { + for _, e := range m.Ballots { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + func (m *QueryOperationalFlagsRequest) Size() (n int) { if m == nil { return 0 @@ -5813,6 +6069,212 @@ func sovQuery(x uint64) (n int) { func sozQuery(x uint64) (n int) { return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } +func (m *QueryBallotsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryBallotsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryBallotsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryBallotsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryBallotsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryBallotsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Ballots", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Ballots = append(m.Ballots, Ballot{}) + if err := m.Ballots[len(m.Ballots)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *QueryOperationalFlagsRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/x/observer/types/query.pb.gw.go b/x/observer/types/query.pb.gw.go index 48bd9447dd..ba2d1831f2 100644 --- a/x/observer/types/query.pb.gw.go +++ b/x/observer/types/query.pb.gw.go @@ -1017,6 +1017,42 @@ func local_request_Query_OperationalFlags_0(ctx context.Context, marshaler runti } +var ( + filter_Query_Ballots_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_Ballots_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryBallotsRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Ballots_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.Ballots(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Ballots_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryBallotsRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Ballots_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Ballots(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterQueryHandlerServer registers the http handlers for service Query to "mux". // UnaryRPC :call QueryServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -1598,6 +1634,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_Ballots_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Ballots_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Ballots_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -2139,6 +2198,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_Ballots_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Ballots_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Ballots_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -2192,6 +2271,8 @@ var ( pattern_Query_TssFundsMigratorInfoAll_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"zeta-chain", "observer", "getAllTssFundsMigrators"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_OperationalFlags_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"zeta-chain", "observer", "operationalFlags"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_Ballots_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"zeta-chain", "observer", "ballots"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( @@ -2244,4 +2325,6 @@ var ( forward_Query_TssFundsMigratorInfoAll_0 = runtime.ForwardResponseMessage forward_Query_OperationalFlags_0 = runtime.ForwardResponseMessage + + forward_Query_Ballots_0 = runtime.ForwardResponseMessage ) From 3c38438587022d00d69f65b0892d411d8bd986f0 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Thu, 19 Dec 2024 17:55:27 -0500 Subject: [PATCH 12/16] generate files --- docs/cli/zetacored/cli.md | 35 +++++++ docs/openapi/openapi.swagger.yaml | 94 +++++++++++++++++++ .../zetachain/zetacore/observer/query_pb.d.ts | 57 ++++++++++- x/observer/client/cli/query_ballot.go | 13 ++- x/observer/keeper/grpc_query_ballot.go | 31 +++++- 5 files changed, 221 insertions(+), 9 deletions(-) diff --git a/docs/cli/zetacored/cli.md b/docs/cli/zetacored/cli.md index 56e293efe4..c5c6401918 100644 --- a/docs/cli/zetacored/cli.md +++ b/docs/cli/zetacored/cli.md @@ -5376,6 +5376,7 @@ zetacored query observer [flags] * [zetacored query](#zetacored-query) - Querying subcommands * [zetacored query observer get-historical-tss-address](#zetacored-query-observer-get-historical-tss-address) - Query tss address by finalized zeta height (for historical tss addresses) * [zetacored query observer get-tss-address](#zetacored-query-observer-get-tss-address) - Query current tss address +* [zetacored query observer list-ballots](#zetacored-query-observer-list-ballots) - Query all ballots * [zetacored query observer list-blame](#zetacored-query-observer-list-blame) - Query AllBlameRecords * [zetacored query observer list-blame-by-msg](#zetacored-query-observer-list-blame-by-msg) - Query AllBlameRecords * [zetacored query observer list-chain-nonces](#zetacored-query-observer-list-chain-nonces) - list all chainNonces @@ -5466,6 +5467,40 @@ zetacored query observer get-tss-address [bitcoinChainId]] [flags] * [zetacored query observer](#zetacored-query-observer) - Querying commands for the observer module +## zetacored query observer list-ballots + +Query all ballots + +``` +zetacored query observer list-ballots [flags] +``` + +### Options + +``` + --grpc-addr string the gRPC endpoint to use for this chain + --grpc-insecure allow gRPC over insecure channels, if not TLS the server must use TLS + --height int Use a specific height to query state at (this can error if the node is pruning state) + -h, --help help for list-ballots + --node string [host]:[port] to Tendermint RPC interface for this chain + -o, --output string Output format (text|json) +``` + +### Options inherited from parent commands + +``` + --chain-id string The network chain ID + --home string directory for config and data + --log_format string The logging format (json|plain) + --log_level string The logging level (trace|debug|info|warn|error|fatal|panic) + --log_no_color Disable colored logs + --trace print out full stack trace on errors +``` + +### SEE ALSO + +* [zetacored query observer](#zetacored-query-observer) - Querying commands for the observer module + ## zetacored query observer list-blame Query AllBlameRecords diff --git a/docs/openapi/openapi.swagger.yaml b/docs/openapi/openapi.swagger.yaml index 65f305da0f..63b56b395e 100644 --- a/docs/openapi/openapi.swagger.yaml +++ b/docs/openapi/openapi.swagger.yaml @@ -29981,6 +29981,65 @@ paths: type: string tags: - Query + /zeta-chain/observer/ballots: + get: + summary: Query all ballots + operationId: Query_Ballots + responses: + "200": + description: A successful response. + schema: + $ref: '#/definitions/observerQueryBallotsResponse' + default: + description: An unexpected error response. + schema: + $ref: '#/definitions/googlerpcStatus' + parameters: + - name: pagination.key + description: |- + key is a value returned in PageResponse.next_key to begin + querying the next page most efficiently. Only one of offset or key + should be set. + in: query + required: false + type: string + format: byte + - name: pagination.offset + description: |- + offset is a numeric offset that can be used when key is unavailable. + It is less efficient than using key. Only one of offset or key should + be set. + in: query + required: false + type: string + format: uint64 + - name: pagination.limit + description: |- + limit is the total number of results to be returned in the result page. + If left empty it will default to a value to be set by each app. + in: query + required: false + type: string + format: uint64 + - name: pagination.count_total + description: |- + count_total is set to true to indicate that the result set should include + a count of the total number of items available for pagination in UIs. + count_total is only respected when offset is used. It is ignored when key + is set. + in: query + required: false + type: boolean + - name: pagination.reverse + description: |- + reverse is set to true if results are to be returned in the descending order. + + Since: cosmos-sdk 0.43 + in: query + required: false + type: boolean + tags: + - Query /zeta-chain/observer/blame_by_chain_and_nonce/{chain_id}/{nonce}: get: summary: Queries a list of VoterByIdentifier items. @@ -57864,6 +57923,31 @@ definitions: properties: valid: type: boolean + observerBallot: + type: object + properties: + index: + type: string + ballot_identifier: + type: string + voter_list: + type: array + items: + type: string + votes: + type: array + items: + $ref: '#/definitions/observerVoteType' + observation_type: + $ref: '#/definitions/observerObservationType' + ballot_threshold: + type: string + ballot_status: + $ref: '#/definitions/observerBallotStatus' + ballot_creation_height: + type: string + format: int64 + title: https://github.com/zeta-chain/node/issues/939 observerBallotStatus: type: string enum: @@ -58180,6 +58264,16 @@ definitions: $ref: '#/definitions/observerObservationType' ballot_status: $ref: '#/definitions/observerBallotStatus' + observerQueryBallotsResponse: + type: object + properties: + ballots: + type: array + items: + type: object + $ref: '#/definitions/observerBallot' + pagination: + $ref: '#/definitions/v1beta1PageResponse' observerQueryBlameByChainAndNonceResponse: type: object properties: diff --git a/typescript/zetachain/zetacore/observer/query_pb.d.ts b/typescript/zetachain/zetacore/observer/query_pb.d.ts index b8916f452d..a3c4a5b240 100644 --- a/typescript/zetachain/zetacore/observer/query_pb.d.ts +++ b/typescript/zetachain/zetacore/observer/query_pb.d.ts @@ -5,13 +5,13 @@ import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf"; import { Message, proto3 } from "@bufbuild/protobuf"; +import type { PageRequest, PageResponse } from "../../../cosmos/base/query/v1beta1/pagination_pb.js"; +import type { Ballot, BallotStatus, VoterList } from "./ballot_pb.js"; import type { OperationalFlags } from "./operational_pb.js"; import type { TssFundMigratorInfo } from "./tss_funds_migrator_pb.js"; import type { ChainNonces } from "./chain_nonces_pb.js"; -import type { PageRequest, PageResponse } from "../../../cosmos/base/query/v1beta1/pagination_pb.js"; import type { PendingNonces } from "./pending_nonces_pb.js"; import type { TSS } from "./tss_pb.js"; -import type { BallotStatus, VoterList } from "./ballot_pb.js"; import type { LastObserverCount, ObservationType } from "./observer_pb.js"; import type { Chain } from "../pkg/chains/chains_pb.js"; import type { ChainParams, ChainParamsList } from "./params_pb.js"; @@ -20,6 +20,59 @@ import type { CrosschainFlags } from "./crosschain_flags_pb.js"; import type { Keygen } from "./keygen_pb.js"; import type { Blame } from "./blame_pb.js"; +/** + * @generated from message zetachain.zetacore.observer.QueryBallotsRequest + */ +export declare class QueryBallotsRequest extends Message { + /** + * @generated from field: cosmos.base.query.v1beta1.PageRequest pagination = 1; + */ + pagination?: PageRequest; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "zetachain.zetacore.observer.QueryBallotsRequest"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): QueryBallotsRequest; + + static fromJson(jsonValue: JsonValue, options?: Partial): QueryBallotsRequest; + + static fromJsonString(jsonString: string, options?: Partial): QueryBallotsRequest; + + static equals(a: QueryBallotsRequest | PlainMessage | undefined, b: QueryBallotsRequest | PlainMessage | undefined): boolean; +} + +/** + * @generated from message zetachain.zetacore.observer.QueryBallotsResponse + */ +export declare class QueryBallotsResponse extends Message { + /** + * @generated from field: repeated zetachain.zetacore.observer.Ballot ballots = 1; + */ + ballots: Ballot[]; + + /** + * @generated from field: cosmos.base.query.v1beta1.PageResponse pagination = 2; + */ + pagination?: PageResponse; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "zetachain.zetacore.observer.QueryBallotsResponse"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): QueryBallotsResponse; + + static fromJson(jsonValue: JsonValue, options?: Partial): QueryBallotsResponse; + + static fromJsonString(jsonString: string, options?: Partial): QueryBallotsResponse; + + static equals(a: QueryBallotsResponse | PlainMessage | undefined, b: QueryBallotsResponse | PlainMessage | undefined): boolean; +} + /** * @generated from message zetachain.zetacore.observer.QueryOperationalFlagsRequest */ diff --git a/x/observer/client/cli/query_ballot.go b/x/observer/client/cli/query_ballot.go index 60b39e2afc..4e4ce65f6b 100644 --- a/x/observer/client/cli/query_ballot.go +++ b/x/observer/client/cli/query_ballot.go @@ -8,6 +8,7 @@ import ( "github.com/zeta-chain/node/x/observer/types" ) +// CmdBallotByIdentifier returns a command which queries a ballot by its identifier func CmdBallotByIdentifier() *cobra.Command { cmd := &cobra.Command{ Use: "show-ballot [ballot-identifier]", @@ -40,19 +41,27 @@ func CmdBallotByIdentifier() *cobra.Command { return cmd } +// CmdAllBallots returns a command which queries all ballots func CmdAllBallots() *cobra.Command { cmd := &cobra.Command{ Use: "list-ballots", Short: "Query all ballots", Args: cobra.ExactArgs(0), - RunE: func(cmd *cobra.Command, args []string) (err error) { + RunE: func(cmd *cobra.Command, _ []string) (err error) { clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } queryClient := types.NewQueryClient(clientCtx) - params := &types.QueryBallotsRequest{} + params := &types.QueryBallotsRequest{ + Pagination: pageReq, + } res, err := queryClient.Ballots(cmd.Context(), params) if err != nil { diff --git a/x/observer/keeper/grpc_query_ballot.go b/x/observer/keeper/grpc_query_ballot.go index 20eed7acda..86ebd3aeec 100644 --- a/x/observer/keeper/grpc_query_ballot.go +++ b/x/observer/keeper/grpc_query_ballot.go @@ -3,7 +3,9 @@ package keeper import ( "context" + "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -53,15 +55,34 @@ func (k Keeper) BallotByIdentifier( }, nil } +// Ballots queries all the ballots. It is a paginated query func (k Keeper) Ballots(goCtx context.Context, req *types.QueryBallotsRequest) (*types.QueryBallotsResponse, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "invalid request") } + ballots := make([]types.Ballot, 0) ctx := sdk.UnwrapSDKContext(goCtx) - ballotList := k.GetAllBallots(ctx) - ballots := make([]types.Ballot, len(ballotList)) - for i, ballot := range ballotList { - ballots[i] = *ballot + + ballotStore := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.VoterKey)) + + if req.Pagination == nil { + req.Pagination = &query.PageRequest{} + } + if req.Pagination.Limit == 0 || req.Pagination.Limit > 100 { + req.Pagination.Limit = 100 + } + + pageRes, err := query.Paginate(ballotStore, req.Pagination, func(_ []byte, value []byte) error { + var ballot types.Ballot + if err := k.cdc.Unmarshal(value, &ballot); err != nil { + return err + } + ballots = append(ballots, ballot) + return nil + }) + + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) } - return &types.QueryBallotsResponse{Ballots: ballots}, nil + return &types.QueryBallotsResponse{Ballots: ballots, Pagination: pageRes}, nil } From 5171ebd3c0da4077fad5b93c22af978da675e85f Mon Sep 17 00:00:00 2001 From: Tanmay Date: Fri, 20 Dec 2024 12:32:24 -0500 Subject: [PATCH 13/16] add changelog --- changelog.md | 1 + x/observer/keeper/grpc_query_ballot.go | 6 ++- x/observer/keeper/grpc_query_ballot_test.go | 59 +++++++++++++++++++-- 3 files changed, 61 insertions(+), 5 deletions(-) diff --git a/changelog.md b/changelog.md index 434d69161e..439e33b100 100644 --- a/changelog.md +++ b/changelog.md @@ -17,6 +17,7 @@ * [3170](https://github.com/zeta-chain/node/pull/3170) - revamp TSS package in zetaclient * [3291](https://github.com/zeta-chain/node/pull/3291) - revamp zetaclient initialization (+ graceful shutdown) +* [2863](https://github.com/zeta-chain/node/pull/2863) - refactor zetacore to delete matured ballots and add a migration script to remove all old ballots. ### Fixes diff --git a/x/observer/keeper/grpc_query_ballot.go b/x/observer/keeper/grpc_query_ballot.go index 86ebd3aeec..4e67536520 100644 --- a/x/observer/keeper/grpc_query_ballot.go +++ b/x/observer/keeper/grpc_query_ballot.go @@ -68,10 +68,12 @@ func (k Keeper) Ballots(goCtx context.Context, req *types.QueryBallotsRequest) ( if req.Pagination == nil { req.Pagination = &query.PageRequest{} } - if req.Pagination.Limit == 0 || req.Pagination.Limit > 100 { + + if req.Pagination.Limit > 100 { req.Pagination.Limit = 100 } - + // The ballots are not sorted in any particular order therefore this query only has limited usefulness + // if the number of ballots is too large pageRes, err := query.Paginate(ballotStore, req.Pagination, func(_ []byte, value []byte) error { var ballot types.Ballot if err := k.cdc.Unmarshal(value, &ballot); err != nil { diff --git a/x/observer/keeper/grpc_query_ballot_test.go b/x/observer/keeper/grpc_query_ballot_test.go index d00956f741..4f7ae65ca5 100644 --- a/x/observer/keeper/grpc_query_ballot_test.go +++ b/x/observer/keeper/grpc_query_ballot_test.go @@ -5,6 +5,7 @@ import ( "testing" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" "github.com/stretchr/testify/require" keepertest "github.com/zeta-chain/node/testutil/keeper" @@ -135,6 +136,60 @@ func TestKeeper_BallotByIdentifier(t *testing.T) { BallotStatus: ballot.BallotStatus, }, res) }) + + t.Run("should return 100 ballots if more exist and limit is not provided", func(t *testing.T) { + k, ctx, _, _ := keepertest.ObserverKeeper(t) + wctx := sdk.WrapSDKContext(ctx) + numOfBallots := 1000 + + ballots := make([]types.Ballot, numOfBallots) + for i := 0; i < numOfBallots; i++ { + ballot := types.Ballot{ + Index: "", + BallotIdentifier: fmt.Sprintf("index-%d", i), + VoterList: []string{sample.AccAddress()}, + Votes: []types.VoteType{types.VoteType_SuccessObservation}, + BallotStatus: types.BallotStatus_BallotInProgress, + BallotCreationHeight: 1, + BallotThreshold: sdk.MustNewDecFromStr("0.5"), + } + k.SetBallot(ctx, &ballot) + ballots[i] = ballot + } + + res, err := k.Ballots(wctx, &types.QueryBallotsRequest{}) + require.NoError(t, err) + require.Len(t, res.Ballots, 100) + }) + + t.Run("should return limit number of ballots if limit is provided", func(t *testing.T) { + k, ctx, _, _ := keepertest.ObserverKeeper(t) + wctx := sdk.WrapSDKContext(ctx) + numOfBallots := 1000 + + ballots := make([]types.Ballot, numOfBallots) + for i := 0; i < numOfBallots; i++ { + ballot := types.Ballot{ + Index: "", + BallotIdentifier: fmt.Sprintf("index-%d", i), + VoterList: []string{sample.AccAddress()}, + Votes: []types.VoteType{types.VoteType_SuccessObservation}, + BallotStatus: types.BallotStatus_BallotInProgress, + BallotCreationHeight: 1, + BallotThreshold: sdk.MustNewDecFromStr("0.5"), + } + k.SetBallot(ctx, &ballot) + ballots[i] = ballot + } + + res, err := k.Ballots(wctx, &types.QueryBallotsRequest{ + Pagination: &query.PageRequest{ + Limit: 10, + }, + }) + require.NoError(t, err) + require.Len(t, res.Ballots, 10) + }) } func TestKeeper_Ballots(t *testing.T) { @@ -153,9 +208,7 @@ func TestKeeper_Ballots(t *testing.T) { res, err := k.Ballots(wctx, &types.QueryBallotsRequest{}) require.NoError(t, err) - require.Equal(t, &types.QueryBallotsResponse{ - Ballots: []types.Ballot{}, - }, res) + require.Empty(t, res.Ballots) }) t.Run("should return all ballots", func(t *testing.T) { From e533f7eff443412b237428b3096d7ae3bfae530b Mon Sep 17 00:00:00 2001 From: Tanmay Date: Fri, 20 Dec 2024 13:30:12 -0500 Subject: [PATCH 14/16] fixed test naming --- x/observer/migrations/v9/migrate.go | 1 - x/observer/migrations/v9/migrate_test.go | 4 ++-- x/observer/types/ballot_test.go | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/x/observer/migrations/v9/migrate.go b/x/observer/migrations/v9/migrate.go index 14c6dc7af6..ba19b665e7 100644 --- a/x/observer/migrations/v9/migrate.go +++ b/x/observer/migrations/v9/migrate.go @@ -19,7 +19,6 @@ const MaturityBlocks = int64(100) func MigrateStore(ctx sdk.Context, observerKeeper observerKeeper) error { currentHeight := ctx.BlockHeight() // Maturity blocks is a parameter in the emissions module - if currentHeight < MaturityBlocks { return nil } diff --git a/x/observer/migrations/v9/migrate_test.go b/x/observer/migrations/v9/migrate_test.go index b13012613f..e584bb9dc9 100644 --- a/x/observer/migrations/v9/migrate_test.go +++ b/x/observer/migrations/v9/migrate_test.go @@ -72,7 +72,7 @@ func TestMigrateStore(t *testing.T) { } }) - t.Run("do not thing if ballot list for height is not found", func(t *testing.T) { + t.Run("do nothing if ballot list for height is not found", func(t *testing.T) { //Arrange k, ctx, _, _ := keepertest.ObserverKeeper(t) // Set current height to 1000 @@ -108,7 +108,7 @@ func TestMigrateStore(t *testing.T) { require.Equal(t, numberOfActualBlocks*numberOfBallotsPerBlock, int64(len(allBallotsAfterMigration))) }) - t.Run("do not thing if current height is less than maturity blocks", func(t *testing.T) { + t.Run("do nothing if current height is less than maturity blocks", func(t *testing.T) { //Arrange k, ctx, _, _ := keepertest.ObserverKeeper(t) // Set current height to 100 diff --git a/x/observer/types/ballot_test.go b/x/observer/types/ballot_test.go index 7127074605..c902a9aaac 100644 --- a/x/observer/types/ballot_test.go +++ b/x/observer/types/ballot_test.go @@ -488,7 +488,7 @@ func TestBallot_GenerateVoterList(t *testing.T) { err require.ErrorAssertionFunc }{ { - name: "Success observation", + name: "success observation", voters: []string{"Observer1", "Observer2", "Observer3", "Observer4"}, votes: []VoteType{ VoteType_SuccessObservation, @@ -518,7 +518,7 @@ func TestBallot_GenerateVoterList(t *testing.T) { }, { - name: "Failure observation", + name: "failure observation", voters: []string{"Observer1", "Observer2", "Observer3", "Observer4"}, votes: []VoteType{ VoteType_FailureObservation, From 3a807eca31b5dcc46e6931ed48a34c6f20919c2a Mon Sep 17 00:00:00 2001 From: Tanmay Date: Fri, 20 Dec 2024 14:35:42 -0500 Subject: [PATCH 15/16] update migration comment --- x/observer/migrations/v9/migrate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/observer/migrations/v9/migrate.go b/x/observer/migrations/v9/migrate.go index ba19b665e7..c936c7feee 100644 --- a/x/observer/migrations/v9/migrate.go +++ b/x/observer/migrations/v9/migrate.go @@ -15,7 +15,7 @@ type observerKeeper interface { const MaturityBlocks = int64(100) // MigrateStore migrates the x/observer module state from the consensus version 8 to version 9. -// It updates the indexing for chain nonces object to use chain ID instead of chain name +// The migration deletes all the ballots and ballot lists that are older than MaturityBlocks. func MigrateStore(ctx sdk.Context, observerKeeper observerKeeper) error { currentHeight := ctx.BlockHeight() // Maturity blocks is a parameter in the emissions module From c56fa113e8c2eb29dae1d6df80a2751fe12c2a25 Mon Sep 17 00:00:00 2001 From: Tanmay Date: Mon, 23 Dec 2024 10:46:25 -0500 Subject: [PATCH 16/16] update module version --- x/observer/module.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/x/observer/module.go b/x/observer/module.go index 1136be6ecd..b9d17995b4 100644 --- a/x/observer/module.go +++ b/x/observer/module.go @@ -145,6 +145,9 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { if err := cfg.RegisterMigration(types.ModuleName, 7, m.Migrate7to8); err != nil { panic(err) } + if err := cfg.RegisterMigration(types.ModuleName, 8, m.Migrate8to9); err != nil { + panic(err) + } } // RegisterInvariants registers the observer module's invariants. @@ -169,7 +172,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw } // ConsensusVersion implements ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 8 } +func (AppModule) ConsensusVersion() uint64 { return 9 } // BeginBlock executes all ABCI BeginBlock logic respective to the observer module. func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) {