diff --git a/module/proto/gravity/v1/query.proto b/module/proto/gravity/v1/query.proto index a77791776..42f2f5504 100644 --- a/module/proto/gravity/v1/query.proto +++ b/module/proto/gravity/v1/query.proto @@ -6,6 +6,7 @@ import "gravity/v1/types.proto"; import "gravity/v1/msgs.proto"; import "gravity/v1/pool.proto"; import "gravity/v1/batch.proto"; +import "gravity/v1/attestation.proto"; import "google/api/annotations.proto"; import "gogoproto/gogo.proto"; @@ -70,6 +71,9 @@ service Query { option (google.api.http).get = "/gravity/v1beta/cosmos_originated/denom_to_erc20"; } + rpc GetAttestations(QueryAttestationsRequest) returns (QueryAttestationsResponse) { + option (google.api.http).get = "/gravity/v1beta/query_attestations"; + } rpc GetDelegateKeyByValidator(QueryDelegateKeysByValidatorAddress) returns (QueryDelegateKeysByValidatorAddressResponse) { option (google.api.http).get = "/gravity/v1beta/query_delegate_keys_by_validator"; } @@ -205,6 +209,13 @@ message QueryDenomToERC20Response { bool cosmos_originated = 2; } +message QueryAttestationsRequest { + uint64 limit = 1; +} +message QueryAttestationsResponse { + repeated Attestation attestations = 1; +} + message QueryDelegateKeysByValidatorAddress { string validator_address = 1; } diff --git a/module/x/gravity/abci.go b/module/x/gravity/abci.go index 96364657f..3bb88b77b 100644 --- a/module/x/gravity/abci.go +++ b/module/x/gravity/abci.go @@ -361,6 +361,18 @@ func pruneAttestations(ctx sdk.Context, k keeper.Keeper) { // Then we sort it sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] }) + // we delete all attestations earlier than the current event nonce + // minus some buffer value. This buffer value is purely to allow + // frontends and other UI components to view recent oracle history + const eventsToKeep = 1000 + lastNonce := uint64(k.GetLastObservedEventNonce(ctx)) + var cutoff uint64 + if lastNonce <= eventsToKeep { + return + } else { + cutoff = lastNonce - eventsToKeep + } + // This iterates over all keys (event nonces) in the attestation mapping. Each value contains // a slice with one or more attestations at that event nonce. There can be multiple attestations // at one event nonce when validators disagree about what event happened at that nonce. @@ -369,8 +381,8 @@ func pruneAttestations(ctx sdk.Context, k keeper.Keeper) { // They are ordered by when the first attestation at the event nonce was received. // This order is not important. for _, att := range attmap[nonce] { - // we delete all attestations earlier than the current event nonce - if nonce < uint64(k.GetLastObservedEventNonce(ctx)) { + // delete all before the cutoff + if nonce < cutoff { k.DeleteAttestation(ctx, att) } } diff --git a/module/x/gravity/keeper/attestation.go b/module/x/gravity/keeper/attestation.go index 6a0ea2f49..224a7d21f 100644 --- a/module/x/gravity/keeper/attestation.go +++ b/module/x/gravity/keeper/attestation.go @@ -2,6 +2,7 @@ package keeper import ( "fmt" + "sort" "strconv" codectypes "github.com/cosmos/cosmos-sdk/codec/types" @@ -162,7 +163,7 @@ func (k Keeper) GetAttestation(ctx sdk.Context, eventNonce uint64, claimHash []b return &att } -// DeleteAttestation deletes an attestation given an event nonce and claim +// DeleteAttestation deletes the given attestation func (k Keeper) DeleteAttestation(ctx sdk.Context, att types.Attestation) { claim, err := k.UnpackAttestationClaim(&att) if err != nil { @@ -219,6 +220,37 @@ func (k Keeper) IterateAttestaions(ctx sdk.Context, cb func([]byte, types.Attest } } +// GetMostRecentAttestations returns sorted (by nonce) attestations up to a provided limit number of attestations +// Note: calls GetAttestationMapping in the hopes that there are potentially many attestations +// which are distributed between few nonces to minimize sorting time +func (k Keeper) GetMostRecentAttestations(ctx sdk.Context, limit uint64) []*types.Attestation { + attestationMapping := k.GetAttestationMapping(ctx) + attestations := make([]*types.Attestation, 0, limit) + + keys := make([]uint64, 0, len(attestationMapping)) + for k := range attestationMapping { + keys = append(keys, k) + } + sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] }) + + // Iterate the nonces and collect the attestations + count := 0 + for _, nonce := range keys { + if count >= int(limit) { + break + } + for _, att := range attestationMapping[nonce] { + if count >= int(limit) { + break + } + attestations = append(attestations, &att) + count++ + } + } + + return attestations +} + // GetLastObservedEventNonce returns the latest observed event nonce func (k Keeper) GetLastObservedEventNonce(ctx sdk.Context) uint64 { store := ctx.KVStore(k.storeKey) diff --git a/module/x/gravity/keeper/attestation_test.go b/module/x/gravity/keeper/attestation_test.go new file mode 100644 index 000000000..2bab5b590 --- /dev/null +++ b/module/x/gravity/keeper/attestation_test.go @@ -0,0 +1,51 @@ +package keeper + +import ( + "testing" + + "github.com/althea-net/cosmos-gravity-bridge/module/x/gravity/types" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdktypes "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +// Sets up 10 attestations and checks that they are returned in the correct order +func TestGetMostRecentAttestations(t *testing.T) { + input := CreateTestEnv(t) + k := input.GravityKeeper + ctx := input.Context + + lenth := 10 + msgs := make([]types.MsgSendToCosmosClaim, 0, lenth) + anys := make([]codectypes.Any, 0, lenth) + for i := 0; i < lenth; i++ { + nonce := uint64(1 + i) + msg := types.MsgSendToCosmosClaim{ + EventNonce: nonce, + BlockHeight: 1, + TokenContract: "0x00000000000000000001", + Amount: sdktypes.NewInt(10000000000 + int64(i)), + EthereumSender: "0x00000000000000000002", + CosmosReceiver: "0x00000000000000000003", + Orchestrator: "0x00000000000000000004", + } + msgs = append(msgs, msg) + + any, _ := codectypes.NewAnyWithValue(&msg) + anys = append(anys, *any) + att := &types.Attestation{ + Observed: false, + Height: uint64(ctx.BlockHeight()), + Claim: any, + } + k.SetAttestation(ctx, nonce, msg.ClaimHash(), att) + } + + recentAttestations := k.GetMostRecentAttestations(ctx, uint64(10)) + require.True(t, len(recentAttestations) == lenth, + "recentAttestations should have len %v but instead has %v", lenth, len(recentAttestations)) + for n, attest := range recentAttestations { + require.Equal(t, attest.Claim.GetCachedValue(), anys[n].GetCachedValue(), + "The %vth claim does not match our message: claim %v\n message %v", n, attest.Claim, msgs[n]) + } +} diff --git a/module/x/gravity/keeper/grpc_query.go b/module/x/gravity/keeper/grpc_query.go index b66a6edf1..a81699048 100644 --- a/module/x/gravity/keeper/grpc_query.go +++ b/module/x/gravity/keeper/grpc_query.go @@ -20,6 +20,8 @@ var _ types.QueryServer = Keeper{ AttestationHandler: nil, } +const QUERY_ATTESTATIONS_LIMIT uint64 = 1000 + // Params queries the params of the gravity module func (k Keeper) Params(c context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { var params types.Params @@ -270,6 +272,20 @@ func (k Keeper) ERC20ToDenom( return &ret, nil } +// GetAttestations queries the attestation map +func (k Keeper) GetAttestations( + c context.Context, + req *types.QueryAttestationsRequest) (*types.QueryAttestationsResponse, error) { + ctx := sdk.UnwrapSDKContext(c) + limit := req.Limit + if limit > QUERY_ATTESTATIONS_LIMIT { + limit = QUERY_ATTESTATIONS_LIMIT + } + attestations := k.GetMostRecentAttestations(ctx, limit) + + return &types.QueryAttestationsResponse{Attestations: attestations}, nil +} + func (k Keeper) GetDelegateKeyByValidator( c context.Context, req *types.QueryDelegateKeysByValidatorAddress) (*types.QueryDelegateKeysByValidatorAddressResponse, error) { diff --git a/module/x/gravity/types/query.pb.go b/module/x/gravity/types/query.pb.go index fb5a40fd8..535d48bc9 100644 --- a/module/x/gravity/types/query.pb.go +++ b/module/x/gravity/types/query.pb.go @@ -1633,6 +1633,94 @@ func (m *QueryDenomToERC20Response) GetCosmosOriginated() bool { return false } +type QueryAttestationsRequest struct { + Limit uint64 `protobuf:"varint,1,opt,name=limit,proto3" json:"limit,omitempty"` +} + +func (m *QueryAttestationsRequest) Reset() { *m = QueryAttestationsRequest{} } +func (m *QueryAttestationsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryAttestationsRequest) ProtoMessage() {} +func (*QueryAttestationsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_29a9d4192703013c, []int{36} +} +func (m *QueryAttestationsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAttestationsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAttestationsRequest.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 *QueryAttestationsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAttestationsRequest.Merge(m, src) +} +func (m *QueryAttestationsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryAttestationsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAttestationsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAttestationsRequest proto.InternalMessageInfo + +func (m *QueryAttestationsRequest) GetLimit() uint64 { + if m != nil { + return m.Limit + } + return 0 +} + +type QueryAttestationsResponse struct { + Attestations []*Attestation `protobuf:"bytes,1,rep,name=attestations,proto3" json:"attestations,omitempty"` +} + +func (m *QueryAttestationsResponse) Reset() { *m = QueryAttestationsResponse{} } +func (m *QueryAttestationsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryAttestationsResponse) ProtoMessage() {} +func (*QueryAttestationsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_29a9d4192703013c, []int{37} +} +func (m *QueryAttestationsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAttestationsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAttestationsResponse.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 *QueryAttestationsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAttestationsResponse.Merge(m, src) +} +func (m *QueryAttestationsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryAttestationsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAttestationsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAttestationsResponse proto.InternalMessageInfo + +func (m *QueryAttestationsResponse) GetAttestations() []*Attestation { + if m != nil { + return m.Attestations + } + return nil +} + type QueryDelegateKeysByValidatorAddress struct { ValidatorAddress string `protobuf:"bytes,1,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty"` } @@ -1641,7 +1729,7 @@ func (m *QueryDelegateKeysByValidatorAddress) Reset() { *m = QueryDelega func (m *QueryDelegateKeysByValidatorAddress) String() string { return proto.CompactTextString(m) } func (*QueryDelegateKeysByValidatorAddress) ProtoMessage() {} func (*QueryDelegateKeysByValidatorAddress) Descriptor() ([]byte, []int) { - return fileDescriptor_29a9d4192703013c, []int{36} + return fileDescriptor_29a9d4192703013c, []int{38} } func (m *QueryDelegateKeysByValidatorAddress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1690,7 +1778,7 @@ func (m *QueryDelegateKeysByValidatorAddressResponse) String() string { } func (*QueryDelegateKeysByValidatorAddressResponse) ProtoMessage() {} func (*QueryDelegateKeysByValidatorAddressResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_29a9d4192703013c, []int{37} + return fileDescriptor_29a9d4192703013c, []int{39} } func (m *QueryDelegateKeysByValidatorAddressResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1741,7 +1829,7 @@ func (m *QueryDelegateKeysByEthAddress) Reset() { *m = QueryDelegateKeys func (m *QueryDelegateKeysByEthAddress) String() string { return proto.CompactTextString(m) } func (*QueryDelegateKeysByEthAddress) ProtoMessage() {} func (*QueryDelegateKeysByEthAddress) Descriptor() ([]byte, []int) { - return fileDescriptor_29a9d4192703013c, []int{38} + return fileDescriptor_29a9d4192703013c, []int{40} } func (m *QueryDelegateKeysByEthAddress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1786,7 +1874,7 @@ func (m *QueryDelegateKeysByEthAddressResponse) Reset() { *m = QueryDele func (m *QueryDelegateKeysByEthAddressResponse) String() string { return proto.CompactTextString(m) } func (*QueryDelegateKeysByEthAddressResponse) ProtoMessage() {} func (*QueryDelegateKeysByEthAddressResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_29a9d4192703013c, []int{39} + return fileDescriptor_29a9d4192703013c, []int{41} } func (m *QueryDelegateKeysByEthAddressResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1839,7 +1927,7 @@ func (m *QueryDelegateKeysByOrchestratorAddress) Reset() { func (m *QueryDelegateKeysByOrchestratorAddress) String() string { return proto.CompactTextString(m) } func (*QueryDelegateKeysByOrchestratorAddress) ProtoMessage() {} func (*QueryDelegateKeysByOrchestratorAddress) Descriptor() ([]byte, []int) { - return fileDescriptor_29a9d4192703013c, []int{40} + return fileDescriptor_29a9d4192703013c, []int{42} } func (m *QueryDelegateKeysByOrchestratorAddress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1888,7 +1976,7 @@ func (m *QueryDelegateKeysByOrchestratorAddressResponse) String() string { } func (*QueryDelegateKeysByOrchestratorAddressResponse) ProtoMessage() {} func (*QueryDelegateKeysByOrchestratorAddressResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_29a9d4192703013c, []int{41} + return fileDescriptor_29a9d4192703013c, []int{43} } func (m *QueryDelegateKeysByOrchestratorAddressResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1939,7 +2027,7 @@ func (m *QueryPendingSendToEth) Reset() { *m = QueryPendingSendToEth{} } func (m *QueryPendingSendToEth) String() string { return proto.CompactTextString(m) } func (*QueryPendingSendToEth) ProtoMessage() {} func (*QueryPendingSendToEth) Descriptor() ([]byte, []int) { - return fileDescriptor_29a9d4192703013c, []int{42} + return fileDescriptor_29a9d4192703013c, []int{44} } func (m *QueryPendingSendToEth) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1984,7 +2072,7 @@ func (m *QueryPendingSendToEthResponse) Reset() { *m = QueryPendingSendT func (m *QueryPendingSendToEthResponse) String() string { return proto.CompactTextString(m) } func (*QueryPendingSendToEthResponse) ProtoMessage() {} func (*QueryPendingSendToEthResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_29a9d4192703013c, []int{43} + return fileDescriptor_29a9d4192703013c, []int{45} } func (m *QueryPendingSendToEthResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2064,6 +2152,8 @@ func init() { proto.RegisterType((*QueryERC20ToDenomResponse)(nil), "gravity.v1.QueryERC20ToDenomResponse") proto.RegisterType((*QueryDenomToERC20Request)(nil), "gravity.v1.QueryDenomToERC20Request") proto.RegisterType((*QueryDenomToERC20Response)(nil), "gravity.v1.QueryDenomToERC20Response") + proto.RegisterType((*QueryAttestationsRequest)(nil), "gravity.v1.QueryAttestationsRequest") + proto.RegisterType((*QueryAttestationsResponse)(nil), "gravity.v1.QueryAttestationsResponse") proto.RegisterType((*QueryDelegateKeysByValidatorAddress)(nil), "gravity.v1.QueryDelegateKeysByValidatorAddress") proto.RegisterType((*QueryDelegateKeysByValidatorAddressResponse)(nil), "gravity.v1.QueryDelegateKeysByValidatorAddressResponse") proto.RegisterType((*QueryDelegateKeysByEthAddress)(nil), "gravity.v1.QueryDelegateKeysByEthAddress") @@ -2077,119 +2167,124 @@ func init() { func init() { proto.RegisterFile("gravity/v1/query.proto", fileDescriptor_29a9d4192703013c) } var fileDescriptor_29a9d4192703013c = []byte{ - // 1789 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x99, 0xc9, 0x6f, 0xdc, 0x46, - 0x16, 0xc6, 0x45, 0x8d, 0x25, 0xd9, 0xcf, 0x7b, 0xa9, 0x65, 0xc8, 0x94, 0xd5, 0x2d, 0xd1, 0x23, - 0xdb, 0x5a, 0xa9, 0x65, 0xbc, 0xcc, 0x78, 0x30, 0x18, 0xb7, 0x2c, 0x7b, 0x0c, 0xdb, 0x23, 0x4f, - 0x8f, 0xc6, 0x83, 0xc4, 0x86, 0x09, 0x76, 0xb3, 0xc4, 0x26, 0xd2, 0x22, 0x65, 0x92, 0x6a, 0xa8, - 0x61, 0xd8, 0x40, 0x72, 0x48, 0xae, 0x01, 0xb2, 0x01, 0x39, 0xe5, 0x96, 0x9c, 0x72, 0x4c, 0x8e, - 0x01, 0x72, 0x32, 0x90, 0x8b, 0x81, 0x5c, 0x72, 0x0a, 0x02, 0x3b, 0x40, 0xfe, 0x8d, 0x80, 0x55, - 0x8f, 0x6c, 0x2e, 0xc5, 0x5e, 0x84, 0x9c, 0x2c, 0x15, 0xdf, 0x7b, 0xdf, 0xef, 0x55, 0x15, 0xab, - 0xf8, 0x59, 0x70, 0xc6, 0x74, 0xf5, 0xa6, 0xe5, 0xb7, 0xd4, 0xe6, 0x8a, 0xfa, 0x74, 0x8f, 0xba, - 0xad, 0xa5, 0x5d, 0xd7, 0xf1, 0x1d, 0x02, 0x38, 0xbe, 0xd4, 0x5c, 0x91, 0xc7, 0x63, 0x31, 0x26, - 0xb5, 0xa9, 0x67, 0x79, 0x3c, 0x4a, 0x8e, 0x67, 0xfb, 0xad, 0x5d, 0x1a, 0x8e, 0x8f, 0xc5, 0xc6, - 0x77, 0x3c, 0x53, 0x34, 0xbc, 0xeb, 0x38, 0x0d, 0x41, 0x95, 0xaa, 0xee, 0xd7, 0xea, 0x38, 0x7e, - 0xce, 0x74, 0x1c, 0xb3, 0x41, 0x55, 0x7d, 0xd7, 0x52, 0x75, 0xdb, 0x76, 0x7c, 0xdd, 0xb7, 0x1c, - 0x3b, 0x2c, 0x56, 0x30, 0x1d, 0xd3, 0x61, 0x3f, 0xaa, 0xc1, 0x4f, 0x7c, 0x54, 0x29, 0x00, 0xf9, - 0x4f, 0xd0, 0xc6, 0x03, 0xdd, 0xd5, 0x77, 0xbc, 0x0a, 0x7d, 0xba, 0x47, 0x3d, 0x5f, 0xb9, 0x0d, - 0xa3, 0x89, 0x51, 0x6f, 0xd7, 0xb1, 0x3d, 0x4a, 0x96, 0x61, 0x78, 0x97, 0x8d, 0x8c, 0x4b, 0x53, - 0xd2, 0xa5, 0xa3, 0xab, 0x64, 0xa9, 0xdd, 0xf5, 0x12, 0x8f, 0x2d, 0x1f, 0x7a, 0xf9, 0x73, 0x69, - 0xa0, 0x82, 0x71, 0xca, 0x04, 0x9c, 0x65, 0x85, 0xd6, 0xf7, 0x5c, 0x97, 0xda, 0xfe, 0x43, 0xbd, - 0xe1, 0x51, 0x3f, 0x54, 0xf9, 0x17, 0xc8, 0xa2, 0x87, 0x28, 0x36, 0x07, 0xc3, 0x4d, 0x36, 0x22, - 0x12, 0xc3, 0x58, 0x8c, 0x50, 0x56, 0x50, 0x26, 0x51, 0x1f, 0xff, 0x21, 0x05, 0x18, 0xb2, 0x1d, - 0xbb, 0x46, 0x59, 0x9d, 0x43, 0x15, 0xfe, 0x4b, 0x24, 0x9e, 0x4a, 0x39, 0x80, 0xf8, 0xdd, 0x84, - 0xf8, 0xba, 0x63, 0x6f, 0x5b, 0xee, 0x4e, 0x47, 0x71, 0x32, 0x0e, 0x23, 0xba, 0x61, 0xb8, 0xd4, - 0xf3, 0xc6, 0x07, 0xa7, 0xa4, 0x4b, 0x47, 0x2a, 0xe1, 0xaf, 0xca, 0x56, 0x02, 0x2b, 0x2a, 0x86, - 0x58, 0x57, 0x60, 0xa4, 0xc6, 0x87, 0x90, 0xeb, 0x5c, 0x9c, 0xeb, 0xbe, 0x67, 0x26, 0xd3, 0xc2, - 0x60, 0xe5, 0xaf, 0x30, 0x9d, 0xad, 0xea, 0x95, 0x5b, 0xff, 0x0e, 0x68, 0x3a, 0xcf, 0xd3, 0x13, - 0x50, 0x3a, 0xa5, 0x22, 0xd8, 0x35, 0x38, 0x8c, 0x5a, 0xc1, 0xde, 0xf8, 0x53, 0x57, 0xb2, 0x28, - 0x5a, 0x99, 0x82, 0x22, 0xab, 0x7f, 0x4f, 0xf7, 0x92, 0xdb, 0x23, 0xda, 0x8c, 0x9b, 0x50, 0xca, - 0x8d, 0x40, 0xf9, 0x05, 0x18, 0xe1, 0x8b, 0x11, 0xaa, 0x8b, 0xd6, 0x2b, 0x0c, 0x51, 0x6e, 0xc1, - 0x5c, 0x54, 0xf0, 0x01, 0xb5, 0x0d, 0xcb, 0x36, 0x13, 0x75, 0xcb, 0xad, 0x1b, 0x86, 0xe1, 0x86, - 0xd3, 0x12, 0x5b, 0x2b, 0x29, 0xb9, 0x56, 0x8f, 0x60, 0xbe, 0xa7, 0x3a, 0x07, 0x82, 0x3c, 0x03, - 0x05, 0x56, 0xbc, 0x1c, 0xbc, 0xe0, 0xb7, 0x68, 0xb8, 0x4a, 0xca, 0x7d, 0x18, 0x4b, 0x8d, 0x63, - 0xf9, 0xbf, 0x00, 0xb0, 0xc3, 0x40, 0xdb, 0xa6, 0x34, 0x54, 0x18, 0x8b, 0x2b, 0x84, 0x19, 0x5e, - 0xe5, 0x48, 0x35, 0xfc, 0x51, 0xd9, 0x80, 0xd9, 0x74, 0x0f, 0x2c, 0xae, 0xcf, 0xa9, 0xd0, 0xb2, - 0x53, 0x2a, 0x2a, 0x83, 0xa8, 0x2b, 0x30, 0xc4, 0x08, 0x70, 0x13, 0x4f, 0xc4, 0x29, 0x37, 0xf7, - 0x7c, 0xd3, 0xb1, 0x6c, 0x73, 0x6b, 0x9f, 0x17, 0xe0, 0x91, 0x4a, 0x19, 0x2e, 0xa4, 0x05, 0xee, - 0x39, 0xa6, 0x55, 0x5b, 0xd7, 0x1b, 0x8d, 0x5e, 0x21, 0x1f, 0xc3, 0xc5, 0xae, 0x35, 0x22, 0xc2, - 0x43, 0x35, 0xbd, 0xd1, 0x40, 0xc0, 0x49, 0x11, 0x60, 0x94, 0x5a, 0x61, 0xa1, 0x4a, 0x09, 0x26, - 0x59, 0xf5, 0x54, 0x03, 0x34, 0xda, 0xc7, 0xff, 0xc7, 0x9d, 0x2e, 0x08, 0x40, 0xd5, 0xcb, 0x30, - 0x52, 0xe5, 0x43, 0xb8, 0x7e, 0x1d, 0x67, 0x26, 0x8c, 0x8d, 0x5e, 0xa1, 0x0c, 0x59, 0x24, 0xfd, - 0x10, 0x5f, 0x21, 0x51, 0x04, 0x6a, 0xaf, 0xc1, 0x50, 0xd0, 0x46, 0xa8, 0xdc, 0xa5, 0x65, 0x1e, - 0xab, 0x54, 0xb1, 0x6e, 0x72, 0xad, 0xbb, 0x9f, 0x2a, 0x64, 0x16, 0x4e, 0xd5, 0x1c, 0xdb, 0x77, - 0xf5, 0x9a, 0xaf, 0x25, 0x4f, 0xc2, 0x93, 0xe1, 0xf8, 0x0d, 0x5c, 0xb5, 0xff, 0xc1, 0x54, 0xbe, - 0xc6, 0xc1, 0x37, 0xd4, 0x63, 0x3c, 0xb5, 0xd9, 0x60, 0x78, 0xac, 0xfd, 0x81, 0xd0, 0xb2, 0xa8, - 0x3a, 0xe2, 0x5e, 0xcd, 0x9c, 0x96, 0x13, 0xa9, 0xd3, 0x12, 0x53, 0x38, 0x71, 0xfb, 0xb0, 0xf4, - 0x10, 0x9a, 0x2f, 0x44, 0x0a, 0xfa, 0x22, 0x9c, 0xb4, 0xec, 0xa6, 0xde, 0xb0, 0x0c, 0x76, 0xef, - 0x6b, 0x96, 0xc1, 0xf0, 0x8f, 0x55, 0x4e, 0xc4, 0x87, 0xef, 0x18, 0x64, 0x11, 0x48, 0x22, 0x90, - 0xb7, 0x3a, 0xc8, 0x5a, 0x3d, 0x1d, 0x7f, 0xc2, 0x26, 0x59, 0x79, 0x0b, 0x7b, 0x49, 0x89, 0x62, - 0x2f, 0xd7, 0x33, 0xbd, 0x94, 0xc4, 0xbd, 0xb4, 0x37, 0x4f, 0xbb, 0x9f, 0xbf, 0xe3, 0xda, 0x06, - 0x6f, 0xe4, 0x46, 0x93, 0xda, 0x3e, 0x53, 0xec, 0xf5, 0x7d, 0xbe, 0x89, 0xb7, 0x9a, 0x38, 0x1b, - 0xf9, 0x4a, 0x70, 0x94, 0x06, 0xcf, 0xb4, 0xf8, 0x82, 0x02, 0x8d, 0xc2, 0x95, 0x65, 0x18, 0x67, - 0x55, 0x36, 0x2a, 0xeb, 0xab, 0xcb, 0x5b, 0xce, 0x4d, 0x6a, 0x3b, 0xf1, 0xdb, 0x9b, 0xba, 0xb5, - 0xd5, 0x65, 0x54, 0xe6, 0xbf, 0x28, 0x4f, 0x70, 0x15, 0x92, 0x19, 0xa8, 0x57, 0x80, 0x21, 0x23, - 0x18, 0x08, 0x53, 0xd8, 0x2f, 0x64, 0x1e, 0x4e, 0xd7, 0x1c, 0x6f, 0xc7, 0xf1, 0x34, 0xc7, 0xb5, - 0x4c, 0xcb, 0xd6, 0x7d, 0x6a, 0xb0, 0x19, 0x3f, 0x5c, 0x39, 0xc5, 0x1f, 0x6c, 0x46, 0xe3, 0x11, - 0x11, 0x2b, 0xbc, 0xe5, 0x30, 0x99, 0x18, 0x51, 0xb6, 0x7c, 0x44, 0x94, 0xcc, 0x68, 0x13, 0x65, - 0x9b, 0xe8, 0x8f, 0xa8, 0x02, 0xe7, 0xb1, 0x7e, 0x83, 0x9a, 0xba, 0x4f, 0xef, 0xd2, 0x96, 0x57, - 0x0e, 0x3e, 0x09, 0x82, 0x8d, 0xe2, 0xb8, 0xb8, 0xeb, 0x83, 0x9a, 0xcd, 0x70, 0x4c, 0x4b, 0x2e, - 0xda, 0xa9, 0x66, 0x2a, 0x58, 0x79, 0x57, 0xc2, 0xeb, 0xb3, 0x73, 0xd1, 0xc4, 0x42, 0xfa, 0xf5, - 0x54, 0x59, 0xa0, 0x7e, 0x3d, 0x54, 0x5f, 0x81, 0x82, 0xe3, 0x06, 0x07, 0xa2, 0xef, 0x26, 0x00, - 0xf8, 0x2b, 0x3a, 0x1a, 0x7f, 0x16, 0x32, 0xfc, 0x13, 0xcf, 0xec, 0x24, 0xc2, 0x46, 0xbb, 0x66, - 0x37, 0x51, 0xe5, 0x03, 0x09, 0x66, 0x3a, 0x96, 0x88, 0xf8, 0xfb, 0x99, 0x9c, 0x83, 0xf4, 0xf2, - 0x08, 0x6f, 0xc8, 0x24, 0xc8, 0x66, 0x36, 0x32, 0xb7, 0xb8, 0x94, 0x5f, 0xfc, 0x05, 0x2c, 0xf5, - 0x56, 0xfc, 0x60, 0xed, 0xa6, 0xa6, 0x79, 0x30, 0x33, 0xcd, 0xff, 0xc0, 0xaf, 0x1e, 0xbc, 0xb6, - 0xff, 0x4b, 0x6d, 0x63, 0xcb, 0xd9, 0xf0, 0xeb, 0x64, 0x06, 0x4e, 0x78, 0xd4, 0x36, 0x68, 0x5a, - 0xe3, 0x38, 0x1f, 0x0d, 0xf3, 0xbf, 0x97, 0x70, 0xa5, 0xd3, 0x05, 0x22, 0xde, 0x07, 0x50, 0xf0, - 0x5d, 0xdd, 0xf6, 0xb6, 0xa9, 0xeb, 0x69, 0x96, 0xad, 0x25, 0x2f, 0xe2, 0xa2, 0xf0, 0x46, 0xc1, - 0xf8, 0xad, 0xfd, 0x0a, 0x89, 0x72, 0xef, 0xd8, 0x78, 0xab, 0x93, 0x4d, 0x18, 0xdd, 0xb3, 0x79, - 0x19, 0x43, 0x8b, 0x9e, 0x8f, 0x0f, 0xf6, 0x56, 0x30, 0x4a, 0x0d, 0x07, 0xbd, 0xd5, 0xdf, 0x64, - 0x18, 0x62, 0x4d, 0x10, 0x0b, 0x86, 0xb9, 0xdd, 0x22, 0x89, 0x3a, 0x59, 0x27, 0x27, 0x97, 0x72, - 0x9f, 0xf3, 0xbe, 0x95, 0xe2, 0x7b, 0x3f, 0xfe, 0xfa, 0xd1, 0xe0, 0x38, 0x39, 0xa3, 0xb6, 0x5d, - 0x65, 0x95, 0xfa, 0xba, 0xca, 0x1d, 0x1c, 0x79, 0x5f, 0x82, 0xe3, 0x09, 0x83, 0x46, 0x66, 0x32, - 0x25, 0x45, 0xee, 0x4e, 0xbe, 0xd0, 0x2d, 0x0c, 0x01, 0x2e, 0x30, 0x80, 0x29, 0x52, 0x4c, 0x03, - 0xf0, 0x2f, 0x61, 0xb5, 0xc6, 0xb3, 0xc8, 0x0b, 0x38, 0x9e, 0x10, 0x10, 0x70, 0x88, 0xec, 0x9f, - 0x80, 0x43, 0x68, 0xf9, 0xf2, 0x27, 0x82, 0x73, 0xb0, 0x89, 0x48, 0x98, 0x98, 0x5c, 0x80, 0xa4, - 0x05, 0xcc, 0x05, 0x48, 0x99, 0xbb, 0xee, 0x13, 0x81, 0xb2, 0x5f, 0x48, 0x30, 0x26, 0x74, 0x63, - 0x64, 0xb1, 0xb3, 0x52, 0xca, 0xf0, 0xc9, 0x4b, 0xbd, 0x86, 0x23, 0xe0, 0x25, 0x06, 0xa8, 0x90, - 0xa9, 0x34, 0x60, 0x78, 0x9f, 0xab, 0xcf, 0xd8, 0x25, 0xfb, 0x9c, 0x7c, 0x2a, 0x01, 0xc9, 0xda, - 0x35, 0x32, 0x97, 0x11, 0xcc, 0x75, 0x7d, 0xf2, 0x7c, 0x4f, 0xb1, 0x48, 0x76, 0x91, 0x91, 0x4d, - 0x93, 0x52, 0xce, 0xd4, 0xb9, 0x21, 0xc1, 0x37, 0x12, 0x14, 0x3b, 0xdb, 0x35, 0x72, 0x45, 0x28, - 0xdc, 0xd5, 0x27, 0xca, 0x57, 0xfb, 0xce, 0x43, 0xf8, 0xf3, 0x0c, 0x7e, 0x92, 0x4c, 0xe4, 0xc0, - 0x37, 0x74, 0xcf, 0x27, 0xdf, 0x4a, 0x30, 0xd9, 0xd1, 0x5c, 0x91, 0xcb, 0x9d, 0xf4, 0x73, 0x3d, - 0x9d, 0x7c, 0xa5, 0xdf, 0xb4, 0x6e, 0x53, 0xce, 0x8e, 0x2d, 0xf5, 0x19, 0x1e, 0xc7, 0xcf, 0xc9, - 0xd7, 0x12, 0xc8, 0xf9, 0x8e, 0x8b, 0xac, 0x76, 0xd2, 0x17, 0x5b, 0x3c, 0x79, 0xad, 0xaf, 0x9c, - 0x6e, 0xc0, 0x8d, 0x20, 0x21, 0x06, 0xfc, 0x95, 0x04, 0x05, 0xd1, 0x27, 0x25, 0x59, 0x10, 0xca, - 0xe6, 0x7c, 0xb7, 0xca, 0x8b, 0x3d, 0x46, 0x23, 0xde, 0x1a, 0xc3, 0x5b, 0x24, 0xf3, 0x69, 0x3c, - 0xc7, 0xd5, 0x6b, 0x0d, 0xaa, 0xb2, 0x2f, 0x56, 0xf6, 0x7a, 0xc5, 0x50, 0x3d, 0x38, 0x12, 0xb9, - 0x7a, 0x32, 0x95, 0x11, 0x4c, 0xfd, 0xdf, 0x81, 0x3c, 0xdd, 0x21, 0x02, 0x31, 0xa6, 0x19, 0xc6, - 0x04, 0x39, 0x2b, 0x5c, 0xd6, 0xed, 0x40, 0xe7, 0x63, 0x09, 0x4e, 0x67, 0x3c, 0x2c, 0x99, 0xcd, - 0xd4, 0xce, 0x33, 0xc2, 0xf2, 0x5c, 0x2f, 0xa1, 0xdd, 0xce, 0x1c, 0xbe, 0xcd, 0x1c, 0x4c, 0xf4, - 0xf7, 0xc9, 0xe7, 0x12, 0x90, 0xac, 0xbf, 0x25, 0xf9, 0x62, 0x19, 0x9b, 0x2c, 0x38, 0x73, 0xf2, - 0x0d, 0xb3, 0x32, 0xcf, 0xc8, 0x66, 0xc8, 0xf9, 0xce, 0x64, 0x6c, 0x77, 0x91, 0xcf, 0x24, 0x18, - 0x15, 0x18, 0x58, 0x32, 0x2f, 0x5e, 0x11, 0xa1, 0x95, 0x96, 0x17, 0x7a, 0x0b, 0x46, 0xbe, 0x19, - 0xc6, 0x57, 0x22, 0x93, 0x39, 0x2f, 0x28, 0x1e, 0xd5, 0xc1, 0xb5, 0x96, 0x70, 0xa9, 0x82, 0x6b, - 0x4d, 0xe4, 0x91, 0x05, 0xd7, 0x9a, 0xd0, 0xec, 0xe6, 0x5f, 0x6b, 0x9c, 0x23, 0xbc, 0x3b, 0x18, - 0x48, 0xc2, 0x62, 0x0a, 0x40, 0x44, 0xbe, 0x57, 0x00, 0x22, 0x74, 0xaa, 0xf9, 0x20, 0xfc, 0x00, - 0x88, 0x40, 0x3e, 0x91, 0xe0, 0x58, 0xdc, 0xda, 0x91, 0x3f, 0x67, 0x04, 0x04, 0x5e, 0x51, 0x9e, - 0xe9, 0x12, 0x85, 0x14, 0xd7, 0x18, 0xc5, 0x2a, 0x59, 0xce, 0x5e, 0xa2, 0x29, 0x37, 0xa6, 0x32, - 0xa3, 0xa6, 0xf9, 0x8e, 0xc6, 0x3d, 0x64, 0xc0, 0x15, 0x37, 0x78, 0x02, 0x2e, 0x81, 0x63, 0x14, - 0x70, 0x89, 0x5c, 0x62, 0x3f, 0x5c, 0x0c, 0x27, 0xe0, 0xe2, 0x4e, 0xf2, 0x3b, 0x09, 0xce, 0xde, - 0xa6, 0x7e, 0xcc, 0x1a, 0xc4, 0x5c, 0x1c, 0x51, 0x05, 0xf2, 0x9d, 0xfc, 0x9e, 0xe0, 0x1e, 0xed, - 0xcd, 0x20, 0xe6, 0x77, 0xc0, 0xfe, 0x4e, 0xa3, 0x19, 0x58, 0x45, 0x7b, 0x87, 0xb6, 0x3c, 0xad, - 0xda, 0xd2, 0x22, 0x17, 0x42, 0xbe, 0x94, 0x60, 0x34, 0xdd, 0x41, 0x60, 0x2e, 0x66, 0xbb, 0xa0, - 0xb4, 0x5d, 0x9e, 0xbc, 0xd2, 0x73, 0x68, 0xc4, 0xbb, 0xca, 0x78, 0x17, 0xc8, 0x5c, 0x8f, 0xbc, - 0xd4, 0xaf, 0x93, 0x1f, 0x24, 0x38, 0x97, 0x26, 0x8d, 0xbb, 0x30, 0xc1, 0x75, 0xda, 0xd5, 0xb2, - 0xc9, 0x7f, 0xeb, 0x3f, 0x27, 0x6a, 0xe2, 0x3a, 0x6b, 0xe2, 0x32, 0x59, 0xeb, 0xb1, 0x89, 0xb8, - 0xb9, 0x0c, 0x3e, 0x13, 0x83, 0x79, 0xcf, 0x98, 0xba, 0xec, 0x3d, 0x95, 0x0e, 0x91, 0x67, 0xbb, - 0x86, 0x44, 0x88, 0x2b, 0x0c, 0x71, 0x9e, 0xcc, 0x8a, 0x11, 0x77, 0x79, 0x9e, 0x16, 0x18, 0x46, - 0xb6, 0xa9, 0xfd, 0x7a, 0xf9, 0xf1, 0xcb, 0xd7, 0x45, 0xe9, 0xd5, 0xeb, 0xa2, 0xf4, 0xcb, 0xeb, - 0xa2, 0xf4, 0xe1, 0x9b, 0xe2, 0xc0, 0xab, 0x37, 0xc5, 0x81, 0x9f, 0xde, 0x14, 0x07, 0xde, 0x2e, - 0x9b, 0x96, 0x5f, 0xdf, 0xab, 0x2e, 0xd5, 0x9c, 0x1d, 0x55, 0x6f, 0xf8, 0x75, 0xaa, 0x2f, 0xda, - 0xec, 0xdb, 0x3c, 0x78, 0x49, 0x16, 0x51, 0x60, 0xb1, 0xea, 0x5a, 0x86, 0x49, 0xd5, 0x1d, 0xc7, - 0xd8, 0x6b, 0x50, 0x75, 0x3f, 0x12, 0x66, 0x7f, 0xf3, 0xab, 0x0e, 0xb3, 0x3f, 0xbd, 0xad, 0xfd, - 0x1e, 0x00, 0x00, 0xff, 0xff, 0x24, 0x7a, 0x80, 0xfb, 0x4c, 0x1c, 0x00, 0x00, + // 1871 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x99, 0x49, 0x6f, 0x1b, 0xc9, + 0x15, 0xc7, 0xd5, 0x8a, 0x25, 0xd9, 0xcf, 0x7b, 0x89, 0x72, 0xe4, 0x96, 0x45, 0x4a, 0x6d, 0xcb, + 0xb6, 0xd6, 0xd6, 0x12, 0x2f, 0x89, 0x83, 0x20, 0xa6, 0x2c, 0x3b, 0x86, 0xed, 0xc8, 0x61, 0x14, + 0x67, 0xb1, 0xe1, 0x46, 0x93, 0x5d, 0x22, 0x1b, 0xa1, 0xba, 0xe5, 0xee, 0x12, 0x21, 0xc2, 0xb0, + 0x81, 0xe4, 0x90, 0x00, 0x39, 0x05, 0xc8, 0x06, 0xe4, 0x34, 0xb7, 0x99, 0xd3, 0x1c, 0x67, 0x8e, + 0x03, 0xcc, 0xc9, 0xc0, 0x5c, 0x0c, 0xcc, 0x65, 0x4e, 0x83, 0x81, 0x3d, 0x1f, 0x61, 0x3e, 0xc0, + 0xa0, 0xab, 0x5e, 0x37, 0x7b, 0xa9, 0x26, 0x29, 0x61, 0x4e, 0x22, 0x5f, 0xbf, 0xe5, 0xf7, 0xaa, + 0xaa, 0xab, 0xea, 0x2f, 0xc2, 0xb9, 0xba, 0x67, 0xb6, 0x6c, 0xd6, 0xd6, 0x5b, 0x2b, 0xfa, 0x8b, + 0x3d, 0xea, 0xb5, 0x97, 0x76, 0x3d, 0x97, 0xb9, 0x04, 0xd0, 0xbe, 0xd4, 0x5a, 0x51, 0xc7, 0x63, + 0x3e, 0x75, 0xea, 0x50, 0xdf, 0xf6, 0x85, 0x97, 0x1a, 0x8f, 0x66, 0xed, 0x5d, 0x1a, 0xda, 0xc7, + 0x62, 0xf6, 0x1d, 0xbf, 0x2e, 0x33, 0xef, 0xba, 0x6e, 0x53, 0x92, 0xa5, 0x6a, 0xb2, 0x5a, 0x03, + 0xed, 0x17, 0x62, 0x76, 0x93, 0x31, 0xea, 0x33, 0x93, 0xd9, 0xae, 0x13, 0x3d, 0x75, 0xdd, 0x7a, + 0x93, 0xea, 0xe6, 0xae, 0xad, 0x9b, 0x8e, 0xe3, 0x8a, 0x87, 0x61, 0xa9, 0x42, 0xdd, 0xad, 0xbb, + 0xfc, 0xa3, 0x1e, 0x7c, 0x12, 0x56, 0xad, 0x00, 0xe4, 0x37, 0x41, 0x93, 0x8f, 0x4d, 0xcf, 0xdc, + 0xf1, 0x2b, 0xf4, 0xc5, 0x1e, 0xf5, 0x99, 0x76, 0x0f, 0x46, 0x13, 0x56, 0x7f, 0xd7, 0x75, 0x7c, + 0x4a, 0x96, 0x61, 0x78, 0x97, 0x5b, 0xc6, 0x95, 0x29, 0xe5, 0xea, 0xf1, 0x55, 0xb2, 0xd4, 0x19, + 0x93, 0x25, 0xe1, 0x5b, 0x3e, 0xf2, 0xe6, 0xeb, 0xd2, 0x40, 0x05, 0xfd, 0xb4, 0x09, 0x38, 0xcf, + 0x13, 0xad, 0xef, 0x79, 0x1e, 0x75, 0xd8, 0x13, 0xb3, 0xe9, 0x53, 0x16, 0x56, 0xf9, 0x15, 0xa8, + 0xb2, 0x87, 0x58, 0x6c, 0x0e, 0x86, 0x5b, 0xdc, 0x22, 0x2b, 0x86, 0xbe, 0xe8, 0xa1, 0xad, 0x60, + 0x99, 0x44, 0x7e, 0xfc, 0x43, 0x0a, 0x30, 0xe4, 0xb8, 0x4e, 0x8d, 0xf2, 0x3c, 0x47, 0x2a, 0xe2, + 0x4b, 0x54, 0x3c, 0x15, 0x72, 0x88, 0xe2, 0x0f, 0x12, 0xc5, 0xd7, 0x5d, 0x67, 0xdb, 0xf6, 0x76, + 0xba, 0x16, 0x27, 0xe3, 0x30, 0x62, 0x5a, 0x96, 0x47, 0x7d, 0x7f, 0x7c, 0x70, 0x4a, 0xb9, 0x7a, + 0xac, 0x12, 0x7e, 0xd5, 0xb6, 0x12, 0x58, 0x51, 0x32, 0xc4, 0xba, 0x0e, 0x23, 0x35, 0x61, 0x42, + 0xae, 0x0b, 0x71, 0xae, 0x47, 0x7e, 0x3d, 0x19, 0x16, 0x3a, 0x6b, 0x3f, 0x85, 0xe9, 0x6c, 0x56, + 0xbf, 0xdc, 0xfe, 0x75, 0x40, 0xd3, 0x7d, 0x9c, 0x9e, 0x83, 0xd6, 0x2d, 0x14, 0xc1, 0x6e, 0xc2, + 0x51, 0xac, 0x15, 0xac, 0x8d, 0x1f, 0xf5, 0x24, 0x8b, 0xbc, 0xb5, 0x29, 0x28, 0xf2, 0xfc, 0x0f, + 0x4d, 0x3f, 0xb9, 0x3c, 0xa2, 0xc5, 0xb8, 0x09, 0xa5, 0x5c, 0x0f, 0x2c, 0xbf, 0x00, 0x23, 0x62, + 0x32, 0xc2, 0xea, 0xb2, 0xf9, 0x0a, 0x5d, 0xb4, 0xbb, 0x30, 0x17, 0x25, 0x7c, 0x4c, 0x1d, 0xcb, + 0x76, 0xea, 0x89, 0xbc, 0xe5, 0xf6, 0x6d, 0xcb, 0xf2, 0xc2, 0x61, 0x89, 0xcd, 0x95, 0x92, 0x9c, + 0xab, 0xa7, 0x30, 0xdf, 0x57, 0x9e, 0x43, 0x41, 0x9e, 0x83, 0x02, 0x4f, 0x5e, 0x0e, 0x5e, 0xff, + 0xbb, 0x34, 0x9c, 0x25, 0xed, 0x11, 0x8c, 0xa5, 0xec, 0x98, 0xfe, 0x27, 0x00, 0x7c, 0xab, 0x30, + 0xb6, 0x29, 0x0d, 0x2b, 0x8c, 0xc5, 0x2b, 0x84, 0x11, 0x7e, 0xe5, 0x58, 0x35, 0xfc, 0xa8, 0x6d, + 0xc0, 0x6c, 0xba, 0x07, 0xee, 0x77, 0xc0, 0xa1, 0x30, 0xb2, 0x43, 0x2a, 0x4b, 0x83, 0xa8, 0x2b, + 0x30, 0xc4, 0x09, 0x70, 0x11, 0x4f, 0xc4, 0x29, 0x37, 0xf7, 0x58, 0xdd, 0xb5, 0x9d, 0xfa, 0xd6, + 0xbe, 0x48, 0x20, 0x3c, 0xb5, 0x32, 0x5c, 0x4e, 0x17, 0x78, 0xe8, 0xd6, 0xed, 0xda, 0xba, 0xd9, + 0x6c, 0xf6, 0x0b, 0xf9, 0x0c, 0xae, 0xf4, 0xcc, 0x11, 0x11, 0x1e, 0xa9, 0x99, 0xcd, 0x26, 0x02, + 0x4e, 0xca, 0x00, 0xa3, 0xd0, 0x0a, 0x77, 0xd5, 0x4a, 0x30, 0xc9, 0xb3, 0xa7, 0x1a, 0xa0, 0xd1, + 0x3a, 0xfe, 0x3d, 0xae, 0x74, 0x89, 0x03, 0x56, 0xbd, 0x06, 0x23, 0x55, 0x61, 0xc2, 0xf9, 0xeb, + 0x3a, 0x32, 0xa1, 0x6f, 0xf4, 0x0a, 0x65, 0xc8, 0xa2, 0xd2, 0x4f, 0xf0, 0x15, 0x92, 0x79, 0x60, + 0xed, 0x35, 0x18, 0x0a, 0xda, 0x08, 0x2b, 0xf7, 0x68, 0x59, 0xf8, 0x6a, 0x55, 0xcc, 0x9b, 0x9c, + 0xeb, 0xde, 0xbb, 0x0a, 0x99, 0x85, 0x33, 0x35, 0xd7, 0x61, 0x9e, 0x59, 0x63, 0x46, 0x72, 0x27, + 0x3c, 0x1d, 0xda, 0x6f, 0xe3, 0xac, 0xfd, 0x0e, 0xa6, 0xf2, 0x6b, 0x1c, 0x7e, 0x41, 0x3d, 0xc3, + 0x5d, 0x9b, 0x1b, 0xc3, 0x6d, 0xed, 0x07, 0x84, 0x56, 0x65, 0xd9, 0x11, 0xf7, 0x46, 0x66, 0xb7, + 0x9c, 0x48, 0xed, 0x96, 0x18, 0x22, 0x88, 0x3b, 0x9b, 0xa5, 0x8f, 0xd0, 0x62, 0x22, 0x52, 0xd0, + 0x57, 0xe0, 0xb4, 0xed, 0xb4, 0xcc, 0xa6, 0x6d, 0xf1, 0x73, 0xdf, 0xb0, 0x2d, 0x8e, 0x7f, 0xa2, + 0x72, 0x2a, 0x6e, 0xbe, 0x6f, 0x91, 0x45, 0x20, 0x09, 0x47, 0xd1, 0xea, 0x20, 0x6f, 0xf5, 0x6c, + 0xfc, 0x09, 0x1f, 0x64, 0xed, 0x8f, 0xd8, 0x4b, 0xaa, 0x28, 0xf6, 0x72, 0x2b, 0xd3, 0x4b, 0x49, + 0xde, 0x4b, 0x67, 0xf1, 0x74, 0xfa, 0xf9, 0x39, 0xce, 0x6d, 0xf0, 0x46, 0x6e, 0xb4, 0xa8, 0xc3, + 0x78, 0xc5, 0x7e, 0xdf, 0xe7, 0x3b, 0x78, 0xaa, 0xc9, 0xa3, 0x91, 0xaf, 0x04, 0xc7, 0x69, 0xf0, + 0xcc, 0x88, 0x4f, 0x28, 0xd0, 0xc8, 0x5d, 0x5b, 0x86, 0x71, 0x9e, 0x65, 0xa3, 0xb2, 0xbe, 0xba, + 0xbc, 0xe5, 0xde, 0xa1, 0x8e, 0x1b, 0x3f, 0xbd, 0xa9, 0x57, 0x5b, 0x5d, 0xc6, 0xca, 0xe2, 0x8b, + 0xf6, 0x1c, 0x67, 0x21, 0x19, 0x81, 0xf5, 0x0a, 0x30, 0x64, 0x05, 0x86, 0x30, 0x84, 0x7f, 0x21, + 0xf3, 0x70, 0xb6, 0xe6, 0xfa, 0x3b, 0xae, 0x6f, 0xb8, 0x9e, 0x5d, 0xb7, 0x1d, 0x93, 0x51, 0x8b, + 0x8f, 0xf8, 0xd1, 0xca, 0x19, 0xf1, 0x60, 0x33, 0xb2, 0x47, 0x44, 0x3c, 0xf1, 0x96, 0xcb, 0xcb, + 0xc4, 0x88, 0xb2, 0xe9, 0x23, 0xa2, 0x64, 0x44, 0x87, 0x28, 0xdb, 0xc4, 0xe1, 0x88, 0x6e, 0x77, + 0xee, 0x9c, 0xf1, 0x77, 0xa5, 0x69, 0xef, 0xd8, 0x2c, 0x7c, 0x57, 0xf8, 0x17, 0xed, 0x0f, 0x48, + 0x94, 0x8c, 0x88, 0xd6, 0xcc, 0x89, 0xd8, 0xed, 0x35, 0x5c, 0x37, 0x3f, 0x8e, 0xaf, 0x9b, 0x58, + 0x5c, 0x25, 0xe1, 0xac, 0x55, 0xe0, 0x22, 0xf6, 0xda, 0xa4, 0x75, 0x93, 0xd1, 0x07, 0xb4, 0xed, + 0x97, 0x83, 0xeb, 0x49, 0xb0, 0x68, 0x5d, 0x0f, 0xdf, 0xc0, 0xa0, 0xbf, 0x56, 0x68, 0x33, 0x92, + 0x0b, 0xe8, 0x4c, 0x2b, 0xe5, 0xac, 0xfd, 0x45, 0xc1, 0xa3, 0xbc, 0x7b, 0xd2, 0xc4, 0xa2, 0x62, + 0x8d, 0x54, 0x5a, 0xa0, 0xac, 0x11, 0x56, 0x5f, 0x81, 0x82, 0xeb, 0x05, 0x9b, 0x33, 0xf3, 0x12, + 0x00, 0x62, 0xbb, 0x18, 0x8d, 0x3f, 0x0b, 0x19, 0x7e, 0x89, 0xe7, 0x47, 0x12, 0x61, 0xa3, 0x93, + 0xb3, 0x57, 0x51, 0xed, 0xef, 0x0a, 0xcc, 0x74, 0x4d, 0x11, 0xf1, 0x1f, 0x64, 0x70, 0x0e, 0xd3, + 0xcb, 0x53, 0x3c, 0xad, 0x93, 0x20, 0x9b, 0x59, 0xcf, 0xdc, 0xe4, 0x4a, 0x7e, 0xf2, 0xd7, 0xb0, + 0xd4, 0x5f, 0xf2, 0xc3, 0xb5, 0x9b, 0x1a, 0xe6, 0xc1, 0xcc, 0x30, 0xff, 0x02, 0x6f, 0x60, 0x78, + 0x85, 0xf8, 0x2d, 0x75, 0xac, 0x2d, 0x77, 0x83, 0x35, 0xc8, 0x0c, 0x9c, 0xf2, 0xa9, 0x63, 0xd1, + 0x74, 0x8d, 0x93, 0xc2, 0x1a, 0xc6, 0x7f, 0xae, 0xe0, 0x4c, 0xa7, 0x13, 0x44, 0xbc, 0x8f, 0xa1, + 0xc0, 0x3c, 0xd3, 0xf1, 0xb7, 0xa9, 0xe7, 0x1b, 0xb6, 0x63, 0x24, 0x2f, 0x05, 0x45, 0xe9, 0xe9, + 0x86, 0xfe, 0x5b, 0xfb, 0x15, 0x12, 0xc5, 0xde, 0x77, 0xf0, 0x86, 0x41, 0x36, 0x61, 0x74, 0xcf, + 0x11, 0x69, 0x2c, 0x23, 0x7a, 0x3e, 0x3e, 0xd8, 0x5f, 0xc2, 0x28, 0x34, 0x34, 0xfa, 0xab, 0xdf, + 0x4d, 0xc0, 0x10, 0x6f, 0x82, 0xd8, 0x30, 0x2c, 0xa4, 0x1f, 0x49, 0xe4, 0xc9, 0xaa, 0x4a, 0xb5, + 0x94, 0xfb, 0x5c, 0xf4, 0xad, 0x15, 0xff, 0xfa, 0xe5, 0xb7, 0xff, 0x1a, 0x1c, 0x27, 0xe7, 0xf4, + 0x8e, 0xce, 0xad, 0x52, 0x66, 0xea, 0x42, 0x4d, 0x92, 0xbf, 0x29, 0x70, 0x32, 0x21, 0x16, 0xc9, + 0x4c, 0x26, 0xa5, 0x4c, 0x69, 0xaa, 0x97, 0x7b, 0xb9, 0x21, 0xc0, 0x65, 0x0e, 0x30, 0x45, 0x8a, + 0x69, 0x00, 0x71, 0x2b, 0xd7, 0x6b, 0x22, 0x8a, 0xbc, 0x86, 0x93, 0x89, 0x02, 0x12, 0x0e, 0x99, + 0x14, 0x95, 0x70, 0x48, 0xe5, 0x67, 0xfe, 0x40, 0x08, 0x0e, 0x3e, 0x10, 0x09, 0x41, 0x95, 0x0b, + 0x90, 0x94, 0xa3, 0xb9, 0x00, 0x29, 0xa1, 0xd9, 0x7b, 0x20, 0xb0, 0xec, 0x07, 0x0a, 0x8c, 0x49, + 0x95, 0x21, 0x59, 0xec, 0x5e, 0x29, 0x25, 0x3e, 0xd5, 0xa5, 0x7e, 0xdd, 0x11, 0xf0, 0x2a, 0x07, + 0xd4, 0xc8, 0x54, 0x1a, 0x30, 0xbc, 0x5b, 0xe8, 0x2f, 0xf9, 0x81, 0xff, 0x8a, 0xfc, 0x57, 0x01, + 0x92, 0x95, 0x8e, 0x64, 0x2e, 0x53, 0x30, 0x57, 0x81, 0xaa, 0xf3, 0x7d, 0xf9, 0x22, 0xd9, 0x15, + 0x4e, 0x36, 0x4d, 0x4a, 0x39, 0x43, 0xe7, 0x85, 0x04, 0x9f, 0x28, 0x50, 0xec, 0x2e, 0x1d, 0xc9, + 0x75, 0x69, 0xe1, 0x9e, 0x9a, 0x55, 0xbd, 0x71, 0xe0, 0x38, 0x84, 0xbf, 0xc8, 0xe1, 0x27, 0xc9, + 0x44, 0x0e, 0x7c, 0xd3, 0xf4, 0x19, 0xf9, 0x54, 0x81, 0xc9, 0xae, 0x42, 0x8f, 0x5c, 0xeb, 0x56, + 0x3f, 0x57, 0x5f, 0xaa, 0xd7, 0x0f, 0x1a, 0xd6, 0x6b, 0xc8, 0xf9, 0xb6, 0xa5, 0xbf, 0xc4, 0xed, + 0xf8, 0x15, 0xf9, 0x58, 0x01, 0x35, 0x5f, 0xfd, 0x91, 0xd5, 0x6e, 0xf5, 0xe5, 0x72, 0x53, 0x5d, + 0x3b, 0x50, 0x4c, 0x2f, 0xe0, 0x66, 0x10, 0x10, 0x03, 0xfe, 0x48, 0x81, 0x82, 0xec, 0x7a, 0x4b, + 0x16, 0xa4, 0x65, 0x73, 0xee, 0xd0, 0xea, 0x62, 0x9f, 0xde, 0x88, 0xb7, 0xc6, 0xf1, 0x16, 0xc9, + 0x7c, 0x1a, 0xcf, 0xf5, 0xcc, 0x5a, 0x93, 0xea, 0xfc, 0xf6, 0xcc, 0x5f, 0xaf, 0x18, 0xaa, 0x0f, + 0xc7, 0xa2, 0xff, 0x30, 0x90, 0xa9, 0x4c, 0xc1, 0xd4, 0xff, 0x31, 0xd4, 0xe9, 0x2e, 0x1e, 0x88, + 0x31, 0xcd, 0x31, 0x26, 0xc8, 0x79, 0xe9, 0xb4, 0x6e, 0x07, 0x75, 0xfe, 0xad, 0xc0, 0xd9, 0x8c, + 0x9e, 0x26, 0xb3, 0x99, 0xdc, 0x79, 0xa2, 0x5c, 0x9d, 0xeb, 0xc7, 0xb5, 0xd7, 0x9e, 0x23, 0x96, + 0x99, 0x8b, 0x81, 0x6c, 0x9f, 0xfc, 0x5f, 0x01, 0x92, 0xd5, 0xda, 0x24, 0xbf, 0x58, 0x46, 0xb2, + 0x4b, 0xf6, 0x9c, 0x7c, 0xf1, 0xae, 0xcd, 0x73, 0xb2, 0x19, 0x72, 0xb1, 0x3b, 0x19, 0x5f, 0x5d, + 0xe4, 0x7f, 0x0a, 0x8c, 0x4a, 0xc4, 0x34, 0x99, 0x97, 0xcf, 0x88, 0x54, 0xd6, 0xab, 0x0b, 0xfd, + 0x39, 0x23, 0xdf, 0x0c, 0xe7, 0x2b, 0x91, 0xc9, 0x9c, 0x17, 0x14, 0xb7, 0xea, 0xe0, 0x58, 0x4b, + 0x28, 0x66, 0xc9, 0xb1, 0x26, 0xd3, 0xeb, 0x92, 0x63, 0x4d, 0x2a, 0xbc, 0xf3, 0x8f, 0x35, 0xc1, + 0x11, 0x9e, 0x1d, 0x1c, 0x24, 0x21, 0x77, 0x25, 0x20, 0x32, 0x0d, 0x2e, 0x01, 0x91, 0xaa, 0xe6, + 0x7c, 0x10, 0xb1, 0x01, 0x44, 0x20, 0xff, 0x51, 0xe0, 0x44, 0x5c, 0x66, 0x92, 0x4b, 0x99, 0x02, + 0x12, 0xdd, 0xaa, 0xce, 0xf4, 0xf0, 0x42, 0x8a, 0x9b, 0x9c, 0x62, 0x95, 0x2c, 0x67, 0x0f, 0xd1, + 0x94, 0x32, 0xd4, 0xb9, 0x68, 0x34, 0x98, 0x6b, 0x08, 0x3d, 0x1b, 0x70, 0xc5, 0xc5, 0xa6, 0x84, + 0x4b, 0xa2, 0x5e, 0x25, 0x5c, 0x32, 0xc5, 0x7a, 0x10, 0x2e, 0x8e, 0x13, 0x70, 0x09, 0x55, 0xfb, + 0x0f, 0x05, 0x4e, 0xdf, 0xa3, 0x2c, 0xae, 0x3a, 0x25, 0x68, 0x12, 0x19, 0x2b, 0x41, 0x93, 0x49, + 0x57, 0x6d, 0x8e, 0xa3, 0x5d, 0x22, 0x5a, 0x1a, 0x8d, 0xff, 0x54, 0x64, 0xc4, 0x95, 0x2a, 0xf9, + 0x4c, 0x81, 0xf3, 0xf7, 0x28, 0x8b, 0xe9, 0x94, 0x98, 0xa4, 0x24, 0xba, 0x64, 0x2c, 0xba, 0x89, + 0x4f, 0xc9, 0xa1, 0xde, 0x9f, 0x5a, 0xcd, 0x1f, 0x4e, 0xc1, 0x6c, 0x61, 0x16, 0xe3, 0xcf, 0xb4, + 0xed, 0x1b, 0xd5, 0xb6, 0x11, 0x49, 0x22, 0xf2, 0xa1, 0x02, 0xa3, 0xe9, 0x0e, 0x02, 0xa5, 0x33, + 0xdb, 0x03, 0xa5, 0x23, 0x39, 0xd5, 0x95, 0xbe, 0x5d, 0x23, 0xde, 0x55, 0xce, 0xbb, 0x40, 0xe6, + 0xfa, 0xe4, 0xa5, 0xac, 0x41, 0xbe, 0x50, 0xe0, 0x42, 0x9a, 0x34, 0x2e, 0x09, 0x25, 0x67, 0x7b, + 0x4f, 0xfd, 0xa8, 0xfe, 0xec, 0xe0, 0x31, 0x51, 0x13, 0xb7, 0x78, 0x13, 0xd7, 0xc8, 0x5a, 0x9f, + 0x4d, 0xc4, 0x95, 0x6e, 0x70, 0x67, 0x0d, 0xc6, 0x3d, 0xa3, 0x30, 0xb3, 0x87, 0x66, 0xda, 0x45, + 0x9d, 0xed, 0xe9, 0x12, 0x21, 0xae, 0x70, 0xc4, 0x79, 0x32, 0x2b, 0x47, 0xdc, 0x15, 0x71, 0x46, + 0xa0, 0x5e, 0xf9, 0x1b, 0xc6, 0x1a, 0xe5, 0x67, 0x6f, 0xde, 0x15, 0x95, 0xb7, 0xef, 0x8a, 0xca, + 0x37, 0xef, 0x8a, 0xca, 0x3f, 0xdf, 0x17, 0x07, 0xde, 0xbe, 0x2f, 0x0e, 0x7c, 0xf5, 0xbe, 0x38, + 0xf0, 0xa7, 0x72, 0xdd, 0x66, 0x8d, 0xbd, 0xea, 0x52, 0xcd, 0xdd, 0xd1, 0xcd, 0x26, 0x6b, 0x50, + 0x73, 0xd1, 0xe1, 0x42, 0x21, 0x78, 0x63, 0x17, 0xb1, 0xc0, 0x62, 0xd5, 0xb3, 0xad, 0x3a, 0xd5, + 0x77, 0x5c, 0x6b, 0xaf, 0x49, 0xf5, 0xfd, 0xa8, 0x30, 0xff, 0xa9, 0xb4, 0x3a, 0xcc, 0x7f, 0x93, + 0x5c, 0xfb, 0x3e, 0x00, 0x00, 0xff, 0xff, 0x9c, 0x23, 0x8f, 0x54, 0x83, 0x1d, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -2223,6 +2318,7 @@ type QueryClient interface { LogicConfirms(ctx context.Context, in *QueryLogicConfirmsRequest, opts ...grpc.CallOption) (*QueryLogicConfirmsResponse, error) ERC20ToDenom(ctx context.Context, in *QueryERC20ToDenomRequest, opts ...grpc.CallOption) (*QueryERC20ToDenomResponse, error) DenomToERC20(ctx context.Context, in *QueryDenomToERC20Request, opts ...grpc.CallOption) (*QueryDenomToERC20Response, error) + GetAttestations(ctx context.Context, in *QueryAttestationsRequest, opts ...grpc.CallOption) (*QueryAttestationsResponse, error) GetDelegateKeyByValidator(ctx context.Context, in *QueryDelegateKeysByValidatorAddress, opts ...grpc.CallOption) (*QueryDelegateKeysByValidatorAddressResponse, error) GetDelegateKeyByEth(ctx context.Context, in *QueryDelegateKeysByEthAddress, opts ...grpc.CallOption) (*QueryDelegateKeysByEthAddressResponse, error) GetDelegateKeyByOrchestrator(ctx context.Context, in *QueryDelegateKeysByOrchestratorAddress, opts ...grpc.CallOption) (*QueryDelegateKeysByOrchestratorAddressResponse, error) @@ -2399,6 +2495,15 @@ func (c *queryClient) DenomToERC20(ctx context.Context, in *QueryDenomToERC20Req return out, nil } +func (c *queryClient) GetAttestations(ctx context.Context, in *QueryAttestationsRequest, opts ...grpc.CallOption) (*QueryAttestationsResponse, error) { + out := new(QueryAttestationsResponse) + err := c.cc.Invoke(ctx, "/gravity.v1.Query/GetAttestations", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *queryClient) GetDelegateKeyByValidator(ctx context.Context, in *QueryDelegateKeysByValidatorAddress, opts ...grpc.CallOption) (*QueryDelegateKeysByValidatorAddressResponse, error) { out := new(QueryDelegateKeysByValidatorAddressResponse) err := c.cc.Invoke(ctx, "/gravity.v1.Query/GetDelegateKeyByValidator", in, out, opts...) @@ -2456,6 +2561,7 @@ type QueryServer interface { LogicConfirms(context.Context, *QueryLogicConfirmsRequest) (*QueryLogicConfirmsResponse, error) ERC20ToDenom(context.Context, *QueryERC20ToDenomRequest) (*QueryERC20ToDenomResponse, error) DenomToERC20(context.Context, *QueryDenomToERC20Request) (*QueryDenomToERC20Response, error) + GetAttestations(context.Context, *QueryAttestationsRequest) (*QueryAttestationsResponse, error) GetDelegateKeyByValidator(context.Context, *QueryDelegateKeysByValidatorAddress) (*QueryDelegateKeysByValidatorAddressResponse, error) GetDelegateKeyByEth(context.Context, *QueryDelegateKeysByEthAddress) (*QueryDelegateKeysByEthAddressResponse, error) GetDelegateKeyByOrchestrator(context.Context, *QueryDelegateKeysByOrchestratorAddress) (*QueryDelegateKeysByOrchestratorAddressResponse, error) @@ -2520,6 +2626,9 @@ func (*UnimplementedQueryServer) ERC20ToDenom(ctx context.Context, req *QueryERC func (*UnimplementedQueryServer) DenomToERC20(ctx context.Context, req *QueryDenomToERC20Request) (*QueryDenomToERC20Response, error) { return nil, status.Errorf(codes.Unimplemented, "method DenomToERC20 not implemented") } +func (*UnimplementedQueryServer) GetAttestations(ctx context.Context, req *QueryAttestationsRequest) (*QueryAttestationsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetAttestations not implemented") +} func (*UnimplementedQueryServer) GetDelegateKeyByValidator(ctx context.Context, req *QueryDelegateKeysByValidatorAddress) (*QueryDelegateKeysByValidatorAddressResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetDelegateKeyByValidator not implemented") } @@ -2861,6 +2970,24 @@ func _Query_DenomToERC20_Handler(srv interface{}, ctx context.Context, dec func( return interceptor(ctx, in, info, handler) } +func _Query_GetAttestations_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAttestationsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).GetAttestations(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/gravity.v1.Query/GetAttestations", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).GetAttestations(ctx, req.(*QueryAttestationsRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Query_GetDelegateKeyByValidator_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(QueryDelegateKeysByValidatorAddress) if err := dec(in); err != nil { @@ -3009,6 +3136,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "DenomToERC20", Handler: _Query_DenomToERC20_Handler, }, + { + MethodName: "GetAttestations", + Handler: _Query_GetAttestations_Handler, + }, { MethodName: "GetDelegateKeyByValidator", Handler: _Query_GetDelegateKeyByValidator_Handler, @@ -4191,6 +4322,71 @@ func (m *QueryDenomToERC20Response) MarshalToSizedBuffer(dAtA []byte) (int, erro return len(dAtA) - i, nil } +func (m *QueryAttestationsRequest) 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 *QueryAttestationsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAttestationsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Limit != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.Limit)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryAttestationsResponse) 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 *QueryAttestationsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAttestationsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Attestations) > 0 { + for iNdEx := len(m.Attestations) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Attestations[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 *QueryDelegateKeysByValidatorAddress) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -4957,6 +5153,33 @@ func (m *QueryDenomToERC20Response) Size() (n int) { return n } +func (m *QueryAttestationsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Limit != 0 { + n += 1 + sovQuery(uint64(m.Limit)) + } + return n +} + +func (m *QueryAttestationsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Attestations) > 0 { + for _, e := range m.Attestations { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + func (m *QueryDelegateKeysByValidatorAddress) Size() (n int) { if m == nil { return 0 @@ -8075,6 +8298,165 @@ func (m *QueryDenomToERC20Response) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryAttestationsRequest) 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: QueryAttestationsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAttestationsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType) + } + m.Limit = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Limit |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAttestationsResponse) 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: QueryAttestationsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAttestationsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Attestations", 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.Attestations = append(m.Attestations, &Attestation{}) + if err := m.Attestations[len(m.Attestations)-1].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 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *QueryDelegateKeysByValidatorAddress) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/module/x/gravity/types/query.pb.gw.go b/module/x/gravity/types/query.pb.gw.go index d5d4494dd..348d0229a 100644 --- a/module/x/gravity/types/query.pb.gw.go +++ b/module/x/gravity/types/query.pb.gw.go @@ -681,6 +681,42 @@ func local_request_Query_DenomToERC20_0(ctx context.Context, marshaler runtime.M } +var ( + filter_Query_GetAttestations_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_GetAttestations_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAttestationsRequest + 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_GetAttestations_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.GetAttestations(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_GetAttestations_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAttestationsRequest + 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_GetAttestations_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.GetAttestations(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_Query_GetDelegateKeyByValidator_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -1245,6 +1281,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_GetAttestations_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_GetAttestations_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_GetAttestations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_GetDelegateKeyByValidator_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -1738,6 +1797,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_GetAttestations_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_GetAttestations_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_GetAttestations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_GetDelegateKeyByValidator_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -1858,6 +1937,8 @@ var ( pattern_Query_DenomToERC20_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"gravity", "v1beta", "cosmos_originated", "denom_to_erc20"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_GetAttestations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"gravity", "v1beta", "query_attestations"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_GetDelegateKeyByValidator_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"gravity", "v1beta", "query_delegate_keys_by_validator"}, "", runtime.AssumeColonVerbOpt(true))) pattern_Query_GetDelegateKeyByEth_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"gravity", "v1beta", "query_delegate_keys_by_eth"}, "", runtime.AssumeColonVerbOpt(true))) @@ -1904,6 +1985,8 @@ var ( forward_Query_DenomToERC20_0 = runtime.ForwardResponseMessage + forward_Query_GetAttestations_0 = runtime.ForwardResponseMessage + forward_Query_GetDelegateKeyByValidator_0 = runtime.ForwardResponseMessage forward_Query_GetDelegateKeyByEth_0 = runtime.ForwardResponseMessage diff --git a/orchestrator/Cargo.lock b/orchestrator/Cargo.lock index 911964269..11ab2f45e 100644 --- a/orchestrator/Cargo.lock +++ b/orchestrator/Cargo.lock @@ -2866,6 +2866,7 @@ dependencies = [ "actix", "actix-rt 2.2.0", "actix-web", + "bytes 1.0.1", "clarity", "cosmos_gravity", "deep_space", @@ -2879,6 +2880,8 @@ dependencies = [ "log", "num256", "orchestrator", + "prost", + "prost-types", "rand 0.8.4", "serde", "serde_derive", diff --git a/orchestrator/cosmos_gravity/src/query.rs b/orchestrator/cosmos_gravity/src/query.rs index fa1572636..39111aa55 100644 --- a/orchestrator/cosmos_gravity/src/query.rs +++ b/orchestrator/cosmos_gravity/src/query.rs @@ -1,7 +1,9 @@ use clarity::Address as EthAddress; use deep_space::address::Address; use gravity_proto::gravity::query_client::QueryClient as GravityQueryClient; +use gravity_proto::gravity::Attestation; use gravity_proto::gravity::Params; +use gravity_proto::gravity::QueryAttestationsRequest; use gravity_proto::gravity::QueryBatchConfirmsRequest; use gravity_proto::gravity::QueryCurrentValsetRequest; use gravity_proto::gravity::QueryLastEventNonceByAddrRequest; @@ -224,3 +226,16 @@ pub async fn get_oldest_unsigned_logic_call( None => Ok(None), } } + +pub async fn get_attestations( + client: &mut GravityQueryClient, + limit: Option, +) -> Result, GravityError> { + let request = client + .get_attestations(QueryAttestationsRequest { + limit: limit.or(Some(1000u64)).unwrap(), + }) + .await?; + let attestations = request.into_inner().attestations; + Ok(attestations) +} diff --git a/orchestrator/cosmos_gravity/src/send.rs b/orchestrator/cosmos_gravity/src/send.rs index b138bd0b2..dfdf0fec9 100644 --- a/orchestrator/cosmos_gravity/src/send.rs +++ b/orchestrator/cosmos_gravity/src/send.rs @@ -430,6 +430,7 @@ pub async fn send_request_batch( denom: String, fee: Coin, contact: &Contact, + timeout: Option, ) -> Result { let our_address = private_key.to_address(&contact.get_prefix()).unwrap(); @@ -456,5 +457,8 @@ pub async fn send_request_batch( .send_transaction(msg_bytes, BroadcastMode::Sync) .await?; - contact.wait_for_tx(response, TIMEOUT).await + match timeout { + Some(duration) => contact.wait_for_tx(response, duration).await, + None => Ok(response), + } } diff --git a/orchestrator/gbt/src/client/cosmos_to_eth.rs b/orchestrator/gbt/src/client/cosmos_to_eth.rs index 1705eecbd..7d4c0d1c3 100644 --- a/orchestrator/gbt/src/client/cosmos_to_eth.rs +++ b/orchestrator/gbt/src/client/cosmos_to_eth.rs @@ -98,9 +98,15 @@ pub async fn cosmos_to_eth(args: CosmosToEthOpts, address_prefix: String) { if !no_batch { info!("Requesting a batch to push transaction along immediately"); - send_request_batch(cosmos_key, gravity_coin.denom, bridge_fee, &contact) - .await - .expect("Failed to request batch"); + send_request_batch( + cosmos_key, + gravity_coin.denom, + bridge_fee, + &contact, + Some(TIMEOUT), + ) + .await + .expect("Failed to request batch"); } else { info!("--no-batch specified, your transfer will wait until someone requests a batch for this token type") } diff --git a/orchestrator/gravity_proto/src/prost/gravity.v1.rs b/orchestrator/gravity_proto/src/prost/gravity.v1.rs index 5c8c9faa3..3ad360525 100644 --- a/orchestrator/gravity_proto/src/prost/gravity.v1.rs +++ b/orchestrator/gravity_proto/src/prost/gravity.v1.rs @@ -49,19 +49,6 @@ pub enum ClaimType { LogicCallExecuted = 4, ValsetUpdated = 5, } -/// IDSet represents a set of IDs -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct IdSet { - #[prost(uint64, repeated, tag="1")] - pub ids: ::prost::alloc::vec::Vec, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct BatchFees { - #[prost(string, tag="1")] - pub token: ::prost::alloc::string::String, - #[prost(string, tag="2")] - pub total_fees: ::prost::alloc::string::String, -} /// OutgoingTxBatch represents a batch of transactions going from gravity to ETH #[derive(Clone, PartialEq, ::prost::Message)] pub struct OutgoingTxBatch { @@ -441,11 +428,26 @@ pub struct MsgSubmitBadSignatureEvidence { pub subject: ::core::option::Option<::prost_types::Any>, #[prost(string, tag="2")] pub signature: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub sender: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct MsgSubmitBadSignatureEvidenceResponse { } -# [doc = r" Generated client implementations."] pub mod msg_client { # ! [allow (unused_variables , dead_code , missing_docs)] use tonic :: codegen :: * ; # [doc = " Msg defines the state transitions possible within gravity"] pub struct MsgClient < T > { inner : tonic :: client :: Grpc < T > , } impl MsgClient < tonic :: transport :: Channel > { # [doc = r" Attempt to create a new client by connecting to a given endpoint."] pub async fn connect < D > (dst : D) -> Result < Self , tonic :: transport :: Error > where D : std :: convert :: TryInto < tonic :: transport :: Endpoint > , D :: Error : Into < StdError > , { let conn = tonic :: transport :: Endpoint :: new (dst) ? . connect () . await ? ; Ok (Self :: new (conn)) } } impl < T > MsgClient < T > where T : tonic :: client :: GrpcService < tonic :: body :: BoxBody > , T :: ResponseBody : Body + HttpBody + Send + 'static , T :: Error : Into < StdError > , < T :: ResponseBody as HttpBody > :: Error : Into < StdError > + Send , { pub fn new (inner : T) -> Self { let inner = tonic :: client :: Grpc :: new (inner) ; Self { inner } } pub fn with_interceptor (inner : T , interceptor : impl Into < tonic :: Interceptor >) -> Self { let inner = tonic :: client :: Grpc :: with_interceptor (inner , interceptor) ; Self { inner } } pub async fn valset_confirm (& mut self , request : impl tonic :: IntoRequest < super :: MsgValsetConfirm > ,) -> Result < tonic :: Response < super :: MsgValsetConfirmResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/ValsetConfirm") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn send_to_eth (& mut self , request : impl tonic :: IntoRequest < super :: MsgSendToEth > ,) -> Result < tonic :: Response < super :: MsgSendToEthResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/SendToEth") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn request_batch (& mut self , request : impl tonic :: IntoRequest < super :: MsgRequestBatch > ,) -> Result < tonic :: Response < super :: MsgRequestBatchResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/RequestBatch") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn confirm_batch (& mut self , request : impl tonic :: IntoRequest < super :: MsgConfirmBatch > ,) -> Result < tonic :: Response < super :: MsgConfirmBatchResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/ConfirmBatch") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn confirm_logic_call (& mut self , request : impl tonic :: IntoRequest < super :: MsgConfirmLogicCall > ,) -> Result < tonic :: Response < super :: MsgConfirmLogicCallResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/ConfirmLogicCall") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn send_to_cosmos_claim (& mut self , request : impl tonic :: IntoRequest < super :: MsgSendToCosmosClaim > ,) -> Result < tonic :: Response < super :: MsgSendToCosmosClaimResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/SendToCosmosClaim") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn batch_send_to_eth_claim (& mut self , request : impl tonic :: IntoRequest < super :: MsgBatchSendToEthClaim > ,) -> Result < tonic :: Response < super :: MsgBatchSendToEthClaimResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/BatchSendToEthClaim") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn valset_update_claim (& mut self , request : impl tonic :: IntoRequest < super :: MsgValsetUpdatedClaim > ,) -> Result < tonic :: Response < super :: MsgValsetUpdatedClaimResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/ValsetUpdateClaim") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn erc20_deployed_claim (& mut self , request : impl tonic :: IntoRequest < super :: MsgErc20DeployedClaim > ,) -> Result < tonic :: Response < super :: MsgErc20DeployedClaimResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/ERC20DeployedClaim") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn logic_call_executed_claim (& mut self , request : impl tonic :: IntoRequest < super :: MsgLogicCallExecutedClaim > ,) -> Result < tonic :: Response < super :: MsgLogicCallExecutedClaimResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/LogicCallExecutedClaim") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn set_orchestrator_address (& mut self , request : impl tonic :: IntoRequest < super :: MsgSetOrchestratorAddress > ,) -> Result < tonic :: Response < super :: MsgSetOrchestratorAddressResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/SetOrchestratorAddress") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn cancel_send_to_eth (& mut self , request : impl tonic :: IntoRequest < super :: MsgCancelSendToEth > ,) -> Result < tonic :: Response < super :: MsgCancelSendToEthResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/CancelSendToEth") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn submit_bad_signature_evidence (& mut self , request : impl tonic :: IntoRequest < super :: MsgSubmitBadSignatureEvidence > ,) -> Result < tonic :: Response < super :: MsgSubmitBadSignatureEvidenceResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/SubmitBadSignatureEvidence") ; self . inner . unary (request . into_request () , path , codec) . await } } impl < T : Clone > Clone for MsgClient < T > { fn clone (& self) -> Self { Self { inner : self . inner . clone () , } } } impl < T > std :: fmt :: Debug for MsgClient < T > { fn fmt (& self , f : & mut std :: fmt :: Formatter < '_ >) -> std :: fmt :: Result { write ! (f , "MsgClient {{ ... }}") } } }// Params represent the Gravity genesis and store parameters +# [doc = r" Generated client implementations."] pub mod msg_client { # ! [allow (unused_variables , dead_code , missing_docs)] use tonic :: codegen :: * ; # [doc = " Msg defines the state transitions possible within gravity"] pub struct MsgClient < T > { inner : tonic :: client :: Grpc < T > , } impl MsgClient < tonic :: transport :: Channel > { # [doc = r" Attempt to create a new client by connecting to a given endpoint."] pub async fn connect < D > (dst : D) -> Result < Self , tonic :: transport :: Error > where D : std :: convert :: TryInto < tonic :: transport :: Endpoint > , D :: Error : Into < StdError > , { let conn = tonic :: transport :: Endpoint :: new (dst) ? . connect () . await ? ; Ok (Self :: new (conn)) } } impl < T > MsgClient < T > where T : tonic :: client :: GrpcService < tonic :: body :: BoxBody > , T :: ResponseBody : Body + HttpBody + Send + 'static , T :: Error : Into < StdError > , < T :: ResponseBody as HttpBody > :: Error : Into < StdError > + Send , { pub fn new (inner : T) -> Self { let inner = tonic :: client :: Grpc :: new (inner) ; Self { inner } } pub fn with_interceptor (inner : T , interceptor : impl Into < tonic :: Interceptor >) -> Self { let inner = tonic :: client :: Grpc :: with_interceptor (inner , interceptor) ; Self { inner } } pub async fn valset_confirm (& mut self , request : impl tonic :: IntoRequest < super :: MsgValsetConfirm > ,) -> Result < tonic :: Response < super :: MsgValsetConfirmResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/ValsetConfirm") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn send_to_eth (& mut self , request : impl tonic :: IntoRequest < super :: MsgSendToEth > ,) -> Result < tonic :: Response < super :: MsgSendToEthResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/SendToEth") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn request_batch (& mut self , request : impl tonic :: IntoRequest < super :: MsgRequestBatch > ,) -> Result < tonic :: Response < super :: MsgRequestBatchResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/RequestBatch") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn confirm_batch (& mut self , request : impl tonic :: IntoRequest < super :: MsgConfirmBatch > ,) -> Result < tonic :: Response < super :: MsgConfirmBatchResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/ConfirmBatch") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn confirm_logic_call (& mut self , request : impl tonic :: IntoRequest < super :: MsgConfirmLogicCall > ,) -> Result < tonic :: Response < super :: MsgConfirmLogicCallResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/ConfirmLogicCall") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn send_to_cosmos_claim (& mut self , request : impl tonic :: IntoRequest < super :: MsgSendToCosmosClaim > ,) -> Result < tonic :: Response < super :: MsgSendToCosmosClaimResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/SendToCosmosClaim") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn batch_send_to_eth_claim (& mut self , request : impl tonic :: IntoRequest < super :: MsgBatchSendToEthClaim > ,) -> Result < tonic :: Response < super :: MsgBatchSendToEthClaimResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/BatchSendToEthClaim") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn valset_update_claim (& mut self , request : impl tonic :: IntoRequest < super :: MsgValsetUpdatedClaim > ,) -> Result < tonic :: Response < super :: MsgValsetUpdatedClaimResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/ValsetUpdateClaim") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn erc20_deployed_claim (& mut self , request : impl tonic :: IntoRequest < super :: MsgErc20DeployedClaim > ,) -> Result < tonic :: Response < super :: MsgErc20DeployedClaimResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/ERC20DeployedClaim") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn logic_call_executed_claim (& mut self , request : impl tonic :: IntoRequest < super :: MsgLogicCallExecutedClaim > ,) -> Result < tonic :: Response < super :: MsgLogicCallExecutedClaimResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/LogicCallExecutedClaim") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn set_orchestrator_address (& mut self , request : impl tonic :: IntoRequest < super :: MsgSetOrchestratorAddress > ,) -> Result < tonic :: Response < super :: MsgSetOrchestratorAddressResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/SetOrchestratorAddress") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn cancel_send_to_eth (& mut self , request : impl tonic :: IntoRequest < super :: MsgCancelSendToEth > ,) -> Result < tonic :: Response < super :: MsgCancelSendToEthResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/CancelSendToEth") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn submit_bad_signature_evidence (& mut self , request : impl tonic :: IntoRequest < super :: MsgSubmitBadSignatureEvidence > ,) -> Result < tonic :: Response < super :: MsgSubmitBadSignatureEvidenceResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Msg/SubmitBadSignatureEvidence") ; self . inner . unary (request . into_request () , path , codec) . await } } impl < T : Clone > Clone for MsgClient < T > { fn clone (& self) -> Self { Self { inner : self . inner . clone () , } } } impl < T > std :: fmt :: Debug for MsgClient < T > { fn fmt (& self , f : & mut std :: fmt :: Formatter < '_ >) -> std :: fmt :: Result { write ! (f , "MsgClient {{ ... }}") } } }/// IDSet represents a set of IDs +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct IdSet { + #[prost(uint64, repeated, tag="1")] + pub ids: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BatchFees { + #[prost(string, tag="1")] + pub token: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub total_fees: ::prost::alloc::string::String, +} +// Params represent the Gravity genesis and store parameters // gravity_id: // a random 32 byte value to prevent signature reuse, for example if the // cosmos validators decided to use the same Ethereum keys for another chain @@ -767,6 +769,16 @@ pub struct QueryDenomToErc20Response { pub cosmos_originated: bool, } #[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAttestationsRequest { + #[prost(uint64, tag="1")] + pub limit: u64, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryAttestationsResponse { + #[prost(message, repeated, tag="1")] + pub attestations: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] pub struct QueryDelegateKeysByValidatorAddress { #[prost(string, tag="1")] pub validator_address: ::prost::alloc::string::String, @@ -814,4 +826,4 @@ pub struct QueryPendingSendToEthResponse { #[prost(message, repeated, tag="2")] pub unbatched_transfers: ::prost::alloc::vec::Vec, } -# [doc = r" Generated client implementations."] pub mod query_client { # ! [allow (unused_variables , dead_code , missing_docs)] use tonic :: codegen :: * ; # [doc = " Query defines the gRPC querier service"] pub struct QueryClient < T > { inner : tonic :: client :: Grpc < T > , } impl QueryClient < tonic :: transport :: Channel > { # [doc = r" Attempt to create a new client by connecting to a given endpoint."] pub async fn connect < D > (dst : D) -> Result < Self , tonic :: transport :: Error > where D : std :: convert :: TryInto < tonic :: transport :: Endpoint > , D :: Error : Into < StdError > , { let conn = tonic :: transport :: Endpoint :: new (dst) ? . connect () . await ? ; Ok (Self :: new (conn)) } } impl < T > QueryClient < T > where T : tonic :: client :: GrpcService < tonic :: body :: BoxBody > , T :: ResponseBody : Body + HttpBody + Send + 'static , T :: Error : Into < StdError > , < T :: ResponseBody as HttpBody > :: Error : Into < StdError > + Send , { pub fn new (inner : T) -> Self { let inner = tonic :: client :: Grpc :: new (inner) ; Self { inner } } pub fn with_interceptor (inner : T , interceptor : impl Into < tonic :: Interceptor >) -> Self { let inner = tonic :: client :: Grpc :: with_interceptor (inner , interceptor) ; Self { inner } } # [doc = " Deployments queries deployments"] pub async fn params (& mut self , request : impl tonic :: IntoRequest < super :: QueryParamsRequest > ,) -> Result < tonic :: Response < super :: QueryParamsResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/Params") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn current_valset (& mut self , request : impl tonic :: IntoRequest < super :: QueryCurrentValsetRequest > ,) -> Result < tonic :: Response < super :: QueryCurrentValsetResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/CurrentValset") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn valset_request (& mut self , request : impl tonic :: IntoRequest < super :: QueryValsetRequestRequest > ,) -> Result < tonic :: Response < super :: QueryValsetRequestResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/ValsetRequest") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn valset_confirm (& mut self , request : impl tonic :: IntoRequest < super :: QueryValsetConfirmRequest > ,) -> Result < tonic :: Response < super :: QueryValsetConfirmResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/ValsetConfirm") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn valset_confirms_by_nonce (& mut self , request : impl tonic :: IntoRequest < super :: QueryValsetConfirmsByNonceRequest > ,) -> Result < tonic :: Response < super :: QueryValsetConfirmsByNonceResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/ValsetConfirmsByNonce") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn last_valset_requests (& mut self , request : impl tonic :: IntoRequest < super :: QueryLastValsetRequestsRequest > ,) -> Result < tonic :: Response < super :: QueryLastValsetRequestsResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/LastValsetRequests") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn last_pending_valset_request_by_addr (& mut self , request : impl tonic :: IntoRequest < super :: QueryLastPendingValsetRequestByAddrRequest > ,) -> Result < tonic :: Response < super :: QueryLastPendingValsetRequestByAddrResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/LastPendingValsetRequestByAddr") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn last_pending_batch_request_by_addr (& mut self , request : impl tonic :: IntoRequest < super :: QueryLastPendingBatchRequestByAddrRequest > ,) -> Result < tonic :: Response < super :: QueryLastPendingBatchRequestByAddrResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/LastPendingBatchRequestByAddr") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn last_pending_logic_call_by_addr (& mut self , request : impl tonic :: IntoRequest < super :: QueryLastPendingLogicCallByAddrRequest > ,) -> Result < tonic :: Response < super :: QueryLastPendingLogicCallByAddrResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/LastPendingLogicCallByAddr") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn last_event_nonce_by_addr (& mut self , request : impl tonic :: IntoRequest < super :: QueryLastEventNonceByAddrRequest > ,) -> Result < tonic :: Response < super :: QueryLastEventNonceByAddrResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/LastEventNonceByAddr") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn batch_fees (& mut self , request : impl tonic :: IntoRequest < super :: QueryBatchFeeRequest > ,) -> Result < tonic :: Response < super :: QueryBatchFeeResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/BatchFees") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn outgoing_tx_batches (& mut self , request : impl tonic :: IntoRequest < super :: QueryOutgoingTxBatchesRequest > ,) -> Result < tonic :: Response < super :: QueryOutgoingTxBatchesResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/OutgoingTxBatches") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn outgoing_logic_calls (& mut self , request : impl tonic :: IntoRequest < super :: QueryOutgoingLogicCallsRequest > ,) -> Result < tonic :: Response < super :: QueryOutgoingLogicCallsResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/OutgoingLogicCalls") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn batch_request_by_nonce (& mut self , request : impl tonic :: IntoRequest < super :: QueryBatchRequestByNonceRequest > ,) -> Result < tonic :: Response < super :: QueryBatchRequestByNonceResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/BatchRequestByNonce") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn batch_confirms (& mut self , request : impl tonic :: IntoRequest < super :: QueryBatchConfirmsRequest > ,) -> Result < tonic :: Response < super :: QueryBatchConfirmsResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/BatchConfirms") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn logic_confirms (& mut self , request : impl tonic :: IntoRequest < super :: QueryLogicConfirmsRequest > ,) -> Result < tonic :: Response < super :: QueryLogicConfirmsResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/LogicConfirms") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn erc20_to_denom (& mut self , request : impl tonic :: IntoRequest < super :: QueryErc20ToDenomRequest > ,) -> Result < tonic :: Response < super :: QueryErc20ToDenomResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/ERC20ToDenom") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn denom_to_erc20 (& mut self , request : impl tonic :: IntoRequest < super :: QueryDenomToErc20Request > ,) -> Result < tonic :: Response < super :: QueryDenomToErc20Response > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/DenomToERC20") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn get_delegate_key_by_validator (& mut self , request : impl tonic :: IntoRequest < super :: QueryDelegateKeysByValidatorAddress > ,) -> Result < tonic :: Response < super :: QueryDelegateKeysByValidatorAddressResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/GetDelegateKeyByValidator") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn get_delegate_key_by_eth (& mut self , request : impl tonic :: IntoRequest < super :: QueryDelegateKeysByEthAddress > ,) -> Result < tonic :: Response < super :: QueryDelegateKeysByEthAddressResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/GetDelegateKeyByEth") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn get_delegate_key_by_orchestrator (& mut self , request : impl tonic :: IntoRequest < super :: QueryDelegateKeysByOrchestratorAddress > ,) -> Result < tonic :: Response < super :: QueryDelegateKeysByOrchestratorAddressResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/GetDelegateKeyByOrchestrator") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn get_pending_send_to_eth (& mut self , request : impl tonic :: IntoRequest < super :: QueryPendingSendToEth > ,) -> Result < tonic :: Response < super :: QueryPendingSendToEthResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/GetPendingSendToEth") ; self . inner . unary (request . into_request () , path , codec) . await } } impl < T : Clone > Clone for QueryClient < T > { fn clone (& self) -> Self { Self { inner : self . inner . clone () , } } } impl < T > std :: fmt :: Debug for QueryClient < T > { fn fmt (& self , f : & mut std :: fmt :: Formatter < '_ >) -> std :: fmt :: Result { write ! (f , "QueryClient {{ ... }}") } } } \ No newline at end of file +# [doc = r" Generated client implementations."] pub mod query_client { # ! [allow (unused_variables , dead_code , missing_docs)] use tonic :: codegen :: * ; # [doc = " Query defines the gRPC querier service"] pub struct QueryClient < T > { inner : tonic :: client :: Grpc < T > , } impl QueryClient < tonic :: transport :: Channel > { # [doc = r" Attempt to create a new client by connecting to a given endpoint."] pub async fn connect < D > (dst : D) -> Result < Self , tonic :: transport :: Error > where D : std :: convert :: TryInto < tonic :: transport :: Endpoint > , D :: Error : Into < StdError > , { let conn = tonic :: transport :: Endpoint :: new (dst) ? . connect () . await ? ; Ok (Self :: new (conn)) } } impl < T > QueryClient < T > where T : tonic :: client :: GrpcService < tonic :: body :: BoxBody > , T :: ResponseBody : Body + HttpBody + Send + 'static , T :: Error : Into < StdError > , < T :: ResponseBody as HttpBody > :: Error : Into < StdError > + Send , { pub fn new (inner : T) -> Self { let inner = tonic :: client :: Grpc :: new (inner) ; Self { inner } } pub fn with_interceptor (inner : T , interceptor : impl Into < tonic :: Interceptor >) -> Self { let inner = tonic :: client :: Grpc :: with_interceptor (inner , interceptor) ; Self { inner } } # [doc = " Deployments queries deployments"] pub async fn params (& mut self , request : impl tonic :: IntoRequest < super :: QueryParamsRequest > ,) -> Result < tonic :: Response < super :: QueryParamsResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/Params") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn current_valset (& mut self , request : impl tonic :: IntoRequest < super :: QueryCurrentValsetRequest > ,) -> Result < tonic :: Response < super :: QueryCurrentValsetResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/CurrentValset") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn valset_request (& mut self , request : impl tonic :: IntoRequest < super :: QueryValsetRequestRequest > ,) -> Result < tonic :: Response < super :: QueryValsetRequestResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/ValsetRequest") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn valset_confirm (& mut self , request : impl tonic :: IntoRequest < super :: QueryValsetConfirmRequest > ,) -> Result < tonic :: Response < super :: QueryValsetConfirmResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/ValsetConfirm") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn valset_confirms_by_nonce (& mut self , request : impl tonic :: IntoRequest < super :: QueryValsetConfirmsByNonceRequest > ,) -> Result < tonic :: Response < super :: QueryValsetConfirmsByNonceResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/ValsetConfirmsByNonce") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn last_valset_requests (& mut self , request : impl tonic :: IntoRequest < super :: QueryLastValsetRequestsRequest > ,) -> Result < tonic :: Response < super :: QueryLastValsetRequestsResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/LastValsetRequests") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn last_pending_valset_request_by_addr (& mut self , request : impl tonic :: IntoRequest < super :: QueryLastPendingValsetRequestByAddrRequest > ,) -> Result < tonic :: Response < super :: QueryLastPendingValsetRequestByAddrResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/LastPendingValsetRequestByAddr") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn last_pending_batch_request_by_addr (& mut self , request : impl tonic :: IntoRequest < super :: QueryLastPendingBatchRequestByAddrRequest > ,) -> Result < tonic :: Response < super :: QueryLastPendingBatchRequestByAddrResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/LastPendingBatchRequestByAddr") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn last_pending_logic_call_by_addr (& mut self , request : impl tonic :: IntoRequest < super :: QueryLastPendingLogicCallByAddrRequest > ,) -> Result < tonic :: Response < super :: QueryLastPendingLogicCallByAddrResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/LastPendingLogicCallByAddr") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn last_event_nonce_by_addr (& mut self , request : impl tonic :: IntoRequest < super :: QueryLastEventNonceByAddrRequest > ,) -> Result < tonic :: Response < super :: QueryLastEventNonceByAddrResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/LastEventNonceByAddr") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn batch_fees (& mut self , request : impl tonic :: IntoRequest < super :: QueryBatchFeeRequest > ,) -> Result < tonic :: Response < super :: QueryBatchFeeResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/BatchFees") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn outgoing_tx_batches (& mut self , request : impl tonic :: IntoRequest < super :: QueryOutgoingTxBatchesRequest > ,) -> Result < tonic :: Response < super :: QueryOutgoingTxBatchesResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/OutgoingTxBatches") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn outgoing_logic_calls (& mut self , request : impl tonic :: IntoRequest < super :: QueryOutgoingLogicCallsRequest > ,) -> Result < tonic :: Response < super :: QueryOutgoingLogicCallsResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/OutgoingLogicCalls") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn batch_request_by_nonce (& mut self , request : impl tonic :: IntoRequest < super :: QueryBatchRequestByNonceRequest > ,) -> Result < tonic :: Response < super :: QueryBatchRequestByNonceResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/BatchRequestByNonce") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn batch_confirms (& mut self , request : impl tonic :: IntoRequest < super :: QueryBatchConfirmsRequest > ,) -> Result < tonic :: Response < super :: QueryBatchConfirmsResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/BatchConfirms") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn logic_confirms (& mut self , request : impl tonic :: IntoRequest < super :: QueryLogicConfirmsRequest > ,) -> Result < tonic :: Response < super :: QueryLogicConfirmsResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/LogicConfirms") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn erc20_to_denom (& mut self , request : impl tonic :: IntoRequest < super :: QueryErc20ToDenomRequest > ,) -> Result < tonic :: Response < super :: QueryErc20ToDenomResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/ERC20ToDenom") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn denom_to_erc20 (& mut self , request : impl tonic :: IntoRequest < super :: QueryDenomToErc20Request > ,) -> Result < tonic :: Response < super :: QueryDenomToErc20Response > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/DenomToERC20") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn get_attestations (& mut self , request : impl tonic :: IntoRequest < super :: QueryAttestationsRequest > ,) -> Result < tonic :: Response < super :: QueryAttestationsResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/GetAttestations") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn get_delegate_key_by_validator (& mut self , request : impl tonic :: IntoRequest < super :: QueryDelegateKeysByValidatorAddress > ,) -> Result < tonic :: Response < super :: QueryDelegateKeysByValidatorAddressResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/GetDelegateKeyByValidator") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn get_delegate_key_by_eth (& mut self , request : impl tonic :: IntoRequest < super :: QueryDelegateKeysByEthAddress > ,) -> Result < tonic :: Response < super :: QueryDelegateKeysByEthAddressResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/GetDelegateKeyByEth") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn get_delegate_key_by_orchestrator (& mut self , request : impl tonic :: IntoRequest < super :: QueryDelegateKeysByOrchestratorAddress > ,) -> Result < tonic :: Response < super :: QueryDelegateKeysByOrchestratorAddressResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/GetDelegateKeyByOrchestrator") ; self . inner . unary (request . into_request () , path , codec) . await } pub async fn get_pending_send_to_eth (& mut self , request : impl tonic :: IntoRequest < super :: QueryPendingSendToEth > ,) -> Result < tonic :: Response < super :: QueryPendingSendToEthResponse > , tonic :: Status > { self . inner . ready () . await . map_err (| e | { tonic :: Status :: new (tonic :: Code :: Unknown , format ! ("Service was not ready: {}" , e . into ())) }) ? ; let codec = tonic :: codec :: ProstCodec :: default () ; let path = http :: uri :: PathAndQuery :: from_static ("/gravity.v1.Query/GetPendingSendToEth") ; self . inner . unary (request . into_request () , path , codec) . await } } impl < T : Clone > Clone for QueryClient < T > { fn clone (& self) -> Self { Self { inner : self . inner . clone () , } } } impl < T > std :: fmt :: Debug for QueryClient < T > { fn fmt (& self , f : & mut std :: fmt :: Formatter < '_ >) -> std :: fmt :: Result { write ! (f , "QueryClient {{ ... }}") } } } \ No newline at end of file diff --git a/orchestrator/test_runner/Cargo.toml b/orchestrator/test_runner/Cargo.toml index 07a2c10ca..983ebb3b0 100644 --- a/orchestrator/test_runner/Cargo.toml +++ b/orchestrator/test_runner/Cargo.toml @@ -16,6 +16,9 @@ gravity_utils = {path = "../gravity_utils"} gravity_proto = {path = "../gravity_proto/"} orchestrator = {path = "../orchestrator/"} +bytes = "1" +prost = "0.7" +prost-types = "0.7" deep_space = "2.4" serde_derive = "1.0" clarity = "0.4" diff --git a/orchestrator/test_runner/src/happy_path.rs b/orchestrator/test_runner/src/happy_path.rs index 1ff470029..b6d73ab84 100644 --- a/orchestrator/test_runner/src/happy_path.rs +++ b/orchestrator/test_runner/src/happy_path.rs @@ -3,22 +3,31 @@ use crate::utils::*; use crate::ADDRESS_PREFIX; use crate::MINER_ADDRESS; use crate::MINER_PRIVATE_KEY; +use crate::OPERATION_TIMEOUT; use crate::STAKING_TOKEN; use crate::STARTING_STAKE_PER_VALIDATOR; use crate::TOTAL_TIMEOUT; +use bytes::BytesMut; use clarity::PrivateKey as EthPrivateKey; use clarity::{Address as EthAddress, Uint256}; +use cosmos_gravity::query::get_attestations; use cosmos_gravity::send::{send_request_batch, send_to_eth}; use cosmos_gravity::{query::get_oldest_unsigned_transaction_batch, send::send_ethereum_claims}; use deep_space::address::Address as CosmosAddress; use deep_space::coin::Coin; use deep_space::private_key::PrivateKey as CosmosPrivateKey; use deep_space::Contact; +use ethereum_gravity::utils::get_event_nonce; use ethereum_gravity::utils::get_valset_nonce; use ethereum_gravity::{send_to_cosmos::send_to_cosmos, utils::get_tx_batch_nonce}; use gravity_proto::gravity::query_client::QueryClient as GravityQueryClient; +use gravity_proto::gravity::MsgSendToCosmosClaim; +use gravity_proto::gravity::MsgValsetUpdatedClaim; use gravity_utils::types::SendToCosmosEvent; +use prost::Message; use rand::Rng; +use std::any::type_name; +use std::thread::sleep; use std::time::Duration; use std::time::Instant; use tokio::time::sleep as delay_for; @@ -57,7 +66,7 @@ pub async fn happy_path_test( // with the first block) is successfully updated if !validator_out { for _ in 0u32..2 { - test_valset_update(web30, contact, &keys, gravity_address).await; + test_valset_update(web30, contact, &mut grpc_client, &keys, gravity_address).await; } } else { wait_for_nonzero_valset(web30, gravity_address).await; @@ -80,6 +89,7 @@ pub async fn happy_path_test( test_erc20_deposit( web30, contact, + &mut grpc_client, dest_cosmos_address, gravity_address, erc20_address, @@ -88,12 +98,16 @@ pub async fn happy_path_test( .await; } + let event_nonce = get_event_nonce(gravity_address, *MINER_ADDRESS, web30) + .await + .unwrap(); + // We are going to submit a duplicate tx with nonce 1 // This had better not increase the balance again // this test may have false positives if the timeout is not // long enough. TODO check for an error on the cosmos send response submit_duplicate_erc20_send( - 1u64, + event_nonce, // Duplicate the current nonce contact, erc20_address, 1u64.into(), @@ -116,6 +130,51 @@ pub async fn happy_path_test( .await; } +// Iterates each attestation known by the grpc endpoint by calling `get_attestations()` +// Executes the input closure `f` against each attestation's decoded claim +// This is useful for testing that certain attestations exist in the oracle, +// see the consumers of this function (check_valset_update_attestation(), +// check_send_to_cosmos_attestation(), etc.) for examples of usage +// +// `F` is the type of the closure, a state mutating function which may be called multiple times +// `F` functions take a single parameter of type `T`, which is some sort of `Message` +// The type `T` is very important as it dictates how we decode the message +pub async fn iterate_attestations( + grpc_client: &mut GravityQueryClient, + f: &mut F, +) { + let attestations = get_attestations(grpc_client, None) + .await + .expect("Something happened while getting attestations after delegating to validator"); + for (i, att) in attestations.into_iter().enumerate() { + let claim = att.clone().claim; + trace!("Processing attestation {}", i); + if claim.is_none() { + trace!("Attestation returned with no claim: {:?}", att); + continue; + } + let claim = claim.unwrap(); + let mut buf = BytesMut::with_capacity(claim.value.len()); + buf.extend_from_slice(&claim.value); + + // Here we use the `T` type to decode whatever type of message this attestation holds + // for use in the `f` function + let decoded = T::decode(buf); + + // Decoding errors indicate there is some other attestation we don't care about + if decoded.is_err() { + debug!( + "Found an attestation which is not a {}: {:?}", + type_name::(), + att, + ); + continue; + } + let decoded = decoded.unwrap(); + f(decoded); + } +} + pub async fn wait_for_nonzero_valset(web30: &Web3, gravity_address: EthAddress) { let start = Instant::now(); let mut current_eth_valset_nonce = get_valset_nonce(gravity_address, *MINER_ADDRESS, web30) @@ -137,6 +196,7 @@ pub async fn wait_for_nonzero_valset(web30: &Web3, gravity_address: EthAddress) pub async fn test_valset_update( web30: &Web3, contact: &Contact, + grpc_client: &mut GravityQueryClient, keys: &[ValidatorKeys], gravity_address: EthAddress, ) { @@ -148,6 +208,7 @@ pub async fn test_valset_update( .await .expect("Incorrect Gravity Address or otherwise unable to contact Gravity"); + let mut grpc_client = grpc_client.clone(); // if we don't do this the orchestrators may run ahead of us and we'll be stuck here after // getting credit for two loops when we did one let starting_eth_valset_nonce = get_valset_nonce(gravity_address, *MINER_ADDRESS, web30) @@ -192,6 +253,8 @@ pub async fn test_valset_update( .await .unwrap(); + check_valset_update_attestation(&mut grpc_client, keys).await; + let mut current_eth_valset_nonce = get_valset_nonce(gravity_address, *MINER_ADDRESS, web30) .await .expect("Failed to get current eth valset"); @@ -213,10 +276,41 @@ pub async fn test_valset_update( info!("Validator set successfully updated!"); } +// Checks for a MsgValsetUpdatedClaim attestation where every validator is represented +async fn check_valset_update_attestation( + grpc_client: &mut GravityQueryClient, + keys: &[ValidatorKeys], +) { + let mut found = true; + iterate_attestations(grpc_client, &mut |decoded: MsgValsetUpdatedClaim| { + // Check that each bridge validator is one of the addresses in our keys + for bridge_val in decoded.members { + let found_val = keys.iter().any(|key: &ValidatorKeys| { + let eth_pub_key = key.eth_key.to_public_key().unwrap().to_string(); + bridge_val.ethereum_address == eth_pub_key + }); + if !found_val { + warn!( + "Could not find BridgeValidator eth pub key {} in keys", + bridge_val.ethereum_address + ); + } + found &= found_val; + } + }) + .await; + assert!( + found, + "Could not find the valset updated attestation we were looking for!" + ); + info!("Found the expected MsgValsetUpdatedClaim attestation"); +} + /// this function tests Ethereum -> Cosmos pub async fn test_erc20_deposit( web30: &Web3, contact: &Contact, + grpc_client: &mut GravityQueryClient, dest: CosmosAddress, gravity_address: EthAddress, erc20_address: EthAddress, @@ -226,6 +320,7 @@ pub async fn test_erc20_deposit( .await .expect("Incorrect Gravity Address or otherwise unable to contact Gravity"); + let mut grpc_client = grpc_client.clone(); let start_coin = check_cosmos_balance("gravity", dest, contact).await; info!( "Sending to Cosmos from {} to {} with amount {}", @@ -238,7 +333,7 @@ pub async fn test_erc20_deposit( amount.clone(), dest, *MINER_PRIVATE_KEY, - Some(TOTAL_TIMEOUT), + None, web30, vec![], ) @@ -246,6 +341,13 @@ pub async fn test_erc20_deposit( .expect("Failed to send tokens to Cosmos"); info!("Send to Cosmos txid: {:#066x}", tx_id); + check_send_to_cosmos_attestation(&mut grpc_client, erc20_address, dest, *MINER_ADDRESS).await; + + let _tx_res = web30 + .wait_for_transaction(tx_id, OPERATION_TIMEOUT, None) + .await + .expect("Send to cosmos transaction failed to be included into ethereum side"); + let start = Instant::now(); while Instant::now() - start < TOTAL_TIMEOUT { match ( @@ -282,6 +384,34 @@ pub async fn test_erc20_deposit( panic!("Failed to bridge ERC20!") } +// Tries up to TOTAL_TIMEOUT time to find a MsgSendToCosmosClaim attestation created in the +// test_erc20_deposit test +async fn check_send_to_cosmos_attestation( + grpc_client: &mut GravityQueryClient, + erc20_address: EthAddress, + receiver: CosmosAddress, + sender: EthAddress, +) { + let start = Instant::now(); + let mut found = false; + loop { + iterate_attestations(grpc_client, &mut |decoded: MsgSendToCosmosClaim| { + let right_contract = decoded.token_contract == erc20_address.to_string(); + let right_destination = decoded.cosmos_receiver == receiver.to_string(); + let right_sender = decoded.ethereum_sender == sender.to_string(); + found = right_contract && right_destination && right_sender; + }) + .await; + if found { + break; + } else if Instant::now() - start > TOTAL_TIMEOUT { + panic!("Could not find the send_to_cosmos attestation we were looking for!"); + } + sleep(Duration::from_secs(5)) + } + info!("Found the expected MsgSendToCosmosClaim attestation"); +} + #[allow(clippy::too_many_arguments)] async fn test_batch( contact: &Contact, @@ -297,6 +427,7 @@ async fn test_batch( .await .expect("Incorrect Gravity Address or otherwise unable to contact Gravity"); + let mut grpc_client = grpc_client.clone(); let dest_cosmos_address = dest_cosmos_private_key .to_address(&contact.get_prefix()) .unwrap(); @@ -315,6 +446,7 @@ async fn test_batch( "Sending {}{} from {} on Cosmos back to Ethereum", amount, token_name, dest_cosmos_address ); + let res = send_to_eth( dest_cosmos_private_key, dest_eth_address, @@ -336,6 +468,7 @@ async fn test_batch( token_name.clone(), get_fee(), contact, + None, ) .await .unwrap(); @@ -344,9 +477,13 @@ async fn test_batch( let requester_address = requester_cosmos_private_key .to_address(&contact.get_prefix()) .unwrap(); - get_oldest_unsigned_transaction_batch(grpc_client, requester_address, contact.get_prefix()) - .await - .expect("Failed to get batch to sign"); + get_oldest_unsigned_transaction_batch( + &mut grpc_client, + requester_address, + contact.get_prefix(), + ) + .await + .expect("Failed to get batch to sign"); let mut current_eth_batch_nonce = get_tx_batch_nonce(gravity_address, erc20_contract, *MINER_ADDRESS, web30) @@ -431,7 +568,7 @@ async fn submit_duplicate_erc20_send( // iterate through all validators and try to send an event with duplicate nonce for k in keys.iter() { - let c_key = k.validator_key; + let c_key = k.orch_key; let res = send_ethereum_claims( contact, c_key, @@ -444,9 +581,11 @@ async fn submit_duplicate_erc20_send( ) .await .unwrap(); - trace!("Submitted duplicate sendToCosmos event: {:?}", res); + info!("Submitted duplicate sendToCosmos event: {:?}", res); } + contact.wait_for_next_block(TOTAL_TIMEOUT).await.unwrap(); + if let Some(end_coin) = check_cosmos_balance("gravity", receiver, contact).await { if start_coin.amount == end_coin.amount && start_coin.denom == end_coin.denom { info!("Successfully failed to duplicate ERC20!"); diff --git a/orchestrator/test_runner/src/happy_path_v2.rs b/orchestrator/test_runner/src/happy_path_v2.rs index ea98a865e..6065733e7 100644 --- a/orchestrator/test_runner/src/happy_path_v2.rs +++ b/orchestrator/test_runner/src/happy_path_v2.rs @@ -8,6 +8,7 @@ use crate::TOTAL_TIMEOUT; use crate::{get_fee, utils::ValidatorKeys}; use clarity::Address as EthAddress; use clarity::Uint256; +use cosmos_gravity::send::TIMEOUT; use cosmos_gravity::send::{send_request_batch, send_to_eth}; use deep_space::coin::Coin; use deep_space::Contact; @@ -112,6 +113,7 @@ pub async fn happy_path_test_v2( token_to_send_to_eth.clone(), get_fee(), contact, + Some(TIMEOUT), ) .await .unwrap(); diff --git a/orchestrator/test_runner/src/main.rs b/orchestrator/test_runner/src/main.rs index fc63b3ee1..8ce8e7633 100644 --- a/orchestrator/test_runner/src/main.rs +++ b/orchestrator/test_runner/src/main.rs @@ -191,7 +191,7 @@ pub async fn main() { return; } else if test_type == "VALSET_STRESS" { info!("Starting Valset update stress test"); - validator_set_stress_test(&web30, &contact, keys, gravity_address).await; + validator_set_stress_test(&web30, grpc_client, &contact, keys, gravity_address).await; return; } else if test_type == "VALSET_REWARDS" { info!("Starting Valset rewards test"); diff --git a/orchestrator/test_runner/src/relay_market.rs b/orchestrator/test_runner/src/relay_market.rs index 570ab71fb..4c9e522cf 100644 --- a/orchestrator/test_runner/src/relay_market.rs +++ b/orchestrator/test_runner/src/relay_market.rs @@ -11,7 +11,7 @@ use crate::{one_eth, MINER_ADDRESS}; use crate::{ADDRESS_PREFIX, OPERATION_TIMEOUT}; use clarity::PrivateKey as EthPrivateKey; use clarity::{Address as EthAddress, Uint256}; -use cosmos_gravity::send::send_to_eth; +use cosmos_gravity::send::{send_to_eth, TIMEOUT}; use cosmos_gravity::{query::get_oldest_unsigned_transaction_batch, send::send_request_batch}; use deep_space::coin::Coin; use deep_space::private_key::PrivateKey as CosmosPrivateKey; @@ -73,7 +73,9 @@ async fn setup_batch_test( gravity_address: EthAddress, erc20_contract: EthAddress, bridge_fee_amount: Uint256, + grpc_client: &mut GravityQueryClient, ) -> (Coin, Uint256, CosmosPrivateKey, Address, EthAddress) { + let mut grpc_client = grpc_client.clone(); // Acquire 10,000 WETH let weth_acquired = web30 .wrap_eth(one_eth() * 10000u16.into(), *MINER_PRIVATE_KEY, None) @@ -118,6 +120,7 @@ async fn setup_batch_test( test_erc20_deposit( web30, contact, + &mut grpc_client, dest_cosmos_address, gravity_address, erc20_contract, @@ -134,6 +137,7 @@ async fn setup_batch_test( test_erc20_deposit( web30, contact, + &mut grpc_client, requester_address, gravity_address, erc20_contract, @@ -187,7 +191,7 @@ async fn wait_for_batch( expect_batch: bool, web30: &Web3, contact: &Contact, - grpc_client: &mut GravityQueryClient, + mut grpc_client: &mut GravityQueryClient, requester_address: Address, erc20_contract: EthAddress, gravity_address: EthAddress, @@ -197,9 +201,13 @@ async fn wait_for_batch( .await .unwrap(); - get_oldest_unsigned_transaction_batch(grpc_client, requester_address, contact.get_prefix()) - .await - .expect("Failed to get batch to sign"); + get_oldest_unsigned_transaction_batch( + &mut grpc_client, + requester_address, + contact.get_prefix(), + ) + .await + .expect("Failed to get batch to sign"); let mut current_eth_batch_nonce = get_tx_batch_nonce(gravity_address, erc20_contract, *MINER_ADDRESS, web30) @@ -253,6 +261,7 @@ async fn test_good_batch( gravity_address, erc20_contract, bridge_fee_amount, + grpc_client, ) .await; @@ -267,6 +276,7 @@ async fn test_good_batch( request_batch_fee.denom.clone(), request_batch_fee, contact, + Some(TIMEOUT), ) .await .unwrap(); @@ -334,6 +344,7 @@ async fn test_bad_batch( gravity_address, erc20_contract, bridge_fee_amount, + grpc_client, ) .await; @@ -348,6 +359,7 @@ async fn test_bad_batch( request_batch_fee.denom.clone(), request_batch_fee, contact, + Some(TIMEOUT), ) .await .unwrap(); diff --git a/orchestrator/test_runner/src/transaction_stress_test.rs b/orchestrator/test_runner/src/transaction_stress_test.rs index fc51892af..df83b9482 100644 --- a/orchestrator/test_runner/src/transaction_stress_test.rs +++ b/orchestrator/test_runner/src/transaction_stress_test.rs @@ -176,9 +176,15 @@ pub async fn transaction_stress_test( for denom in denoms { info!("Requesting batch for {}", denom); - let res = send_request_batch(keys[0].validator_key, denom, get_fee(), contact) - .await - .unwrap(); + let res = send_request_batch( + keys[0].validator_key, + denom, + get_fee(), + contact, + Some(TIMEOUT), + ) + .await + .unwrap(); info!("batch request response is {:?}", res); } diff --git a/orchestrator/test_runner/src/valset_rewards.rs b/orchestrator/test_runner/src/valset_rewards.rs index 9511a61c6..0a369eb60 100644 --- a/orchestrator/test_runner/src/valset_rewards.rs +++ b/orchestrator/test_runner/src/valset_rewards.rs @@ -96,7 +96,7 @@ pub async fn valset_rewards_test( assert_eq!(params.bridge_ethereum_address, gravity_address.to_string()); // trigger a valset update - test_valset_update(web30, contact, &keys, gravity_address).await; + test_valset_update(web30, contact, &mut grpc_client, &keys, gravity_address).await; // check that one of the relayers has footoken now let mut found = false; diff --git a/orchestrator/test_runner/src/valset_stress.rs b/orchestrator/test_runner/src/valset_stress.rs index aee93190c..bb7864bcd 100644 --- a/orchestrator/test_runner/src/valset_stress.rs +++ b/orchestrator/test_runner/src/valset_stress.rs @@ -4,18 +4,22 @@ use crate::utils::start_orchestrators; use crate::utils::ValidatorKeys; use clarity::Address as EthAddress; use deep_space::Contact; +use gravity_proto::gravity::query_client::QueryClient as GravityQueryClient; +use tonic::transport::Channel; use web30::client::Web3; pub async fn validator_set_stress_test( web30: &Web3, + grpc_client: GravityQueryClient, contact: &Contact, keys: Vec, gravity_address: EthAddress, ) { + let mut grpc_client = grpc_client.clone(); let no_relay_market_config = create_default_test_config(); start_orchestrators(keys.clone(), gravity_address, false, no_relay_market_config).await; for _ in 0u32..10 { - test_valset_update(web30, contact, &keys, gravity_address).await; + test_valset_update(web30, contact, &mut grpc_client, &keys, gravity_address).await; } }